nlib
nlibメインページ

Windows, Linux, FreeBSD, OS X, Cygwin及び任天堂の開発環境に対応したライブラリの集合です。

nlibについて

nlibはWindows, Linux, FreeBSD, OS X, Cygwin及び任天堂の開発環境に対して同一のI/Fを利用したプログラミングが可能な、ユーザーランド上で動作するライブラリ群を提供することを目的として開発されています。 開発はsoftware centricに行われ、適切で現実的なコーディングルール(nlibのコーディングルール)と個別の開発環境からの独立性が確保されたI/Fと実装によって、複数の開発環境に対して同時並行的に高い品質と性能及び信頼性を維持しつつ行われることにフォーカスしています。

nlibが実装している機能

主に以下のような機能が実装されています。
  • XML及びJSONの読み書き
  • 高効率なメモリアロケータ
  • googletest互換のテストフレームワーク
  • SSE4.2/NEON両対応のコード開発を可能とするラッパーライブラリ。4x4行列及び3次元,4次元ベクトルに対する各種計算のサポートを含みます。
  • キーワード検索等のための簡潔データ構造ライブラリ
  • UTF-8の読み書きや正規化, UTF-16/UTF-32との変換
  • スレッド, ミューテックス, 条件変数, TLS, バリア, リードライトロック, アトミック変数, 等
  • システムメモリの取得と解放, 時刻の取得, ファイルの読み書き, 等
  • 基本的なロックフリーデータ構造とアルゴリズム
  • その他、多数のプラットフォームや複数のコンパイラに対応するための基底となるCリンケージの関数群やマクロ定義

nlibが動作する環境

nlibは現在以下の環境でコンパイル及び動作確認が行われています。
Platform Library types Remarks
Windows Visual Studio 2017 64bit static library, DLL Version 15.3
Visual Studio 2015 64bit static library, DLL Update 3
32bit static library
Visual Studio 2013 64bit static library, DLL Update 5, Express Edition is available
32bit static library
Cygwin 64bit static library gcc 6.4.0, newlib, libstdc++
Bash on Ubuntu on Windows 64bit shared library Ubuntu 16.04
Linux Ubuntu 17.04 64bit shared library gcc 6.3.0, clang 4.0.0, glibc, libstdc++, https://app.vagrantup.com/bento/
Ubuntu 16.04 LTS 64bit gcc 5.3.1, clang 3.8, glibc, libstdc++, https://app.vagrantup.com/bento/
Ubuntu 14.04 LTS 64bit gcc 4.8.4, clang 3.4, glibc, libstdc++, https://app.vagrantup.com/ubuntu/
32bit
CentOS 7 (v1708.01) 64bit devtoolset-4, gcc 5.3.1, glibc, libstdc++, https://app.vagrantup.com/centos/
Fedora 26 64bit gcc 7.1.1, clang 4.0, glibc, libstdc++. https://app.vagrantup.com/fedora/
Alpine 3.6.0 64bit gcc 6.3.0, musl libc, libstdc++, https://app.vagrantup.com/maier
FreeBSD FreeBSD 11.1 64bit shared library clang 4.0, BSD libc, libc++, https://app.vagrantup.com/freebsd/
macOS macOS 10.13 (High Sierra) 64bit shared library Xcode 9.0
CTR CTR-SDK 11.5 32bit static library CTR_SDK-11_5_2-20161105-ja.zip
armcc_4_1_nintendo-b1454-20150227.zip
Cafe CafeSDK 2.13.01 32bit static library cafe_sdk-2_13_01-20150728.zip
MULTI-5_3_26-20150918.zip
コンパイラのバージョン等により、適宜C++11の機能を利用してコンパイルされるようになっています(nlibで利用しているC++11/14/17の機能)。

nlibのサポート方針等

サポート方法については、パッケージのリリース元にお問い合わせください。 FAQ 等も併せてお読みください。 なお、今後の開発予定やリリース予定日のドキュメント等は作成や公開されずに、現在の実装について本ドキュメント及びサンプルで説明される形となります。 サポート及びバグフィックスはその時点での最新バージョンに対して行われます。 特定のプロジェクトに対してのみの特別バージョン等の提供や特別扱いのサポートが行われることはありません。 これらは開発チームの規模を最小限に抑えるために必要なルールとなっています。
また、やむを得ず互換性が失われるような変更が予告なしに行われる場合もあります。 ご了承ください。
利用の際には利用する機能について受け入れテスト等で、期待通りの動作をするか、速度は十分にでるか、メモリ消費量等は許容範囲内かを事前に確認しておくのがよいでしょう。 受け入れテストを作成しておくことは、nlibのアップデートによるトラブルを回避するためにも役に立ちます。 そのような受け入れテストの作成にtestingライブラリを利用するのはよい考えです。
バグ報告は可能であれば、再現コードをnn::nlib::testing形式のテストコードとして記述してそれを報告に含めると迅速に修正されるかもしれません。

