版本库结构和文件说明

  版本库依赖支持子目录的层次文件系统。以下只包括版本库根目录下的顶级子目录和少数特定的二级子目录及其中的部分文件的说明。

  • .git Git 目录(可通过 hg-git 同步)
  • .hg Mercurial 目录
  • 3rdparty 第三方依赖项
  • Data 最终用户环境中部署的数据目录
  • Tools 开发使用的(辅助)工具
    • Tools/SHBuild SHBuild 构建工具
    • Tools/Scripts 用于构建和建立 SHBuild 环境的工具脚本
  • YBase 顶级子项目 YBase
  • YFramework 顶级子项目 YFramework
  • YSTest 测试用示例项目目录(项目名为 YSTest ,以实际内容命名的项目名为 YReader )
    • YSTest/Android 示例项目 YReader 的 Android 平台项目(未完成正式支持)
    • YSTest/DS_ARM7 示例项目 YReader 的 ARM7 项目(仅用于 DS 平台,用于生成 ARM7 ELF 二进制映像)
    • YSTest/DS_ARM9 示例项目 YReader 的 ARM9 项目(包括 DS 平台 ARM9 部分,于生成 ARM9 ELF 二进制映像;源代码和其它平台共享)
    • YSTest/DS 示例项目 YReader 的 DS 平台可执行文件项目(仅用于 DS 平台,用于生成 NDS 文件)
    • YSTest/MinGW32 示例项目 YReader 的 MinGW32 平台可执行文件项目(仅用于 MinGW32 平台,用于生成 EXE 文件)
  • build 默认构建目录(可选构建时生成)
  • doc 开发文档
  • doc/vsd 架构示意 Visio 文档
  • test 测试代码目录
  • .gitignore Git 忽略文件
  • .hgeol Mercurial EOL 插件配置文件
  • .hgignore Mercurial 忽略文件
  • .hgtags Mercurial 标签文件
  • CC BY-SA 3.0 legalcode.txt 文档许可证: Creative Commons Legal Code Attribution-ShareAlike 3.0 Unported
  • Doxyfile Doxygen 配置文件
  • FTL.TXT 许可证: The FreeType Project LICENSE
  • gpl-2.0.txt 许可证: GNU GENERAL PUBLIC LICENSE Version 2
  • gpl-3.0.txt 许可证: GNU GENERAL PUBLIC LICENSE Version 3
  • LICENSE.txt 整体许可证
  • LICENSE_HISTORY.txt 整体许可证:历史版本
  • license-fi.txt 许可证: FreeImage Public License - Version 1.0
  • Readme.zh-CN.txt 自述文件
  • YSTest.sln Visual Studio 解决方案文件
  • YSTest.workspace Code::Blocks 工作空间文件

注释 以上布局中的顶级子目录可作为顶级子项目或作为项目模块在开文档中引用,其名称起始使用大写字母,以目录的名称原文作为模块名称。其它构建时生成以外的目录也可被引用,但不使用目录名称作为模块名称。

  顶级子项目或其中的平台子目录中,可包含以下目录:

  • include 可被安装部署的公开头文件
  • source 被构建的源文件

  以下目录会被默认支持的构建配置生成:

  • YDE/ 下以 . 起始的特定宿主平台为子目录名的构建目录是 stage 2 环境下的 YDE 项目的生成文件目录
  • build/ 下以特定的宿主平台为子目录名的默认构建目录,默认配置构建时会创建不同的平台目录,其中的子目录可包括:
    • .stage1 stage 1 环境 构建和生成目录
    • .test 测试项目构建和生成文件目录
    • . 起始的其它 Sysroot 构建目录,用于创建 stage 2 环境的 YSLib 库以及基于 stage 2 环境的 Sysroot 方式的 YSTest 的构建
    • 其它非 Sysroot 的 YSLib 和 YSTest 项目生成文件目录
  • sysroot 使用脚本构建的默认 Sysroot (含 stage 2 环境) 生成目录

文件系统布局约定

  版本库遵循一定的文件系统布局规则。这些规则在这里和一些开发文档中被描述。没有通过这些描述被明确的布局应被视为实现细节,其改变可不被文档描述。

  不论是否是实现细节,特定的路径都可被版本库的忽略文件路径涵盖。