nlibのパッケージに関する説明

パッケージによって収録されているライブラリや対応プラットフォームが異なりますのでご注意ください。

ディレクトリ構成

以下のような構成になっています。
    ├── bin
    │   └── cmake                 # Command-line tools
    ├── cmake                      # Common Cmake scripts
    ├── documents-ja(documents-en)
    │   └── API                   # Reference Manual
    │       ├── html              # HTML version of the Reference Manual
    │       └── searchdata.xml    # Search index
    ├── include                    # Include files (in `system/include` for Cafe)
    │   ├── nn
    │   │   └── nlib
    │   │       ├── exi
    │   │       ├── heap
    │   │       ├── msgpack
    │   │       │   └── jsonrpc
    │   │       ├── oss
    │   │       ├── simd
    │   │       ├── succinct
    │   │       ├── testing
    │   │       ├── threading
    │   │       └── unicode
    │   ├── lz4.h
    │   ├── lz4hc.h
    │   ├── lz4frame.h
    │   ├── sqlite3.h
    │   └── sqlite3ext.h
    ├── lib                        # Platform-specific library files (`system/lib` for Cafe, `libraries` for CTR)
    ├── samples                    # Source code for samples
    │  ├── cmake
    │  └── sources
    │      ├── exi
    │      ├── heap
    │      ├── misc
    │      ├── msgpack
    │      ├── oss
    │      ├── succinct
    │      └── testing
    └── setup
        ├── setup-bash-ubuntu-windows-tools.sh
        ├── setup-cygwin-tools.sh
        ├── setup-msvc-libraries.ps1
        └── setup-osx-tools.sh

個別プラットフォームに関する説明事項

各種ライブラリの説明

libnライブラリ(libn.a, libn.so, n-vc120amd64.lib, n-vc120dllamd64.dll等)
このライブラリではプラットフォーム間の差異を吸収しているCリンケージを持つ関数群で構成されます。
具体的には以下のような関数を含みます。
miscライブラリ(libnx_misc.a, libnx_misc.so, nx_misc-vc120amd64.lib, nx_misc-vc120dllamd64.dll等)
このライブラリは、比較的小規模なクラスで構成されたクラスライブラリです。 多くのプログラムで使うであろう機能が実装されています。
具体的には以下のものを含みます。
  • InputStream, OutputStreamを基底とする各種ストリームを扱うためのクラス群
  • UTF-8文字列をストリームからvalidationしつつ読み書きするためのクラス(TextReader, TextWriter)
  • バイナリデータをストリームから読み書きするためのクラス(BinaryReader, BinaryWriter)
  • ユニコードを扱うためのクラス
  • スレッドを扱うためのクラスや関数群
  • 日時や時間情報を扱うためのクラスや関数群
    • 日時を加減算したり、日付文字列(RFC2822, W3CDTF)をパースしたり作成するクラス(DateTime, TimeSpan)
  • URIを扱うためのクラスや関数群
    • URIパーサー(Uri)
    • URI Template(RFC6570) を処理するためのクラス(UriTemplate)
    • 環境ごとに異なる文字列となることの多いファイルパスをURI文字列に標準化するためのクラス(NativePathMapper)
  • 非同期ファイルアクセスを行うためのクラス(threading::AsyncFileIo)
  • 基本的なロックフリーデータ構造とアルゴリズム
  • 各種ガシェットクラス
    • std::unique_ptr代替クラス(UniquePtr)。C++11ではstd::unique_ptrtypedefされる。
    • シングルトンクラス(Singleton, SimpleSingleton)
    • 拡張時にメモリの解放(と要素のコピー)が必要とならないstd::vector類似クラス(Nlist)
    • コマンドライン文字列を解析するためのクラス(Nflags)
    • ハンドル作成支援クラス(HandleMaker)
名前空間はnn::nlib, nn::nlib::unicode, nn::nlib::threadingです。
exiライブラリ(libnx_exi.a, libnx_exi.so, nx_exi-vc120amd64.lib, nx_exi-vc120dllamd64.dll等)
バイナリXMLを読み書きするライブラリです。テキストのXMLを読み書きすることも可能です。 XML名前空間をサポートしていて、プログラミングの簡単なPull parsing APIを備えています。
名前空間はnn::nlib::exiです。
heapライブラリ(libnx_heap.a, libnx_heap.so, nx_heap.lib, nx_heap-vc120dllamd64.dll等)
マルチスレッドでのメモリの確保と解放に関して最適化されたヒープライブラリで、nmalloc()/nfree()(とそれらを実装するheap::CachedHeap, heap::CentralHeap)は、多段のフリーリストを利用することでフラグメンテーションの抑制を行い、性能の劣化を抑えています。 また、小さいサイズのメモリの場合は各スレッド毎にキャッシュを保持することにより、ロックをかけずにメモリの割り当てと解放が可能になっていてマルチスレッドでの性能劣化を抑制しています。 フリーリスト内のポインタはマングルされているか割り当て状態がチェックされていて、外部からのメモリの書き換えによる不正利用が行いにくいように実装されています。
名前空間はnn::nlib::heap及びグローバル名前空間(Cリンケージの関数)です。
succinctライブラリ(libnx_succinct.a, libnx_succinct.so, nx_succinct-vc120amd64.lib, nx_succinct-vc120dllamd64.dll等)
簡潔データ構造を扱うためのライブラリです。 簡潔データ構造とは、圧縮したままの状態で中身の検索を行うことができるデータ構造とお考えください。
succinctライブラリは以下のものを含みます。
  • 各種簡潔ベクトルクラスの実装
  • 括弧列(Balanced Parentheses)を実装したクラス
  • LOUDS(Level-Order Unary Degree Sequence)を実装したクラス
  • Trieの実装
  • Aho Corasick法のための高圧縮なインデックスを作成し、文字列の検索に利用するためのクラス
名前空間はnn::nlib::succinctです。
msgpackライブラリ(libnx_msgpack.a, libnx_msgpack.so, nx_msgpack-vc120amd64.lib, nx_msgpack-vc120dllamd64.dll等)
MessagePackとJSONを読み書きするためのライブラリです。 CSVをパースするクラスも含まれています。
msgpackライブラリは以下のものを含みます。
  • ストリームからJSONを読み書きするためのクラス
  • ストリームからmsgpackを読み書きするためのクラス
  • メモリ上のmsgpackを高速に解釈するためのクラス
  • CSVを読み込むためのクラス
  • 読み込んだJSONやmsgpack、及びCSVのデータを保持するためのクラス
  • JSON-RPCのための実装
名前空間はnn::nlib::msgpackです。
testingライブラリ(libnx_testing.a, libnx_testing.so, nx_testing-vc120amd64.lib, nx_testing-vc120dllamd64.dll等)
移植性の高いテストコードを記述するためのライブラリです。 googletestで書かれたテストとある程度のソースコード互換性を持つテストフレームワークです。
名前空間はnn::nlib::testing(googletestとの互換性のためtesting名前空間にエイリアスされている)です。miscライブラリに依存します。
ossライブラリ(libnx_oss_bsdiff.a, libnx_oss_sqlite3.a, libnx_oss_lz4.a等)
オープンソース・ソフトウェア(OSS)のコード、及びOSSから派生したコード、及びOSSにアクセスするためのコードが格納されます。 利用する場合にはOSSライセンスの処理が必要となります。
現在は、以下のライブラリが含まれています。それぞれが別々のライブラリファイルとしてビルドされています。
  • bsdiffbzlib2ではなくzlibを使うように改変してライブラリ化したもの、及びそのコマンドラインプログラム
  • SQLite3nlibが提供しているI/Fを利用して動作するように改変したもの、及びそのコマンドラインシェル
  • LZ4zlibに比べて圧縮では約20倍、展開では約5倍の速度で動作するアルゴリズムです。
名前空間はnn::nlib::oss及びグローバル名前空間(Cリンケージの関数)です。
simdライブラリ(大半がインライン関数でmiscライブラリに含まれる)
SIMD命令を用いることにより、プログラムを大幅に高速化することが可能です。 simdライブラリは、SSE4.2とNEONに両対応したコードを記述するためのライブラリです。
各種整数と単精度浮動小数点数の計算に対応していて、高速な演算を行うコードを記述可能です。
なお、単精度浮動小数点数の計算については、SSEやNEONに対応していない環境でも利用することが可能です。
CAFEにおいてはpaired singleを利用するように最適化されています。
つまり、同一のコードを書くことで、下記の環境に対応することができます。
  • x86系プロセッサではSSE4.2を利用した高速化が適用されたコードにコンパイルされます。
  • NEONをサポートするプロセッサではNEONを利用した高速化が適用されたコードにコンパイルされます。
  • CAFEではpaired singleを利用した高速化が適用されたコードにコンパイルされます(浮動小数点演算のみ, 4次元ベクトル等を値返しするI/FのためCAFE-SDKの行列計算等よりかなり遅い)。
  • CTRではgenericなコードがコンパイルされます(浮動小数点演算のみ)。
名前空間はnn::nlib::simdです。

nlibのライブラリ間の依存関係

nlibの各ライブラリ間の依存関係は下図のようになります。

dot_inline_dotgraph_32.png

nlibで利用しているC++11/14/17の機能