注意 版本库中的文件系统布局和 Sysroot 约定的部署实例的布局相互独立,不适用此处的规则,且布局可能存在差异。

  虽然没有在项目初始指定,版本库中部分目录和文件结构及使用方式与现有的一些约定类似或兼容:

  • 部分文件系统布局和使用符合 cxx-pflR1
    • 顶级子目录 build 符合 build/ 指定的目的和作用。
    • 顶级子项目或其中的平台子目录中的子目录 includesource 对应符合 include/src/ 指定的目的和作用,其使用符合分离放置布局
    • 顶级子目录 test 符合 tests/ 指定的主要目的和作用,但不限于非单元测试。
    • 顶级子目录 Data 符合 data/ 指定的主要目的和作用,但强调最终用户环境,且不适用生成文档的源代码。
    • 顶级子目录 doc 符合 docs/ 指定的目的和作用。
    • 因为不使用版本管理的子模块机制,不使用 libs/extras/ ,符合指定的规则。
  • 部分文件系统布局和使用符合 Jonathan de Boyne Pollard 约定的 slashpackage 内部结构
    • 顶级子项目或其中的平台子目录中的子目录 source 符合指定的目的和作用。
    • 默认构建目录是名为 build 的一级子目录,可能不存在,符合指定的目的和作用。
    • 除构建目录外的文件预期不应被构建过程修改,默认与之兼容。
    • 不要求 source 链接到 build ,与之不兼容。
    • 构建 Sysroot 可能直接链接文件到输出目录,与之不兼容。
    • 仅要求部署过程正常时的部署目标目录的完整性,不要求更新是原子的或可事务性回滚,与之不兼容。

项目结构和特性

  项目内容以模块为单位组织。关于模块的概念及其表示形式,详见 YSLib 项目文档 doc/ProjectRules.txt 。因为特性众多,在此只列出较上层的基本结构,不总是精确到具体模块。

YBase :YFramework 基础库

  详见 doc/YBase.txt

  替代标准库的特性另见 StandardUsing(en-US)

  • YStandardEx : YFramework 标准扩展库
  • LibDefect :标准库修正
  • YTest :YFramework 基础测试库

YFramework : YFramework 框架库

  详见 doc/YFramework.txt

  • CHRLib :字符编码处理库
    • 编码标识
    • 目前支持 UTF-8/UCS-2/UCS-4/GBK ,可扩充
    • 默认编码 UTF-8
  • YCLib : YSLib 基础库
    • Platform :平台定义
    • 平台相关 API 封装
    • 平台相关硬件抽象
    • Win32 专用接口(略)
  • YSLib :YShell 库(主体,暂定)
    • Adaptor :适配器层
      • Configuration : 库配置
      • YReference :智能指针封装(基于 Loki 实现【已移除】/使用 ISO C++11 标准库)
      • 简单的内存调试设施
      • 附加容器(可选 Loki 的 yasli 容器,默认不启用)
      • Anti-Grain Geometry 2.4 移植(修复了一处在 2.5 仍然存在的 bug ),因在 DS 上效率太低所以默认不启用【已移除】
      • Font :字体管理(基于 FreeType 2 实现)
      • Image :平台中立的图像输入和输出(基于 FreeImage 实现)
    • Core : YSLib 核心
    • Service :YSLib 服务
    • UI : YSLib 用户界面
    • NPL
    • Helper :助手库:初始化、宿主支持等

YReader :示例

  • ShlExplorer :文件列表浏览
  • 控件测试:按钮点击、窗口拖曳、FPS (伪)显示等
  • Shell 切换
  • ShlReader :文本浏览
    • 读取并显示文本文件的内容
    • 随机跳转
    • 书签设置、读取和保存
  • HexBrowser:十六进制浏览

构建

  支持使用多种途径进行构建。支持多平台构建。另见 Sysroot 和以下的“轮子列表”章节。

  依赖以模块为单位组织。接口(如公开 API 头文件)不出现循环依赖。

  可通过修改代码以裁剪、定制库实现内部的模块构建(如为了减小编译后的二进制映像体积),但应注意在 YSLib 项目文档中列出的显式依赖规则。未来可能会支持构建时的定制配置工具。

ABI

  目前除 YBase::LibDefect 和具体实现兼容外,不保证 ABI 稳定。

  具体策略详见 YSLib 项目文档 doc/ 下各个库的文档。

API

  对各 API 的说明和注意事项详见 YSLib 项目中的源代码,可构建文档