nlibではコンパイラの種類やバージョンによって、C++11/14/17の機能を利用してコンパイルされています。 コンパイラがそれらの機能をサポートしているかどうかは、コンパイラのバージョンやC++14から推奨となったFeature Testing Macrosを用いて判断しています。
C++11の機能 識別用マクロ C++03互換用マクロやtypedef等 Visual Studio gcc
Rvalue references __cpp_rvalue_references なし 2010 4.3
Variadic templates __cpp_variadic_templates なし 2013 4.7
Static assertions __cpp_static_assert NLIB_STATIC_ASSERT() 2010 4.3
Null pointer constant NLIB_CXX11_NULL_POINTER_CONSTANT nn::nlib::nullptr, nn::nlib::nullptr_t 2010 4.6
Deleted functions NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS NLIB_DISALLOW_COPY_AND_ASSIGN() 2015 4.4
Explicit conversion operators NLIB_CXX11_EXPLICIT_CONVERSION_OPERATORS NLIB_SAFE_BOOL() 2013 4.6
Alias templates __cpp_alias_templates なし 2013 4.7
constexpr __cpp_constexpr NLIB_CEXPR 2015 4.7
char16_t, char32_t __cpp_unicode_characters nlib_utf16_t, nlib_utf32_t 2015 4.4
alignas NLIB_CXX11_ALIGNMENT_SUPPORT NLIB_ALIGNAS() 2015 4.8
Explicit virtual overrides NLIB_CXX11_EXPLICIT_VIRTUAL_OVERRIDES NLIB_OVERRIDE 2012 4.7
final NLIB_CXX11_EXPLICIT_VIRTUAL_OVERRIDES NLIB_FINAL 2012 4.7
noexcept NLIB_CXX11_NOEXCEPT NLIB_NOEXCEPT 2015 4.6
Range-based for __cpp_range_based_for なし 2012 4.6
lambda __cpp_lambdas なし 2012 4.7
Delegating constructors __cpp_delegating_constructors なし 2013 4.7
std::unique_ptr NLIB_CXX11_UNIQUEPTR nn::nlib::UniquePtr 2013 4.7
#include <random> NLIB_CXX11_STDLIB_RANDOM なし 2013 4.8
#include <chrono> NLIB_CXX11_STDLIB_CHRONO nn::nlib::DateTime との変換 2012 4.7
#include <atomic> NLIB_CXX11_STDLIB_ATOMIC NLIB_MEMORY_ORDER_SEQ_CST2012 4.8
#include <array> NLIB_CXX11_STDLIB_ARRAY なし 2012 4.5
#include <unordered_map>
#include <unordered_set>
NLIB_CXX11_STDLIB_UNORDERED なし 2012 4.5
#include <tuple> NLIB_CXX11_STDLIB_TUPLE なし 2012 4.5

nlibのコーディングルール

nlibの基本的なコーディングルール

nlibのコーディングルールは、(最新の)Google C++ Style Guide(若干古いが日本語訳)に若干の変更と緩和を行ったものになっています。
Google C++ Style Guideを利用する理由については以下の点を挙げることが可能です。
  • コーディングルールの文書にアクセスしやすい。公式ではないにしろ翻訳もされている。
  • ゲーム業界での一般的なコーディングルールと同様にC++例外とRTTIの利用を禁止している。
  • 今までに継続的に更新されている。
  • 更新毎のコーディングルールの変化は穏当なもので、突然全く変わってしまう、といったことがなかった。
  • 5年後においてもメンテナンスされていることが期待できる。
変更点及び緩和点は以下のとおりです。
コーディングルール Google C++ Style Guide nlib
行の長さ 80 100
インデント 2 4
パラメータの順序 入力が先で出力が後 出力が先で入力が後
デフォルト引数 原則として禁止 以下の場合以外では利用可能。
  • コンストラクタ。デフォルト値により引数が1つになるまで省略可能な場合に問題を引き起こすため。
  • 仮想関数。オーバーライドした関数でデフォルト引数が違う場合に問題を引き起こすため。
  • 関数ポインタとして利用されうる場合。コーディングに混乱を引き起こすため。
ファイル名 file_name.cc FileName.cpp(サンプルではfile_name.cpp)
インクルードガード 更に#pragma onceをつける(Visual Studioでのコンパイル高速化のため)
Boostの利用 ライブラリ本体では利用しない(テスト等では自由)
アクセサ関数名 get_xyz() / set_xyz() GetXyz() / SetXyz()
参照型の引数 非const参照は禁止 nlibでは以下については例外的に非const参照を利用可能にしている
  • std::swap()の特殊化を行う場合
  • C++03でmove semanticsを真似するコード
  • 機能が単純なクラス。例えばScopedLockクラスのようにロックを保持するだけの機能を持っているクラス。
  • nn::nlib::UniquePtrを引数で渡す場合(値渡しは非効率だし、UniquePtrへのポインタを渡すというのも変である)