平台相关 API 注意事项

  • YCLib::MemoryMapping 中 platform::MappedFile 的实现需确保文件内容可访问,否则取指针后,可在之后的操作中引发不可恢复的错误。
    • 在硬件支持 MMU 的平台上,使用内存映射实现。
      • 读取错误产生不可恢复的错误。
      • 因此不支持不可靠的远程文件。
    • 其它平台(当前包括 DS ),使用文件流模拟。
      • platform::MappedFile 初始化失败会直接抛出异常。除非用户代码忽略,可避免引发后续失败(引起未定义行为)。
    • 当前仅支持只读映射。若修改取得的映射指针指向的存储,在使用内存映射实现的平台上也可引发上述行为类似的不可恢复的错误。

标准库使用

  YSLib 对 C++ 标准库具有明确的要求,且仅使用明确的标准库特性

  和 LLVM 编码标准对 C++ 标准库的使用(en-US)类似,YSLib 强调尽可能依赖标准库的公开接口。仅在具有充足理由时不依赖标准库而提供和使用自定义 API (基本上总是因为设计和实现的质量不足够满足需求和以上要求的原因)。

  对标准库特性使用的具体限制见开发说明及 YSLib 项目文档 doc/LanguageConvention.txt 等规则。

  相关的其它原理另见下节。

轮子列表

  本项目发明了一些轮子。为了符合不重复发明轮子的项目内容规则,在发现更好的替代时,其中一些会被逐渐移除。

  但是,其余一些轮子,因为特定的原因,不视为对此规则的违反而得以保留,包括一些在当前实现中使用的和较新版本语言规范中提供的兼容的特性。

  主要包括以下内容:

  • YBase.YStandardEx
    • 为了兼容性需要,一些标准库接口的实现会被保留。但当合适的版本可用时,通过条件包含选择别名声明,优先使用标准库提供的版本。
    • Meta 、TypeTraits 以及其它元编程设施
      • 其它元编程设施因为没有被标准化、风格和可用性问题,提供了 C++14 兼容的元函数和类似 Range-v3Boost.Hana 的实现使用的接口。
    • IntegerSequence
      • 主要接口兼容 C++14 的 std::integer_sequence ,但早于提案 N3493
      • 提供了更丰富的底层接口如 make_peano_sequence
    • Operators
      • 接口类似 Boost.Operators ,但有以下不同:
        • 要求 C++11 支持。
        • 使用代码量较少的紧凑的实现,不支持对不符合标准的编译器的多数实现细节上的变通。
        • 不支持链式模板参数(这是为了兼容不支持偏特化的编译器的变通)。
        • 提供对 noexcept 的支持。
      • 接口类似 The Art of C++ / Operators(原 df.operators )。
      • 除以上列出外,还有以下差异和特性:
        • 操作符模板使用别名而不保证是类。
        • 支持可选的操作符参数,默认推断 constexpr
        • 重载操作符实现为模板友元以支持推断 constexpr 同时允许在派生类中提供显式覆盖实现。
      • 此外,提供部分不在上述类似接口中提供的成员操作符重载。
    • Any
      • 接口类似 Boost.Any ,包括内部非公开的 unsafe_any_cast 作为扩展;此外 any 成员也有一些扩展。
      • 除了 any 外还提供底层实现相关的扩展,用于实现 AnyIterator ,这无法被简单取代
      • Any 的提案最早于 2006 年基于 Boost.Any 提出,未考虑 C++11 特性。此实现早于标准库提案的后续修订版本实现。
      • 现在和 WG21 N4081std::experimental::any 同步,但仍然保持扩展。
      • 使用了小对象优化实现,这也符合后来更新的提案中的建议。
      • 提供 emplace 相关扩展,可避免构造 any 对象或赋值时冗余初始化目标类型的值。
      • 提供 unchecked_* 成员和 unchecked_any_cast 模板扩展,要求参数非空,因为省略检查比对应的检查空值的接口( unchecked_any_cast 对应 unsafe_any_cast )更高效。
    • Optional
      • ISO C++17 的 <optional> 在 ISO C++11 下的移植和扩展。
      • 支持几乎所有特性,除 operator-> 因为核心语言特性限制不总是支持结果是常量表达式。
      • 支持少量扩展接口: make_optional_inplaceref_opt
    • Map
      • ISO C++17 的 <map> 在 ISO C++11 下的移植和扩展。
      • 支持不完整键类型,不依赖特定扩展(如 libstdc++ 的 std::map)。
    • Invoke
      • 提供 std::invoke 的替代。
    • Apply
      • 提供 std::apply 的替代。
    • Function
      • 提供 std::function 的替代。
    • Rational
      • 类模板 fixed_point 和提案 P0037R1 中的有相似之处,但模板参数类型更明确,且提出较早。
    • 一些非直接的(以同名接口一一替代的)标准库替代接口
      • 减少了标准库对应的限制,提升了易用性。
      • 不一定和标准库的对应功能的 API 同名。
      • lref 部分取代 std::reference_wrapper (涉及 std::bind 的使用无法取代)。
      • mapped_setystdex::map 模拟 std::set
        • 不要求键类型保持 const 。这意味着(和 C++98/03 类似)只要不影响比较操作的等价关系,元素可以使用无 mutable 修饰的成员而保持 const 类型检查。
        • 使用 ADL set_value_move 优化插入等操作,允许转移值。
        • 在 C++11 下即支持泛型查询接口。
        • 因为使用 ystdex::map ,支持不完整键类型。
    • 一些通常典型地用于标准库内部实现的接口
      • 实际上也适于被用户代码使用。
      • has_mem_valuehas_nested_allocatorenable_if_transparent_t 等检查类型要求的元编程设施。
      • search_map 提供关联容器查找,适合实现 map 等的 operator[]try_emplace 等设施。
        • 支持迭代器提示参数。使用比当前(2016-03) 最新开发版本的 libstdc++ 更紧凑的实现(而 libc++ 对 map::try_emplace,用 lower_bound 近似,也包括对用户代码提供提示参数的情况(直接忽略提示),后者尽管满足复杂度要求但特定情况下容易更低效。
    • 其它可在 C++11 下使用的标准库扩展
      • ISO/IEC TS 19568:2015 C++ Extensions for Library Fundamentals (最终草案 N4480) 以及 ISO/IEC DTS 19568 C++ Extensions for Library Fundamentals, Version 2 (草案 N4564)的一些接口在 C++11 下的实现和 YStandardEx 扩展。
        • 提供元函数 and_or_not_
          • 是早于提案 P0013R0 的实现。
          • 比原始提案及 libstdc++ 中使用的实现更简单。
          • 以别名模板的形式支持 P0013R1
        • 函数模板 apply 利用更加强大(投影到不同参数位置进行调用)的 call_projection 实现,而非直接基于 integer_sequence
        • 类模板 optional
        • any 大体兼容这里的接口规范。
        • 类模板 string_view
        • 类模板 observer_ptr
        • 部分比较操作使用 Operators 实现,保证一般预期的可用性同时简化实现及改善编译性能,但不完全和规范一致。
      • 函数模板 destroy 是早于提案 P0040R0 的实现。
        • 使用不同的参数形式被重命名为 destruct 等模板。
        • 实现和 P0040R2 兼容的相关接口。
      • 类型特征 unwrap_reference 早于提案 P0318R0 提供,功能近似。
  • YFramework
    • 一些接口存在第三方的高效实现,但不足以同时在性能和功能上取代现有接口和实现。(以下性能测试因为实际环境基准问题当前仅用于内部测试,未正式支持。)
    • CHRLib
      • 提供的 UTF-8 解码实现之一在主要支持平台(即 MinGW32 )上实测为当前已知最快的实现。
        • 第二快的是 RapidJSON 。虽然同样使用状态转移查找表,它使用刻意避免分支判断的实现机制,使用的表较大而对缓存可能不友好,导致在典型的实现中反而不一定更快。此外实测表明,使用 GCC 的 __attribute__((flatten)) 即能明显影响这里的性能,程度和算法优化相比无法忽视。
        • 其它朴素实现都明显落后于使用状态查找表算法的性能。
    • YSLib.Core.YEvent
      • 在不进行体系结构和 ABI 相关优化的限制前提下,YSLib::GEvent 的性能超过这里的除了 jl_signal 所有实现。而后者基于特定实现的 ABI 进行了较为复杂的优化。(待定:整合新的测试。)
      • 除了没有 Boost.Signal2 的线程安全和定制返回类型策略的接口外,所有功能都不弱于上述测试中的例子。
      • 此外,基于 ystdex::make_expanded 提供允许省略未使用的参数这个实用特性,是以上测试用例都不具备的。事实上,尚没有已知的 C++ 库中提供类似的特性。其它语言可能提供类似的特性简化 GUI 开发,如 {x:Bind} ,但实现原理上,其运行时性能不可能超过此处的方式(静态语言在翻译时确定参数列表)。