C++11の利用 ヘッダ、及びソースコードはC++03のコンパイラでもコンパイルできるようにしておくこと。
  • C++11を使うなということではない。ムーブコンストラクタ, range based for, Explicit virtual overrides, Explicit conversion operators 等は積極的にサポートするべきである。
  • 可能ならばマクロ等を利用して同一のソースコードがコンパイルされるようにすること。不可能な場合でも、C++03から利用できる同等の機能を実装しておくこと。
nullptr C++11なら利用 C++03が使われているうちは、原則としてnullptr_tnullptrを使わないこと
  • C++03でnullptrを実現するためのnullptrイディオムは、複数のライブラリで定義されている場合にエラーとなるので、グローバル名前空間で定義できない
  • nlibでは、C++03の場合は nn::nlib::nullptr_t, nn::nlib::nullptrとして定義されている
  • 紛らわしいオーバーロードを使わないことで、nullptrが必要となる状況の殆どは回避できるはずである
constexpr C++11なら利用 当分の間、constexprの利用は自明なケース以外では見合わせること
  • 残念ながら、constexprを積極的に利用したコードは、コンパイラ毎の挙動の違いによりコンパイルエラーを多発させる要因になるという移植性におけるデメリットが存在する。
  • 自明なケースとは、空の定数オブジェクト, 定数を設定するだけの単純なコンストラクタ等のconstexprをサポートするどのコンパイラでもコンパイルが通ることを期待できる場合のことである。
コメント
  • 翻訳の手間を考慮すると、公開ヘッダには非ASCII文字(非英語)のコメントを書くべきではない(翻訳される可能性が全くない場合は考慮の必要はない)。
  • 詳細なコメントを書きたい場合は、ソースコードファイルか、リファレンス・マニュアルに記述すること。
  • doxygenコメントを公開ヘッダに書いてはいけない。ドキュメントの変更による再コンパイルという問題があるし、翻訳の手間を増大させる。 ライブラリ毎にmanual_ja.hmanual_en.hといったファイルを用意してそこに記述すべきである。
  • リファレンス・マニュアル内の改行は文単位で行い、文の途中で改行してはならない。これは、翻訳支援ソフトの都合によるものである。 このことは、前述の1行100桁制限よりも優先される必要がある。

コーディングスタイルのチェックと矯正

コーディングスタイルは、cpplintを用いて簡単にチェックすることができます。
警告基準は以下のように若干緩和されています。
  • --linelength=100 を指定して、1行は100行以内であるとしている。
  • cpplintのlegal/copyright, build/include_alpha, whitespace/newlineによる警告は抑制されている。
  • std::swap()の利用に際してヘッダalgorithmのインクルードは要求されないよう緩和している。
Makefileに以下のようなルールを書いておけば、手軽にチェックをかけることができます。
cpplint:
-./cpplint.py --linelength=100 \
$(shell find ./include/ -path "*.h") \
$(shell find ./sources/ -path "*.cpp" -or -path "*.h") 2>&1 | tee cpplint.log
また、nlibclang-checkによるソースコードの検査にも対応しています。 cmakeでMakefileを生成すると、compile_commands.jsonというファイルが一緒に作成され、clang-checkはこれを利用して動作します。
詳しくは、clangマニュアルのJSON Compilation Database Format Specification を御覧ください。

コーディングスタイルの自動整形

clang-formatを用いるとインデント等を好みの方法に統一することが可能です。 nlibで用いている設定が .clang-formatファイル(clang3.5用です)としてnlibのパッケージに含まれていて利用することが可能です。 まず、clang-formatで一括してソースコードの大まかな変換を行い、cpplint.pyでより細かい日常的なチェックを行うことをおすすめします。

コンパイル時の警告の設定等

複数のコンパイラや実行環境でテストすることにより、コードの品質を向上させることが可能です。 各コンパイラで比較的厳しめのワーニングレベルを設定します。
  • Visual Studio 2013 以降の全てのバージョンでコンパイルを成功させること。/W4 オプションを利用した上で原則として警告を無くすこと。
    • pragmaによる警告の抑制は容認される。
    • 常に最新のUpdateを適用し、コードで_MSC_FULL_VERをチェックすること。
    • 定期的にVisual Studioのコード分析を利用して警告を減らしておくこと。
  • cygwin(32bit)及びUbuntuにおいてバイナリパッケージで手に入る最新版のgcc, clangでコンパイルを成功させること。-Wall -Wextraを利用した上で原則として警告を無くすこと。
    • cygwinは常に最新にしておくこと。 cygwinのアップデートでビルド動作がおかしくなった場合はビルドスクリプトの方を修正すること。
    • pragmaによる警告の抑制は容認される。
    • -Wstack-usage=65536 を利用し、スタックを使い過ぎないようにすること。
    • -fstack-protector を利用すること。
  • CAFEの開発環境で警告なしにコンパイルを成功させること。
  • CTRの開発環境でコンパイルを成功させること。
  • 各種64bit環境でも同様にコンパイルが成功することが望ましい。
  • doxygenの警告もなくしておくこと。
cpplint.pyの警告をゼロにし、各種環境でのコンパイルとテストを通すことがnlibの基本的なリリース基準になっています。

追加のルールや慣習

  • 原則として、Platform.hで定義される関数の宣言や実装以外のコードは利用する可能性のある全環境でコンパイルできるコードで記述されている必要がある。ただしSIMD命令等によって機種別に最適化されたコードが含まれることは容認される。
  • NLIB_FINAL, NLIB_OVERRIDE等のマクロやtypedefを利用してC++11の機能を安全に導入し、C++11やC++14以降への連続的な移行を可能にすること。
  • エラー値は可能であればPOSIX.1 2008のエラーコードを利用し、エラー値の型はerrno_tとすること(https://www.jpcert.or.jp/sc-rules/c-dcl09-c.html)。
    これは、
    typedef int errno_t;
    とされていて、エラー値であることが分かりやすくなっている。
    • POSIX.1 2008のエラーコードの値は十分に小さい整数値なので、ARMのようなプロセッサで効率的に即値ロードできる。
  • 例外・RTTIを利用せずに実装しなくてはならないが、nlibを利用する側のコードがこれらを利用する場合を想定したコードを記述すること(例外安全性等)。
  • malloc(), free()等はnlib_malloc(), nlib_free()等を利用すること。
  • newは、new (std::nothrow)を利用すること。
  • ライブラリ内部でグローバルのnewをオーバーロードしてはならない。
    • このオーバーロードは依存関係のないはずの他のライブラリの挙動に影響を与えてしまうのでやってはならない。
  • マルチバイト文字列はASCII文字列かUTF-8文字列のどちらかにすること。
    • WindowsにおいてもUTF-8で渡す実装でなくてはならない。パス文字列やnlib_printf()に渡す文字列はnlib内部でUTF-16に変換された上でWin32 APIに渡されている。
    • コマンドライン引数処理(Nflags)は例外
  • char型が符号付きでも符号無しでも正常に動作するようにしておくこと。
    • signed charを用いれば明示的に符号付きの値として扱うことができる。
  • wchar_tに関してはwchar_tが16bitの場合はUTF-16として、32bitの場合はUTF-32としてサポートすること。
    • NLIB_WCHAR_SIZEが2か4のいずれかに定義されるのでそれで判断することができる。
  • UTF-16文字の型には nlib_utf16_t, UTF-32文字の型には nlib_utf32_tを利用すること。
    • これらはC++11の場合はそれぞれ、char16_t, char32_ttypedefとなる。
  • 原則としてUTF-16やUTF-32より、UTF-8を優先すること。
    • UTF-8の方がメモリ消費量が少なく、複数プラットフォームへの対応が容易である。
    • サロゲートペアや結合文字の存在により、UTF-16やUTF-32を利用しても必ずしも1文字を固定長で表現することができない。
    • nlib_strcplen_ex()を使うことにより、validationを行いつつコードポイント数とバイト長を同時に求めることができる。更にSIMDがサポートされている場合にはこの動作をより高速に行うことができる。
  • ムーブコンストラクタ、ムーブ代入演算子を定義する場合には、NLIB_CXX11_RVALUE_REFERENCESで切り分けられたコード内での定義の他に、C++03でも同等の機能を実現できるよう、以下のようなメンバ関数を定義しなければならない。
    Type::Type(Type& rhs, ::nn::nlib::move_tag); // ムーブコンストラクタと同じ動作をさせる。
    Type& Type::assign(Type& rhs, ::nn::nlib::move_tag); // ムーブ代入演算子と同じ動作をさせる。
    boost::moveのような素晴らしい手法も存在するが、結局完全な互換性は達成できないのでこの手法は利用しない。
  • type_traitsの利用は慎重に行うこと。C++11のこの機能はコンパイラやそのバージョンによってバグがあったり実装が抜けていたり、といったことがある。 nn/nlib/TypeTraits.h に一応のラップが行われているが、やむを得ない場合にのみ利用すること。
  • Non-copyable Mixinを使わないこと。
    • 代わりに、NLIB_DISALLOW_COPY_AND_ASSIGN()を使うこと。
    • 継承階層を増やすことが、ソースコードの解析プログラムやドキュメンテーションシステムに悪影響を与えることがある。
  • C標準ライブラリのヘッダは .h形式のものをインクルードすること。理由は以下の2つ。
    • C++標準ライブラリのヘッダが壊れているような状況に対応するため
    • nn/nlib/Platform.hはCコンパイラでコンパイル可能である必要があることから、xxx.h形式のヘッダをインクルードする必要があるため、nlib内部でxxx.h形式とcxxx形式の両方の形式でインクルードすることに起因するコード上の混乱を抑制するため。
  • テストをgoogletest形式で記述して、どのプラットフォームでも単体テストが実行されている状態にしておくこと。
    • 特定のプラットフォーム向けの実装のバグや、特定の環境でしか見つからないバグを見つけることが容易になる。
    • どのプラットフォームでも実行する共通のテストと、PCのみで実行するテストを分けておくとよい。
      • PCのようなパワーのある環境では、ストレスをかけるテストや総当りのテストが記述しやすい。
      • PC環境ではOSSをテストプログラムで利用することが容易で、便利なことがある。
      • Windows環境ではDirectX等をテストプログラムで使うことができ、便利なことがある。
      • googletestが動作しない環境では、 testingライブラリを利用することが可能である。
      • gccでコンパイルしている場合は、gcovrを使うことでテストのカバレッジを自動計測することができる。
  • リファレンス・マニュアルはdoxygen形式で記述すること。
    • doxygenは継続的に改良されていて、5年後においても改良されつつ存在していることが期待できるドキュメンテーションシステムであるから。
    • doxygenコメントは各インクルードディレクトリにmanual.hというファイルを配置して、そこに記述すること。英語版のマニュアルの場合はmanual_en.hである。こうすることで複数言語版を同じレポジトリで管理することができる。
  • 可能であればcmakeでビルドできるようにすること。
    • cmakeはWindowsとLinuxの両方で動作するようなC/C++のコードを記述する場合において代表的な選択肢となっている。

nlibにおけるCMakeのサポート

CMakeはnlibのサンプルのコンパイルやnlibそのもののコンパイルに利用されていて、nlibのユーザーが利用することが可能です。 CMakeLists.txtから、cmake/common.cmakeをインクルードし、FIND_PACKAGE()でnlib内のライブラリを組み込んで利用します。 samples/cmake/CMakeLists.txtを参考にすることができます。
nlibが提供するCMakeサポート用スクリプトは以下のコンパイラでの動作を確認しています。
  • Visual Studioの各バージョン
  • Cygwinでのgcc
  • Bash on Ubuntu on Windowsでのgcc, clang
  • Linuxでのgcc, clang
  • FreeBSDでのclang
  • macOSでのclang
  • CAFEでのghs(cmake/toolchain-cafe-ninja.cmakeを利用)。Windows版のCMakeとninja(https://ninja-build.org/)が必要です。
  • CTRでのarmcc(cmake/toolchain-ctr-ninja.cmakeを利用)。Windows版のCMakeとninja(https://ninja-build.org/)が必要です。

FAQ

このセクションでは、nlibを利用する際によく遭遇する状況と対処法について説明します。
new/deleteのオーバーロード
nlibはメモリの確保にはnew (std::nothrow)を利用しています。 アプリケーション、又は他のライブラリでnew/deleteをオーバーロードする場合には、operator new(size_t, const std::nothrow_t&)もオーバーロードする必要があります。
詳しくはheap_replace_mallocサンプルを御覧ください。
malloc等の置き換え
nlibmalloc, freeを直接使うことはしていません。代わりにnlib_malloc(), nlib_free()等を利用します。 これらの関数はweak関数として定義されていてユーザーが定義することで置き換え可能です。
ユーザー定義のヒープを利用したい場合にはこれらの関数を置き換える必要があります。 必要なのは、以下の関数です。
void* nlib_malloc(size_t size);
void nlib_free(void* ptr);
void* nlib_calloc(size_t nmemb, size_t size);
void* nlib_realloc(void* ptr, size_t size);
void* nlib_memalign(size_t alignment, size_t size); // not defined if WIN32 or CTR
詳しくはheap_replace_mallocサンプルを御覧ください。
コンパイルオプションについて
パッケージのcmake/common.cmake.win32等のファイルにプラットフォーム毎のスイッチ等の定義が記述されています。 参考にしてください。
コンパイルすると"MACRO_XXXX not defined, compile may fail"と表示される
コンパイラへのコマンドライン引数でMACRO_XXXXを定義するようにしてください。
私達のプロジェクトで最新版を利用すべきかどうか教えてください。
それはnlibを利用するプロジェクトの判断に委ねられます。 受け入れテストを記述しておくことで、そういった判断をより容易にすることができます。 ただし、サポートの対象となるのは最新版のみです。ご了承ください。
私達のプロジェクトのために専用パッケージをリリースしてください。
プロジェクトのニーズはプロジェクトの数だけ存在します。例えば、以下のようなものがあります。
  • 私達にはライブラリXは必要ないので取り除いたものをリリースしてください。
  • 私達にはサンプルを取り除いたものをリリースしてください。
  • 私達はVisual Studio 2015(64bit)を使っているので、Visual Studio 2015用のソリューションを構築済みの状態にしてリリースしてください。
これらのニーズに柔軟に応えることを可能にするために、nlibを利用するプロジェクト側においてnlibのパッケージを再構成、再パッケージを行いプロジェクト内においてのみ再配布することが認められています。
nlib_printf()でShift JIS文字列が表示できません。
nlib_printf()の入力文字列はUTF-8である必要があります。
半年前のリリースにバグがあるので修正パッチをリリースしてください。
バグの修正は最新版に反映されます。次回以降のリリースを組み込んでください。
私達のライブラリやフレームワークのやり方に合わせて貰えませんか?
それが公開されていて、Windows/Linux/FreeBSD/OS X/Cafe/CTRの全てに対応しているものならば可能かもしれません。 ご連絡ください。

Changelogs

2017-09-26

2017-08-29

  • ossライブラリに収録されているSQLiteをバージョン3.20.0にアップデートしました。
  • Fedora環境におけるテストで、ASAN, UBSANが常時利用されるようになっています。
  • その他細かい変更と修正

2017-07-25

  • 今回のリリースではソースコード互換性が一部失われています。
  • Fedora 26での動作確認を開始しました。これに伴いFedora 25での動作確認を終了しました。
  • FreeBSD 11.1での動作確認を開始しました。これに伴いFreeBSD 11.0での動作確認を終了しました。
  • NLIB-54: msgpack::MpDirectWriterを追加しました。MessagePackのデータをメモリに直接書き出すためのクラスです。
  • NLIB-87: UriQueryDecoder, UriQueryEncoderを追加しました。
  • NLIB-75: msgpack::JsonStreamParser::Parse()にてエラーが発生した箇所を示す文字列の取得が可能になりました。
  • nlib_bswap16(), nlib_bswap32(), nlib_bswap64()を追加しました。
  • ムーブコンストラクタ及びムーブ代入演算子の実装を改善しました。
  • 各種クラスのメンバ関数swap()がdeprecatedになりました。フリー関数のswap()はムーブコンストラクタ及びムーブ代入演算子を利用した標準の方法で定義されます。
  • NLIB-82: HttpStyleUri, FileStyleUriがdeprecatedになりました。UriUriQueryDecoder, UriQueryEncoderを利用してください。
  • その他細かい変更と修正

2017-06-20

2017-05-16

  • Ubuntu 17.04での動作確認を開始しました。これに伴いUbuntu 16.10での動作確認を終了しました。
  • Alpine Linux 3.5での動作確認を開始しました。これに伴いAlpine Linux 3.4での動作確認を終了しました。
  • NLIB-27: nlib_byte_t型を追加しました。この型は将来的にC++17のstd::byteにtypedefされます。
  • NLIB-41: 列挙型の値をkEnumNameのような書き方に統一していきます。ENUM_NAMEのような書き方は将来的に使えなくなります。
  • NLIB-48: 互換性のために定義されていたマクロ、nlib_strcplen2, nlib_popcnt(x), nlib_clz(x), nlib_ctz(x)を削除しました。nlib_strcplen, nlib_popcnt32(x), nlib_clz32(x), nlib_ctz32(x)を利用してください。
  • msgpack::MpObject::Clone()がconstメンバ関数に変更されています。
  • その他細かい変更と修正

2017-04-18

  • msgpack::MpWalkerでバイト列の最後に到達するとエラー状態になるバグを修正しました。
  • その他細かい変更と修正

2017-03-22

  • 今回のリリースではソースコード互換性が一部失われています。
  • msgpack::JsonPatchクラス及びmsgpack::JsonPatchBuilderクラスを追加しました。JSON Patch(RFC 6902)をサポートします。
  • simd::i128argの定義が不必要に参照型になることがある問題を修正しました。
  • msgpack::GetMapItem()に、非ヌル終端の文字列を用いてMpObjectKvを取得することのできるオーバーロードを追加しました。
  • deprecatedとなっていたコードを削除しました。
  • NLIB-17: Visual StudioのDebugビルドにおいて、/Ob1オプションが指定されるようになりました。インライン関数が展開されるようになります。
  • その他細かい変更と修正

2017-02-14

2017-01-24

  • msgpackライブラリに、msgpack::MpObject::ResolveJsonPointer()を追加しました。JSON Pointer(RFC6901)をサポートします。
  • nlib_utf16_t, nlib_utf32_tがC言語利用時においてもtypedefされるようになりました。
  • nlib_utf8_tを新たに追加しました。
  • utf16_t, utf32_tがdeprecatedになりました。これらの型は将来のリリースで削除されます。
  • NINTENDOSDK-3321: msgpack::jsonrpc::JsonRpcRequest::Init()paramsを省略したリクエストを不正と判定する不具合を修正しました。
  • その他細かい変更と修正
こちらに 過去のChangelogs があります。