├── .clang-format ├── .clang-tidy ├── .gitattributes ├── .github └── workflows │ └── tests.yml ├── .gitignore ├── .gitmodules ├── CMakeLists.txt ├── LICENSE ├── README.md ├── cmake └── cpp_yyjsonConfig.cmake.in ├── include ├── cpp_yyjson.hpp └── field_reflection.hpp └── test ├── CMakeLists.txt ├── bench_read.cpp ├── bench_read.log ├── bench_write.cpp ├── bench_write.log └── test.cpp /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | Language: Cpp 3 | AccessModifierOffset: -4 4 | AlignAfterOpenBracket: Align 5 | AlignArrayOfStructures: None 6 | AlignConsecutiveAssignments: 7 | Enabled: false 8 | AcrossEmptyLines: false 9 | AcrossComments: false 10 | AlignCompound: false 11 | AlignFunctionPointers: false 12 | PadOperators: true 13 | AlignConsecutiveBitFields: 14 | Enabled: false 15 | AcrossEmptyLines: false 16 | AcrossComments: false 17 | AlignCompound: false 18 | AlignFunctionPointers: false 19 | PadOperators: true 20 | AlignConsecutiveDeclarations: 21 | Enabled: false 22 | AcrossEmptyLines: false 23 | AcrossComments: false 24 | AlignCompound: false 25 | AlignFunctionPointers: false 26 | PadOperators: true 27 | AlignConsecutiveMacros: 28 | Enabled: false 29 | AcrossEmptyLines: false 30 | AcrossComments: false 31 | AlignCompound: false 32 | AlignFunctionPointers: false 33 | PadOperators: true 34 | AlignConsecutiveShortCaseStatements: 35 | Enabled: false 36 | AcrossEmptyLines: false 37 | AcrossComments: false 38 | AlignCaseColons: false 39 | AlignEscapedNewlines: Left 40 | AlignOperands: Align 41 | AlignTrailingComments: 42 | Kind: Always 43 | OverEmptyLines: 1 44 | AllowAllArgumentsOnNextLine: true 45 | AllowAllParametersOfDeclarationOnNextLine: true 46 | AllowBreakBeforeNoexceptSpecifier: Never 47 | AllowShortBlocksOnASingleLine: Empty 48 | AllowShortCaseLabelsOnASingleLine: false 49 | AllowShortCompoundRequirementOnASingleLine: true 50 | AllowShortEnumsOnASingleLine: true 51 | AllowShortFunctionsOnASingleLine: All 52 | AllowShortIfStatementsOnASingleLine: WithoutElse 53 | AllowShortLambdasOnASingleLine: All 54 | AllowShortLoopsOnASingleLine: true 55 | AlwaysBreakAfterDefinitionReturnType: None 56 | AlwaysBreakAfterReturnType: None 57 | AlwaysBreakBeforeMultilineStrings: true 58 | AlwaysBreakTemplateDeclarations: Yes 59 | AttributeMacros: 60 | - __capability 61 | BinPackArguments: true 62 | BinPackParameters: true 63 | BitFieldColonSpacing: Both 64 | BraceWrapping: 65 | AfterCaseLabel: true 66 | AfterClass: true 67 | AfterControlStatement: Always 68 | AfterEnum: true 69 | AfterExternBlock: true 70 | AfterFunction: true 71 | AfterNamespace: true 72 | AfterObjCDeclaration: true 73 | AfterStruct: true 74 | AfterUnion: true 75 | BeforeCatch: true 76 | BeforeElse: true 77 | BeforeLambdaBody: false 78 | BeforeWhile: false 79 | IndentBraces: false 80 | SplitEmptyFunction: true 81 | SplitEmptyRecord: true 82 | SplitEmptyNamespace: true 83 | BreakAdjacentStringLiterals: true 84 | BreakAfterAttributes: Never 85 | BreakAfterJavaFieldAnnotations: false 86 | BreakArrays: true 87 | BreakBeforeBinaryOperators: None 88 | BreakBeforeConceptDeclarations: Always 89 | BreakBeforeBraces: Custom 90 | BreakBeforeInlineASMColon: OnlyMultiline 91 | BreakBeforeTernaryOperators: true 92 | BreakConstructorInitializers: BeforeColon 93 | BreakInheritanceList: BeforeColon 94 | BreakStringLiterals: true 95 | ColumnLimit: 120 96 | CommentPragmas: '^( IWYU pragma:|/ | TODO)' 97 | CompactNamespaces: false 98 | ConstructorInitializerIndentWidth: 4 99 | ContinuationIndentWidth: 4 100 | Cpp11BracedListStyle: true 101 | DerivePointerAlignment: true 102 | DisableFormat: false 103 | EmptyLineAfterAccessModifier: Never 104 | EmptyLineBeforeAccessModifier: LogicalBlock 105 | ExperimentalAutoDetectBinPacking: false 106 | FixNamespaceComments: true 107 | ForEachMacros: 108 | - foreach 109 | - Q_FOREACH 110 | - BOOST_FOREACH 111 | IfMacros: 112 | - KJ_IF_MAYBE 113 | IncludeBlocks: Preserve 114 | IncludeCategories: 115 | - Regex: '^' 116 | Priority: 2 117 | SortPriority: 0 118 | CaseSensitive: false 119 | - Regex: '^<.*\.h>' 120 | Priority: 1 121 | SortPriority: 0 122 | CaseSensitive: false 123 | - Regex: '^<.*' 124 | Priority: 2 125 | SortPriority: 0 126 | CaseSensitive: false 127 | - Regex: '.*' 128 | Priority: 3 129 | SortPriority: 0 130 | CaseSensitive: false 131 | IncludeIsMainRegex: '([-_](test|unittest))?$' 132 | IncludeIsMainSourceRegex: '' 133 | IndentAccessModifiers: false 134 | IndentCaseBlocks: false 135 | IndentCaseLabels: true 136 | IndentExternBlock: AfterExternBlock 137 | IndentGotoLabels: true 138 | IndentPPDirectives: None 139 | IndentRequiresClause: false 140 | IndentWidth: 4 141 | IndentWrappedFunctionNames: false 142 | InsertBraces: false 143 | InsertNewlineAtEOF: false 144 | InsertTrailingCommas: None 145 | IntegerLiteralSeparator: 146 | Binary: 0 147 | BinaryMinDigits: 0 148 | Decimal: 0 149 | DecimalMinDigits: 0 150 | Hex: 0 151 | HexMinDigits: 0 152 | JavaScriptQuotes: Leave 153 | JavaScriptWrapImports: true 154 | KeepEmptyLinesAtTheStartOfBlocks: false 155 | KeepEmptyLinesAtEOF: false 156 | LambdaBodyIndentation: Signature 157 | LineEnding: DeriveLF 158 | MacroBlockBegin: '' 159 | MacroBlockEnd: '' 160 | MaxEmptyLinesToKeep: 1 161 | NamespaceIndentation: All 162 | ObjCBinPackProtocolList: Auto 163 | ObjCBlockIndentWidth: 4 164 | ObjCBreakBeforeNestedBlockParam: true 165 | ObjCSpaceAfterProperty: false 166 | ObjCSpaceBeforeProtocolList: false 167 | PackConstructorInitializers: NextLine 168 | PenaltyBreakAssignment: 2 169 | PenaltyBreakBeforeFirstCallParameter: 1 170 | PenaltyBreakComment: 300 171 | PenaltyBreakFirstLessLess: 120 172 | PenaltyBreakOpenParenthesis: 0 173 | PenaltyBreakScopeResolution: 500 174 | PenaltyBreakString: 1000 175 | PenaltyBreakTemplateDeclaration: 10 176 | PenaltyExcessCharacter: 1000000 177 | PenaltyIndentedWhitespace: 0 178 | PenaltyReturnTypeOnItsOwnLine: 200 179 | PointerAlignment: Left 180 | PPIndentWidth: -1 181 | QualifierAlignment: Leave 182 | RawStringFormats: 183 | - Language: TextProto 184 | CanonicalDelimiter: '' 185 | BasedOnStyle: google 186 | ReferenceAlignment: Pointer 187 | ReflowComments: true 188 | RemoveBracesLLVM: false 189 | RemoveParentheses: Leave 190 | RemoveSemicolon: false 191 | RequiresClausePosition: OwnLine 192 | RequiresExpressionIndentation: OuterScope 193 | SeparateDefinitionBlocks: Leave 194 | ShortNamespaceLines: 1 195 | SkipMacroDefinitionBody: false 196 | SortIncludes: CaseSensitive 197 | SortJavaStaticImport: Before 198 | SortUsingDeclarations: LexicographicNumeric 199 | SpaceAfterCStyleCast: false 200 | SpaceAfterLogicalNot: false 201 | SpaceAfterTemplateKeyword: true 202 | SpaceAroundPointerQualifiers: Default 203 | SpaceBeforeAssignmentOperators: true 204 | SpaceBeforeCaseColon: false 205 | SpaceBeforeCpp11BracedList: false 206 | SpaceBeforeCtorInitializerColon: true 207 | SpaceBeforeInheritanceColon: true 208 | SpaceBeforeJsonColon: false 209 | SpaceBeforeParens: Custom 210 | SpaceBeforeParensOptions: 211 | AfterControlStatements: true 212 | AfterForeachMacros: true 213 | AfterFunctionDefinitionName: false 214 | AfterFunctionDeclarationName: false 215 | AfterIfMacros: true 216 | AfterOverloadedOperator: false 217 | AfterPlacementOperator: true 218 | AfterRequiresInClause: true 219 | AfterRequiresInExpression: false 220 | BeforeNonEmptyParentheses: false 221 | SpaceBeforeRangeBasedForLoopColon: true 222 | SpaceBeforeSquareBrackets: false 223 | SpaceInEmptyBlock: false 224 | SpacesBeforeTrailingComments: 2 225 | SpacesInAngles: Never 226 | SpacesInContainerLiterals: true 227 | SpacesInLineCommentPrefix: 228 | Minimum: 1 229 | Maximum: -1 230 | SpacesInParens: Never 231 | SpacesInParensOptions: 232 | InCStyleCasts: false 233 | InConditionalStatements: false 234 | InEmptyParentheses: false 235 | Other: false 236 | SpacesInSquareBrackets: false 237 | Standard: Auto 238 | StatementAttributeLikeMacros: 239 | - Q_EMIT 240 | StatementMacros: 241 | - Q_UNUSED 242 | - QT_REQUIRE_VERSION 243 | TabWidth: 4 244 | UseTab: Never 245 | VerilogBreakBetweenInstancePorts: true 246 | WhitespaceSensitiveMacros: 247 | - STRINGIZE 248 | - PP_STRINGIZE 249 | - BOOST_PP_STRINGIZE 250 | - NS_SWIFT_NAME 251 | - CF_SWIFT_NAME 252 | ... 253 | 254 | -------------------------------------------------------------------------------- /.clang-tidy: -------------------------------------------------------------------------------- 1 | --- 2 | Checks: 'clang-diagnostic-*,clang-analyzer-*,clang-diagnostic-*,clang-analyzer-*,clang-diagnostic-*,clang-analyzer-*,clang-diagnostic-*,clang-analyzer-*,-*,google-*,modernize-*,performance-*,portability-*,readability-*,clang-diagnostic-*,clang-analyzer-*,-modernize-pass-by-value,-modernize-use-trailing-return-type,-google-readability-todo,-google-readability-braces-around-statements,-google-runtime-references,-readability-named-parameter,-readability-braces-around-statements,-readability-redundant-declaration,-readability-function-cognitive-complexity,-readability-qualified-auto,-readability-identifier-length,-readability-static-accessed-through-instance' 3 | WarningsAsErrors: '' 4 | HeaderFilterRegex: '.*' 5 | FormatStyle: file 6 | CheckOptions: 7 | cert-dcl16-c.NewSuffixes: 'L;LL;LU;LLU' 8 | cert-err33-c.AllowCastToVoid: 'true' 9 | cert-err33-c.CheckedFunctions: '::aligned_alloc;::asctime_s;::at_quick_exit;::atexit;::bsearch;::bsearch_s;::btowc;::c16rtomb;::c32rtomb;::calloc;::clock;::cnd_broadcast;::cnd_init;::cnd_signal;::cnd_timedwait;::cnd_wait;::ctime_s;::fclose;::fflush;::fgetc;::fgetpos;::fgets;::fgetwc;::fopen;::fopen_s;::fprintf;::fprintf_s;::fputc;::fputs;::fputwc;::fputws;::fread;::freopen;::freopen_s;::fscanf;::fscanf_s;::fseek;::fsetpos;::ftell;::fwprintf;::fwprintf_s;::fwrite;::fwscanf;::fwscanf_s;::getc;::getchar;::getenv;::getenv_s;::gets_s;::getwc;::getwchar;::gmtime;::gmtime_s;::localtime;::localtime_s;::malloc;::mbrtoc16;::mbrtoc32;::mbsrtowcs;::mbsrtowcs_s;::mbstowcs;::mbstowcs_s;::memchr;::mktime;::mtx_init;::mtx_lock;::mtx_timedlock;::mtx_trylock;::mtx_unlock;::printf_s;::putc;::putwc;::raise;::realloc;::remove;::rename;::scanf;::scanf_s;::setlocale;::setvbuf;::signal;::snprintf;::snprintf_s;::sprintf;::sprintf_s;::sscanf;::sscanf_s;::strchr;::strerror_s;::strftime;::strpbrk;::strrchr;::strstr;::strtod;::strtof;::strtoimax;::strtok;::strtok_s;::strtol;::strtold;::strtoll;::strtoul;::strtoull;::strtoumax;::strxfrm;::swprintf;::swprintf_s;::swscanf;::swscanf_s;::thrd_create;::thrd_detach;::thrd_join;::thrd_sleep;::time;::timespec_get;::tmpfile;::tmpfile_s;::tmpnam;::tmpnam_s;::tss_create;::tss_get;::tss_set;::ungetc;::ungetwc;::vfprintf;::vfprintf_s;::vfscanf;::vfscanf_s;::vfwprintf;::vfwprintf_s;::vfwscanf;::vfwscanf_s;::vprintf_s;::vscanf;::vscanf_s;::vsnprintf;::vsnprintf_s;::vsprintf;::vsprintf_s;::vsscanf;::vsscanf_s;::vswprintf;::vswprintf_s;::vswscanf;::vswscanf_s;::vwprintf_s;::vwscanf;::vwscanf_s;::wcrtomb;::wcschr;::wcsftime;::wcspbrk;::wcsrchr;::wcsrtombs;::wcsrtombs_s;::wcsstr;::wcstod;::wcstof;::wcstoimax;::wcstok;::wcstok_s;::wcstol;::wcstold;::wcstoll;::wcstombs;::wcstombs_s;::wcstoul;::wcstoull;::wcstoumax;::wcsxfrm;::wctob;::wctrans;::wctype;::wmemchr;::wprintf_s;::wscanf;::wscanf_s;' 10 | cert-oop54-cpp.WarnOnlyIfThisHasSuspiciousField: 'false' 11 | cert-str34-c.DiagnoseSignedUnsignedCharComparisons: 'false' 12 | cppcoreguidelines-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic: 'true' 13 | google-build-namespaces.HeaderFileExtensions: ';h;hh;hpp;hxx' 14 | google-global-names-in-headers.HeaderFileExtensions: ';h;hh;hpp;hxx' 15 | google-readability-braces-around-statements.ShortStatementLines: '1' 16 | google-readability-function-size.BranchThreshold: '4294967295' 17 | google-readability-function-size.LineThreshold: '4294967295' 18 | google-readability-function-size.NestingThreshold: '4294967295' 19 | google-readability-function-size.ParameterThreshold: '4294967295' 20 | google-readability-function-size.StatementThreshold: '800' 21 | google-readability-function-size.VariableThreshold: '4294967295' 22 | google-readability-namespace-comments.ShortNamespaceLines: '10' 23 | google-readability-namespace-comments.SpacesBeforeComments: '2' 24 | google-runtime-int.SignedTypePrefix: int 25 | google-runtime-int.TypeSuffix: '' 26 | google-runtime-int.UnsignedTypePrefix: uint 27 | llvm-else-after-return.WarnOnConditionVariables: 'false' 28 | llvm-else-after-return.WarnOnUnfixable: 'false' 29 | llvm-qualified-auto.AddConstToQualified: 'false' 30 | modernize-avoid-bind.PermissiveParameterList: 'false' 31 | modernize-deprecated-headers.CheckHeaderFile: 'false' 32 | modernize-loop-convert.IncludeStyle: llvm 33 | modernize-loop-convert.MakeReverseRangeFunction: '' 34 | modernize-loop-convert.MakeReverseRangeHeader: '' 35 | modernize-loop-convert.MaxCopySize: '16' 36 | modernize-loop-convert.MinConfidence: reasonable 37 | modernize-loop-convert.NamingStyle: CamelCase 38 | modernize-loop-convert.UseCxx20ReverseRanges: 'true' 39 | modernize-make-shared.IgnoreDefaultInitialization: 'true' 40 | modernize-make-shared.IgnoreMacros: 'true' 41 | modernize-make-shared.IncludeStyle: llvm 42 | modernize-make-shared.MakeSmartPtrFunction: 'std::make_shared' 43 | modernize-make-shared.MakeSmartPtrFunctionHeader: '' 44 | modernize-make-unique.IgnoreDefaultInitialization: 'true' 45 | modernize-make-unique.IgnoreMacros: 'true' 46 | modernize-make-unique.IncludeStyle: llvm 47 | modernize-make-unique.MakeSmartPtrFunction: 'std::make_unique' 48 | modernize-make-unique.MakeSmartPtrFunctionHeader: '' 49 | modernize-raw-string-literal.DelimiterStem: lit 50 | modernize-raw-string-literal.ReplaceShorterLiterals: 'false' 51 | modernize-replace-auto-ptr.IncludeStyle: llvm 52 | modernize-replace-disallow-copy-and-assign-macro.MacroName: DISALLOW_COPY_AND_ASSIGN 53 | modernize-replace-random-shuffle.IncludeStyle: llvm 54 | modernize-type-traits.IgnoreMacros: 'false' 55 | modernize-use-auto.MinTypeNameLength: '5' 56 | modernize-use-auto.RemoveStars: 'false' 57 | modernize-use-bool-literals.IgnoreMacros: 'true' 58 | modernize-use-default-member-init.IgnoreMacros: 'true' 59 | modernize-use-default-member-init.UseAssignment: 'false' 60 | modernize-use-emplace.ContainersWithPush: '::std::stack;::std::queue;::std::priority_queue' 61 | modernize-use-emplace.ContainersWithPushBack: '::std::vector;::std::list;::std::deque' 62 | modernize-use-emplace.ContainersWithPushFront: '::std::forward_list;::std::list;::std::deque' 63 | modernize-use-emplace.EmplacyFunctions: 'vector::emplace_back;vector::emplace;deque::emplace;deque::emplace_front;deque::emplace_back;forward_list::emplace_after;forward_list::emplace_front;list::emplace;list::emplace_back;list::emplace_front;set::emplace;set::emplace_hint;map::emplace;map::emplace_hint;multiset::emplace;multiset::emplace_hint;multimap::emplace;multimap::emplace_hint;unordered_set::emplace;unordered_set::emplace_hint;unordered_map::emplace;unordered_map::emplace_hint;unordered_multiset::emplace;unordered_multiset::emplace_hint;unordered_multimap::emplace;unordered_multimap::emplace_hint;stack::emplace;queue::emplace;priority_queue::emplace' 64 | modernize-use-emplace.IgnoreImplicitConstructors: 'false' 65 | modernize-use-emplace.SmartPointers: '::std::shared_ptr;::std::unique_ptr;::std::auto_ptr;::std::weak_ptr' 66 | modernize-use-emplace.TupleMakeFunctions: '::std::make_pair;::std::make_tuple' 67 | modernize-use-emplace.TupleTypes: '::std::pair;::std::tuple' 68 | modernize-use-equals-default.IgnoreMacros: 'true' 69 | modernize-use-equals-delete.IgnoreMacros: 'true' 70 | modernize-use-nodiscard.ReplacementString: '[[nodiscard]]' 71 | modernize-use-noexcept.ReplacementString: '' 72 | modernize-use-noexcept.UseNoexceptFalse: 'true' 73 | modernize-use-nullptr.IgnoredTypes: 'std::_CmpUnspecifiedParam::;^std::__cmp_cat::__unspec' 74 | modernize-use-nullptr.NullMacros: 'NULL' 75 | modernize-use-override.AllowOverrideAndFinal: 'false' 76 | modernize-use-override.FinalSpelling: final 77 | modernize-use-override.IgnoreDestructors: 'false' 78 | modernize-use-override.IgnoreTemplateInstantiations: 'false' 79 | modernize-use-override.OverrideSpelling: override 80 | modernize-use-std-numbers.DiffThreshold: '0.001' 81 | modernize-use-std-numbers.IncludeStyle: llvm 82 | modernize-use-std-print.FprintfLikeFunctions: '::fprintf;absl::FPrintF' 83 | modernize-use-std-print.IncludeStyle: llvm 84 | modernize-use-std-print.PrintHeader: '' 85 | modernize-use-std-print.PrintfLikeFunctions: '::printf;absl::PrintF' 86 | modernize-use-std-print.ReplacementPrintFunction: 'std::print' 87 | modernize-use-std-print.ReplacementPrintlnFunction: 'std::println' 88 | modernize-use-std-print.StrictMode: 'false' 89 | modernize-use-transparent-functors.SafeMode: 'false' 90 | modernize-use-using.IgnoreExternC: 'false' 91 | modernize-use-using.IgnoreMacros: 'true' 92 | performance-enum-size.EnumIgnoreList: '' 93 | performance-faster-string-find.StringLikeClasses: '::std::basic_string;::std::basic_string_view' 94 | performance-for-range-copy.AllowedTypes: '' 95 | performance-for-range-copy.WarnOnAllAutoCopies: 'false' 96 | performance-inefficient-string-concatenation.StrictMode: 'false' 97 | performance-inefficient-vector-operation.EnableProto: 'false' 98 | performance-inefficient-vector-operation.VectorLikeClasses: '::std::vector' 99 | performance-move-const-arg.CheckMoveToConstRef: 'true' 100 | performance-move-const-arg.CheckTriviallyCopyableMove: 'false' 101 | performance-no-automatic-move.AllowedTypes: '' 102 | performance-type-promotion-in-math-fn.IncludeStyle: llvm 103 | performance-unnecessary-copy-initialization.AllowedTypes: '' 104 | performance-unnecessary-copy-initialization.ExcludedContainerTypes: '' 105 | performance-unnecessary-value-param.AllowedTypes: '' 106 | performance-unnecessary-value-param.IncludeStyle: llvm 107 | portability-restrict-system-includes.Includes: '*' 108 | portability-simd-intrinsics.Std: '' 109 | portability-simd-intrinsics.Suggest: 'false' 110 | readability-avoid-const-params-in-decls.IgnoreMacros: 'true' 111 | readability-avoid-return-with-void-value.IgnoreMacros: 'true' 112 | readability-avoid-return-with-void-value.StrictMode: 'true' 113 | readability-const-return-type.IgnoreMacros: 'true' 114 | readability-container-data-pointer.IgnoredContainers: '' 115 | readability-container-size-empty.ExcludedComparisonTypes: '::std::array' 116 | readability-else-after-return.WarnOnConditionVariables: 'true' 117 | readability-else-after-return.WarnOnUnfixable: 'true' 118 | readability-function-size.BranchThreshold: '4294967295' 119 | readability-function-size.LineThreshold: '4294967295' 120 | readability-function-size.NestingThreshold: '4294967295' 121 | readability-function-size.ParameterThreshold: '4294967295' 122 | readability-function-size.StatementThreshold: '800' 123 | readability-function-size.VariableThreshold: '4294967295' 124 | readability-identifier-naming.AbstractClassCase: lower_case 125 | readability-identifier-naming.AbstractClassIgnoredRegexp: '' 126 | readability-identifier-naming.AbstractClassPrefix: '' 127 | readability-identifier-naming.AbstractClassSuffix: '' 128 | readability-identifier-naming.AggressiveDependentMemberLookup: 'false' 129 | readability-identifier-naming.CheckAnonFieldInParent: 'false' 130 | readability-identifier-naming.ClassCase: lower_case 131 | readability-identifier-naming.ClassConstantCase: lower_case 132 | readability-identifier-naming.ClassConstantIgnoredRegexp: '' 133 | readability-identifier-naming.ClassConstantPrefix: '' 134 | readability-identifier-naming.ClassConstantSuffix: _ 135 | readability-identifier-naming.ClassIgnoredRegexp: '' 136 | readability-identifier-naming.ClassMemberCase: lower_case 137 | readability-identifier-naming.ClassMemberIgnoredRegexp: '' 138 | readability-identifier-naming.ClassMemberPrefix: '' 139 | readability-identifier-naming.ClassMemberSuffix: _ 140 | readability-identifier-naming.ClassMethodCase: lower_case 141 | readability-identifier-naming.ClassMethodIgnoredRegexp: '' 142 | readability-identifier-naming.ClassMethodPrefix: '' 143 | readability-identifier-naming.ClassMethodSuffix: '' 144 | readability-identifier-naming.ClassPrefix: '' 145 | readability-identifier-naming.ClassSuffix: '' 146 | readability-identifier-naming.ConstantCase: lower_case 147 | readability-identifier-naming.ConstantIgnoredRegexp: '' 148 | readability-identifier-naming.ConstantMemberCase: lower_case 149 | readability-identifier-naming.ConstantMemberIgnoredRegexp: '' 150 | readability-identifier-naming.ConstantMemberPrefix: '' 151 | readability-identifier-naming.ConstantMemberSuffix: '' 152 | readability-identifier-naming.ConstantParameterCase: lower_case 153 | readability-identifier-naming.ConstantParameterIgnoredRegexp: '' 154 | readability-identifier-naming.ConstantParameterPrefix: '' 155 | readability-identifier-naming.ConstantParameterSuffix: '' 156 | readability-identifier-naming.ConstantPointerParameterCase: lower_case 157 | readability-identifier-naming.ConstantPointerParameterIgnoredRegexp: '' 158 | readability-identifier-naming.ConstantPointerParameterPrefix: '' 159 | readability-identifier-naming.ConstantPointerParameterSuffix: '' 160 | readability-identifier-naming.ConstantPrefix: '' 161 | readability-identifier-naming.ConstantSuffix: '' 162 | readability-identifier-naming.ConstexprFunctionCase: lower_case 163 | readability-identifier-naming.ConstexprFunctionIgnoredRegexp: '' 164 | readability-identifier-naming.ConstexprFunctionPrefix: '' 165 | readability-identifier-naming.ConstexprFunctionSuffix: '' 166 | readability-identifier-naming.ConstexprMethodCase: lower_case 167 | readability-identifier-naming.ConstexprMethodIgnoredRegexp: '' 168 | readability-identifier-naming.ConstexprMethodPrefix: '' 169 | readability-identifier-naming.ConstexprMethodSuffix: '' 170 | readability-identifier-naming.ConstexprVariableCase: lower_case 171 | readability-identifier-naming.ConstexprVariableIgnoredRegexp: '' 172 | readability-identifier-naming.ConstexprVariablePrefix: '' 173 | readability-identifier-naming.ConstexprVariableSuffix: '' 174 | readability-identifier-naming.EnumCase: CamelCase 175 | readability-identifier-naming.EnumConstantCase: CamelCase 176 | readability-identifier-naming.EnumConstantIgnoredRegexp: '' 177 | readability-identifier-naming.EnumConstantPrefix: '' 178 | readability-identifier-naming.EnumConstantSuffix: '' 179 | readability-identifier-naming.EnumIgnoredRegexp: '' 180 | readability-identifier-naming.EnumPrefix: '' 181 | readability-identifier-naming.EnumSuffix: '' 182 | readability-identifier-naming.FunctionCase: lower_case 183 | readability-identifier-naming.FunctionIgnoredRegexp: '' 184 | readability-identifier-naming.FunctionPrefix: '' 185 | readability-identifier-naming.FunctionSuffix: '' 186 | readability-identifier-naming.GetConfigPerFile: 'true' 187 | readability-identifier-naming.GlobalConstantCase: lower_case 188 | readability-identifier-naming.GlobalConstantIgnoredRegexp: '' 189 | readability-identifier-naming.GlobalConstantPointerCase: CamelCase 190 | readability-identifier-naming.GlobalConstantPointerIgnoredRegexp: '' 191 | readability-identifier-naming.GlobalConstantPointerPrefix: '' 192 | readability-identifier-naming.GlobalConstantPointerSuffix: '' 193 | readability-identifier-naming.GlobalConstantPrefix: '' 194 | readability-identifier-naming.GlobalConstantSuffix: '' 195 | readability-identifier-naming.GlobalFunctionCase: lower_case 196 | readability-identifier-naming.GlobalFunctionIgnoredRegexp: '' 197 | readability-identifier-naming.GlobalFunctionPrefix: '' 198 | readability-identifier-naming.GlobalFunctionSuffix: '' 199 | readability-identifier-naming.GlobalPointerCase: lower_case 200 | readability-identifier-naming.GlobalPointerIgnoredRegexp: '' 201 | readability-identifier-naming.GlobalPointerPrefix: '' 202 | readability-identifier-naming.GlobalPointerSuffix: '' 203 | readability-identifier-naming.GlobalVariableCase: lower_case 204 | readability-identifier-naming.GlobalVariableIgnoredRegexp: '' 205 | readability-identifier-naming.GlobalVariablePrefix: '' 206 | readability-identifier-naming.GlobalVariableSuffix: '' 207 | readability-identifier-naming.IgnoreFailedSplit: 'false' 208 | readability-identifier-naming.IgnoreMainLikeFunctions: 'false' 209 | readability-identifier-naming.InlineNamespaceCase: lower_case 210 | readability-identifier-naming.InlineNamespaceIgnoredRegexp: '' 211 | readability-identifier-naming.InlineNamespacePrefix: '' 212 | readability-identifier-naming.InlineNamespaceSuffix: '' 213 | readability-identifier-naming.LocalConstantCase: lower_case 214 | readability-identifier-naming.LocalConstantIgnoredRegexp: '' 215 | readability-identifier-naming.LocalConstantPointerCase: lower_case 216 | readability-identifier-naming.LocalConstantPointerIgnoredRegexp: '' 217 | readability-identifier-naming.LocalConstantPointerPrefix: '' 218 | readability-identifier-naming.LocalConstantPointerSuffix: '' 219 | readability-identifier-naming.LocalConstantPrefix: '' 220 | readability-identifier-naming.LocalConstantSuffix: '' 221 | readability-identifier-naming.LocalPointerCase: lower_case 222 | readability-identifier-naming.LocalPointerIgnoredRegexp: '' 223 | readability-identifier-naming.LocalPointerPrefix: '' 224 | readability-identifier-naming.LocalPointerSuffix: '' 225 | readability-identifier-naming.LocalVariableCase: lower_case 226 | readability-identifier-naming.LocalVariableIgnoredRegexp: '' 227 | readability-identifier-naming.LocalVariablePrefix: '' 228 | readability-identifier-naming.LocalVariableSuffix: '' 229 | readability-identifier-naming.MemberCase: lower_case 230 | readability-identifier-naming.MemberIgnoredRegexp: '' 231 | readability-identifier-naming.MemberPrefix: '' 232 | readability-identifier-naming.MemberSuffix: '' 233 | readability-identifier-naming.MethodCase: lower_case 234 | readability-identifier-naming.MethodIgnoredRegexp: '' 235 | readability-identifier-naming.MethodPrefix: '' 236 | readability-identifier-naming.MethodSuffix: '' 237 | readability-identifier-naming.NamespaceCase: lower_case 238 | readability-identifier-naming.NamespaceIgnoredRegexp: '' 239 | readability-identifier-naming.NamespacePrefix: '' 240 | readability-identifier-naming.NamespaceSuffix: '' 241 | readability-identifier-naming.ParameterCase: lower_case 242 | readability-identifier-naming.ParameterIgnoredRegexp: '' 243 | readability-identifier-naming.ParameterPackCase: lower_case 244 | readability-identifier-naming.ParameterPackIgnoredRegexp: '' 245 | readability-identifier-naming.ParameterPackPrefix: '' 246 | readability-identifier-naming.ParameterPackSuffix: '' 247 | readability-identifier-naming.ParameterPrefix: '' 248 | readability-identifier-naming.ParameterSuffix: '' 249 | readability-identifier-naming.PointerParameterCase: lower_case 250 | readability-identifier-naming.PointerParameterIgnoredRegexp: '' 251 | readability-identifier-naming.PointerParameterPrefix: '' 252 | readability-identifier-naming.PointerParameterSuffix: '' 253 | readability-identifier-naming.PrivateMemberCase: lower_case 254 | readability-identifier-naming.PrivateMemberIgnoredRegexp: '' 255 | readability-identifier-naming.PrivateMemberPrefix: '' 256 | readability-identifier-naming.PrivateMemberSuffix: _ 257 | readability-identifier-naming.PrivateMethodCase: lower_case 258 | readability-identifier-naming.PrivateMethodIgnoredRegexp: '' 259 | readability-identifier-naming.PrivateMethodPrefix: '' 260 | readability-identifier-naming.PrivateMethodSuffix: '' 261 | readability-identifier-naming.ProtectedMemberCase: lower_case 262 | readability-identifier-naming.ProtectedMemberIgnoredRegexp: '' 263 | readability-identifier-naming.ProtectedMemberPrefix: '' 264 | readability-identifier-naming.ProtectedMemberSuffix: _ 265 | readability-identifier-naming.ProtectedMethodCase: lower_case 266 | readability-identifier-naming.ProtectedMethodIgnoredRegexp: '' 267 | readability-identifier-naming.ProtectedMethodPrefix: '' 268 | readability-identifier-naming.ProtectedMethodSuffix: '' 269 | readability-identifier-naming.PublicMemberCase: lower_case 270 | readability-identifier-naming.PublicMemberIgnoredRegexp: '' 271 | readability-identifier-naming.PublicMemberPrefix: '' 272 | readability-identifier-naming.PublicMemberSuffix: '' 273 | readability-identifier-naming.PublicMethodCase: lower_case 274 | readability-identifier-naming.PublicMethodIgnoredRegexp: '' 275 | readability-identifier-naming.PublicMethodPrefix: '' 276 | readability-identifier-naming.PublicMethodSuffix: '' 277 | readability-identifier-naming.StaticConstantCase: lower_case 278 | readability-identifier-naming.StaticConstantIgnoredRegexp: '' 279 | readability-identifier-naming.StaticConstantPrefix: '' 280 | readability-identifier-naming.StaticConstantSuffix: '' 281 | readability-identifier-naming.StaticVariableCase: lower_case 282 | readability-identifier-naming.StaticVariableIgnoredRegexp: '' 283 | readability-identifier-naming.StaticVariablePrefix: '' 284 | readability-identifier-naming.StaticVariableSuffix: '' 285 | readability-identifier-naming.StructCase: lower_case 286 | readability-identifier-naming.StructIgnoredRegexp: '' 287 | readability-identifier-naming.StructPrefix: '' 288 | readability-identifier-naming.StructSuffix: '' 289 | readability-identifier-naming.TemplateParameterCase: CamelCase 290 | readability-identifier-naming.TemplateParameterIgnoredRegexp: '' 291 | readability-identifier-naming.TemplateParameterPrefix: '' 292 | readability-identifier-naming.TemplateParameterSuffix: '' 293 | readability-identifier-naming.TemplateTemplateParameterCase: CamelCase 294 | readability-identifier-naming.TemplateTemplateParameterIgnoredRegexp: '' 295 | readability-identifier-naming.TemplateTemplateParameterPrefix: '' 296 | readability-identifier-naming.TemplateTemplateParameterSuffix: '' 297 | readability-identifier-naming.TypeAliasCase: lower_case 298 | readability-identifier-naming.TypeAliasIgnoredRegexp: '' 299 | readability-identifier-naming.TypeAliasPrefix: '' 300 | readability-identifier-naming.TypeAliasSuffix: '' 301 | readability-identifier-naming.TypeTemplateParameterCase: CamelCase 302 | readability-identifier-naming.TypeTemplateParameterIgnoredRegexp: '' 303 | readability-identifier-naming.TypeTemplateParameterPrefix: '' 304 | readability-identifier-naming.TypeTemplateParameterSuffix: '' 305 | readability-identifier-naming.TypedefCase: lower_case 306 | readability-identifier-naming.TypedefIgnoredRegexp: '' 307 | readability-identifier-naming.TypedefPrefix: '' 308 | readability-identifier-naming.TypedefSuffix: '' 309 | readability-identifier-naming.UnionCase: CamelCase 310 | readability-identifier-naming.UnionIgnoredRegexp: '' 311 | readability-identifier-naming.UnionPrefix: '' 312 | readability-identifier-naming.UnionSuffix: '' 313 | readability-identifier-naming.ValueTemplateParameterCase: CamelCase 314 | readability-identifier-naming.ValueTemplateParameterIgnoredRegexp: '' 315 | readability-identifier-naming.ValueTemplateParameterPrefix: '' 316 | readability-identifier-naming.ValueTemplateParameterSuffix: '' 317 | readability-identifier-naming.VariableCase: lower_case 318 | readability-identifier-naming.VariableIgnoredRegexp: '' 319 | readability-identifier-naming.VariablePrefix: '' 320 | readability-identifier-naming.VariableSuffix: '' 321 | readability-identifier-naming.VirtualMethodCase: lower_case 322 | readability-identifier-naming.VirtualMethodIgnoredRegexp: '' 323 | readability-identifier-naming.VirtualMethodPrefix: '' 324 | readability-identifier-naming.VirtualMethodSuffix: '' 325 | readability-implicit-bool-conversion.AllowIntegerConditions: 'false' 326 | readability-implicit-bool-conversion.AllowPointerConditions: 'false' 327 | readability-inconsistent-declaration-parameter-name.IgnoreMacros: 'true' 328 | readability-inconsistent-declaration-parameter-name.Strict: 'false' 329 | readability-magic-numbers.IgnoreAllFloatingPointValues: 'false' 330 | readability-magic-numbers.IgnoreBitFieldsWidths: 'true' 331 | readability-magic-numbers.IgnorePowersOf2IntegerValues: 'false' 332 | readability-magic-numbers.IgnoreTypeAliases: 'false' 333 | readability-magic-numbers.IgnoreUserDefinedLiterals: 'false' 334 | readability-magic-numbers.IgnoredFloatingPointValues: '1.0;100.0;' 335 | readability-magic-numbers.IgnoredIntegerValues: '1;2;3;4;' 336 | readability-operators-representation.BinaryOperators: '&&;&=;&;|;~;!;!=;||;|=;^;^=' 337 | readability-operators-representation.OverloadedOperators: '&&;&=;&;|;~;!;!=;||;|=;^;^=' 338 | readability-redundant-casting.IgnoreMacros: 'true' 339 | readability-redundant-casting.IgnoreTypeAliases: 'false' 340 | readability-redundant-member-init.IgnoreBaseInCopyConstructors: 'false' 341 | readability-redundant-smartptr-get.IgnoreMacros: 'true' 342 | readability-redundant-string-init.StringNames: '::std::basic_string_view;::std::basic_string' 343 | readability-simplify-boolean-expr.ChainedConditionalAssignment: 'false' 344 | readability-simplify-boolean-expr.ChainedConditionalReturn: 'false' 345 | readability-simplify-boolean-expr.IgnoreMacros: 'false' 346 | readability-simplify-boolean-expr.SimplifyDeMorgan: 'true' 347 | readability-simplify-boolean-expr.SimplifyDeMorganRelaxed: 'false' 348 | readability-simplify-subscript-expr.Types: '::std::basic_string;::std::basic_string_view;::std::vector;::std::array' 349 | readability-static-accessed-through-instance.NameSpecifierNestingThreshold: '3' 350 | readability-suspicious-call-argument.Abbreviation: 'true' 351 | readability-suspicious-call-argument.Abbreviations: 'lst=list;arr=array;num=number;ptr=pointer;i=index;val=value;ln=line;cpy=copy;idx=index;vec=vector;src=source;dest=destination;wdth=width;nr=number;elem=element;srv=server;pos=position;cl=client;stmt=statement;len=length;buf=buffer;dist=distancedst=distance;hght=height;var=variable;col=column;ref=reference;attr=attribute;str=string;cnt=count;addr=address' 352 | readability-suspicious-call-argument.Dice: 'true' 353 | readability-suspicious-call-argument.DiceDissimilarBelow: '60' 354 | readability-suspicious-call-argument.DiceSimilarAbove: '70' 355 | readability-suspicious-call-argument.Equality: 'true' 356 | readability-suspicious-call-argument.JaroWinkler: 'true' 357 | readability-suspicious-call-argument.JaroWinklerDissimilarBelow: '75' 358 | readability-suspicious-call-argument.JaroWinklerSimilarAbove: '85' 359 | readability-suspicious-call-argument.Levenshtein: 'true' 360 | readability-suspicious-call-argument.LevenshteinDissimilarBelow: '50' 361 | readability-suspicious-call-argument.LevenshteinSimilarAbove: '66' 362 | readability-suspicious-call-argument.MinimumIdentifierNameLength: '3' 363 | readability-suspicious-call-argument.Prefix: 'true' 364 | readability-suspicious-call-argument.PrefixDissimilarBelow: '25' 365 | readability-suspicious-call-argument.PrefixSimilarAbove: '30' 366 | readability-suspicious-call-argument.Substring: 'true' 367 | readability-suspicious-call-argument.SubstringDissimilarBelow: '40' 368 | readability-suspicious-call-argument.SubstringSimilarAbove: '50' 369 | readability-suspicious-call-argument.Suffix: 'true' 370 | readability-suspicious-call-argument.SuffixDissimilarBelow: '25' 371 | readability-suspicious-call-argument.SuffixSimilarAbove: '30' 372 | readability-uniqueptr-delete-release.PreferResetCall: 'false' 373 | readability-uppercase-literal-suffix.IgnoreMacros: 'true' 374 | readability-uppercase-literal-suffix.NewSuffixes: '' 375 | SystemHeaders: false 376 | ... 377 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf encoding=utf-8 2 | -------------------------------------------------------------------------------- /.github/workflows/tests.yml: -------------------------------------------------------------------------------- 1 | name: Tests 2 | 3 | on: 4 | workflow_dispatch: 5 | pull_request: 6 | push: 7 | branches: 8 | - main 9 | tags: 10 | - "v*" 11 | 12 | concurrency: 13 | group: test-${{ github.ref }} 14 | cancel-in-progress: false 15 | 16 | jobs: 17 | windows-build: 18 | strategy: 19 | fail-fast: false 20 | matrix: 21 | compiler: 22 | [ 23 | { c: "clang-cl", cxx: "clang-cl" }, 24 | # { c: "cl", cxx: "cl" }, 25 | ] 26 | name: Windows - ${{ matrix.compiler.cxx }} 27 | runs-on: windows-latest 28 | 29 | env: 30 | triplet: x64-windows 31 | 32 | steps: 33 | - uses: actions/checkout@v4 34 | with: 35 | submodules: true 36 | 37 | - name: Configure VS Toolchain 38 | uses: ilammy/msvc-dev-cmd@v1 39 | 40 | - name: Install dependencies 41 | run: vcpkg install yyjson fmt nameof gtest --triplet ${{ env.triplet }} 42 | 43 | - name: Build and test 44 | run: | 45 | rm -rf "${{ github.workspace }}\build" 46 | cmake -B "${{ github.workspace }}\build" -DCMAKE_TOOLCHAIN_FILE="$VCPKG_INSTALLATION_ROOT\\scripts\\buildsystems\\vcpkg.cmake" -DVCPKG_TARGET_TRIPLET=${{ env.triplet }} -DCMAKE_CXX_COMPILER=${{ matrix.compiler.cxx }} -G "Ninja Multi-Config" 47 | # cmake --build "${{ github.workspace }}\build" --config Debug --clean-first 48 | # ctest --test-dir "${{ github.workspace }}\build" -C Debug 49 | cmake --build "${{ github.workspace }}\build" --config Release --clean-first 50 | ctest --test-dir "${{ github.workspace }}\build" -C Release 51 | shell: bash 52 | 53 | ubuntu-build: 54 | strategy: 55 | fail-fast: false 56 | matrix: 57 | compiler: 58 | [ 59 | { c: "gcc-12", cxx: "g++-12" }, 60 | { c: "gcc-13", cxx: "g++-13" }, 61 | { c: "gcc-14", cxx: "g++-14" }, 62 | { 63 | c: "clang-16", 64 | cxx: "clang++-16", 65 | }, 66 | { 67 | c: "clang-17", 68 | cxx: "clang++-17", 69 | }, 70 | { 71 | c: "clang-18", 72 | cxx: "clang++-18", 73 | }, 74 | ] 75 | name: Ubuntu - ${{ matrix.compiler.cxx }} 76 | runs-on: ubuntu-24.04 77 | 78 | env: 79 | triplet: x64-linux 80 | 81 | steps: 82 | - uses: actions/checkout@v4 83 | with: 84 | submodules: true 85 | 86 | - name: Install compilers 87 | run: | 88 | eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)" 89 | brew install ninja 90 | 91 | - name: Install dependencies 92 | run: CC=${{ matrix.compiler.c }} CXX=${{ matrix.compiler.cxx }} vcpkg install yyjson fmt nameof gtest --triplet ${{ env.triplet }} 93 | 94 | - name: Build and test 95 | run: | 96 | eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)" 97 | rm -rf ${{ github.workspace }}/build 98 | cmake -B ${{ github.workspace }}/build -DCMAKE_TOOLCHAIN_FILE=$VCPKG_INSTALLATION_ROOT/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET=${{ env.triplet }} -DCMAKE_CXX_COMPILER=${{ matrix.compiler.cxx }} -G "Ninja Multi-Config" 99 | cmake --build ${{ github.workspace }}/build --config Debug --clean-first 100 | ctest --test-dir ${{ github.workspace }}/build -C Debug 101 | cmake --build ${{ github.workspace }}/build --config Release --clean-first 102 | ctest --test-dir ${{ github.workspace }}/build -C Release 103 | 104 | macos-build: 105 | strategy: 106 | fail-fast: false 107 | matrix: 108 | compiler: 109 | [ 110 | { c: "gcc-12", cxx: "g++-12", brewpkg: "", }, 111 | { c: "gcc-13", cxx: "g++-13", brewpkg: "", }, 112 | { c: "gcc-14", cxx: "g++-14", brewpkg: "", }, 113 | { 114 | c: "$(brew --prefix llvm@16)/bin/clang", 115 | cxx: "$(brew --prefix llvm@16)/bin/clang++", 116 | brewpkg: "llvm@16", 117 | }, 118 | { 119 | c: "$(brew --prefix llvm@17)/bin/clang", 120 | cxx: "$(brew --prefix llvm@17)/bin/clang++", 121 | brewpkg: "llvm@17", 122 | }, 123 | { 124 | c: "$(brew --prefix llvm@18)/bin/clang", 125 | cxx: "$(brew --prefix llvm@18)/bin/clang++", 126 | brewpkg: "llvm@18", 127 | }, 128 | ] 129 | name: MacOS - ${{ matrix.compiler.cxx }} 130 | runs-on: macos-latest 131 | 132 | env: 133 | triplet: arm64-osx 134 | 135 | steps: 136 | - uses: actions/checkout@v4 137 | with: 138 | submodules: true 139 | 140 | - name: Install compilers 141 | run: brew install ninja ${{ matrix.compiler.brewpkg }} 142 | 143 | - name: Install dependencies 144 | run: | 145 | git clone --depth 1 https://github.com/microsoft/vcpkg.git external/vcpkg 146 | ./external/vcpkg/bootstrap-vcpkg.sh 147 | CC=${{ matrix.compiler.c }} CXX=${{ matrix.compiler.cxx }} ./external/vcpkg/vcpkg install yyjson fmt nameof gtest --triplet ${{ env.triplet }} 148 | 149 | - name: Build and test 150 | run: | 151 | rm -rf ${{ github.workspace }}/build 152 | cmake -B ${{ github.workspace }}/build -DCMAKE_TOOLCHAIN_FILE=./external/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET=${{ env.triplet }} -DCMAKE_CXX_COMPILER=${{ matrix.compiler.cxx }} -G "Ninja Multi-Config" 153 | cmake --build ${{ github.workspace }}/build --config Debug --clean-first 154 | ctest --test-dir ${{ github.workspace }}/build -C Debug 155 | cmake --build ${{ github.workspace }}/build --config Release --clean-first 156 | ctest --test-dir ${{ github.workspace }}/build -C Release 157 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | 34 | # CMake 35 | CMakeLists.txt.user 36 | CMakeCache.txt 37 | CMakeFiles 38 | CMakeScripts 39 | Testing 40 | Makefile 41 | cmake_install.cmake 42 | install_manifest.txt 43 | compile_commands.json 44 | CTestTestfile.cmake 45 | _deps 46 | 47 | # build directory 48 | build/ 49 | 50 | # etc 51 | **/.vs/ 52 | **/.vscode/ 53 | **/.ccls-cache/ 54 | **/.clangd/ 55 | **/.cache/ 56 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "external/yyjson_benchmark"] 2 | path = external/yyjson_benchmark 3 | url = https://github.com/ibireme/yyjson_benchmark.git 4 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | project( 3 | cpp_yyjson 4 | VERSION 0.6.0 5 | LANGUAGES CXX) 6 | 7 | # check if the project is top-level 8 | if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) 9 | set(CPPYYJSON_IS_TOPLEVEL_PROJECT ON) 10 | else() 11 | set(CPPYYJSON_IS_TOPLEVEL_PROJECT OFF) 12 | endif() 13 | 14 | # options 15 | option(CPPYYJSON_BUILD_TEST "Build ${PROJECT_NAME} tests" 16 | ${CPPYYJSON_IS_TOPLEVEL_PROJECT}) 17 | option(CPPYYJSON_BUILD_BENCH "Build ${PROJECT_NAME} tests and benchmarks" OFF) 18 | 19 | # library 20 | include(GNUInstallDirs) 21 | add_library(${PROJECT_NAME} INTERFACE) 22 | add_library(${PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME}) 23 | target_compile_features(${PROJECT_NAME} INTERFACE cxx_std_20) 24 | target_include_directories( 25 | ${PROJECT_NAME} 26 | INTERFACE $ 27 | $) 28 | set_target_properties(${PROJECT_NAME} PROPERTIES VERSION ${PROJECT_VERSION}) 29 | 30 | # for MSVC 31 | if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") 32 | target_compile_options(${PROJECT_NAME} INTERFACE /Zc:preprocessor) 33 | endif() 34 | 35 | # dependencies 36 | function(find_and_link package_name qualified_name) 37 | cmake_parse_arguments(FIND_AND_LINK "" "VERSION" "" ${ARGN}) 38 | if(NOT TARGET ${package_name} OR CPPYYJSON_IS_TOPLEVEL_PROJECT) 39 | find_package(${package_name} ${FIND_AND_LINK_VERSION} CONFIG REQUIRED) 40 | target_link_libraries(${PROJECT_NAME} INTERFACE ${qualified_name}) 41 | else() 42 | target_link_libraries(${PROJECT_NAME} INTERFACE ${package_name}) 43 | endif() 44 | endfunction() 45 | 46 | find_and_link(yyjson yyjson::yyjson) 47 | find_and_link(fmt fmt::fmt-header-only VERSION 10.0.0) 48 | find_and_link(nameof nameof::nameof VERSION 0.10.0) 49 | 50 | # install 51 | if(CPPYYJSON_IS_TOPLEVEL_PROJECT) 52 | install(TARGETS ${PROJECT_NAME} EXPORT ${PROJECT_NAME}_Targets) 53 | 54 | install( 55 | EXPORT ${PROJECT_NAME}_Targets 56 | FILE ${PROJECT_NAME}Targets.cmake 57 | NAMESPACE ${PROJECT_NAME}:: 58 | DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}) 59 | 60 | include(CMakePackageConfigHelpers) 61 | write_basic_package_version_file( 62 | ${PROJECT_NAME}ConfigVersion.cmake COMPATIBILITY SameMajorVersion 63 | ARCH_INDEPENDENT) 64 | configure_package_config_file( 65 | "${PROJECT_SOURCE_DIR}/cmake/${PROJECT_NAME}Config.cmake.in" 66 | "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" 67 | INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}) 68 | 69 | # install config files 70 | install(FILES "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" 71 | "${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake" 72 | DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}) 73 | 74 | # install header files 75 | install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/ 76 | DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) 77 | endif() 78 | 79 | # test and benchmark 80 | if(CPPYYJSON_BUILD_TEST OR CPPYYJSON_BUILD_BENCH) 81 | enable_testing() 82 | add_subdirectory(test) 83 | endif() 84 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Yoshiki Matsuda 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /cmake/cpp_yyjsonConfig.cmake.in: -------------------------------------------------------------------------------- 1 | @PACKAGE_INIT@ 2 | 3 | set(CPPYYJSON_VERSION @PROJECT_VERSION@) 4 | 5 | include(CMakeFindDependencyMacro) 6 | find_dependency(yyjson CONFIG REQUIRED) 7 | find_dependency(fmt 10.0.0 CONFIG REQUIRED) 8 | find_dependency(nameof CONFIG REQUIRED) 9 | 10 | include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake") 11 | check_required_components("@PROJECT_NAME@") 12 | -------------------------------------------------------------------------------- /include/field_reflection.hpp: -------------------------------------------------------------------------------- 1 | /*===================================================* 2 | | field-reflection version v0.2.1 | 3 | | https://github.com/yosh-matsuda/field-reflection | 4 | | | 5 | | Copyright (c) 2024 Yoshiki Matsuda @yosh-matsuda | 6 | | | 7 | | This software is released under the MIT License. | 8 | | https://opensource.org/license/mit/ | 9 | ====================================================*/ 10 | 11 | #pragma once 12 | 13 | #include // CHAR_BIT 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | namespace field_reflection 22 | { 23 | namespace detail 24 | { 25 | 26 | #if defined(__GNUC__) || defined(__clang__) 27 | #pragma GCC diagnostic push 28 | #pragma GCC diagnostic ignored "-Wundefined-inline" 29 | #endif 30 | template 31 | struct any_lref 32 | { 33 | template 34 | requires (!std::same_as) 35 | constexpr operator U&() const&& noexcept; // NOLINT 36 | template 37 | requires (!std::same_as) 38 | constexpr operator U&() const& noexcept; // NOLINT 39 | }; 40 | 41 | template 42 | struct any_rref 43 | { 44 | template 45 | requires (!std::same_as) 46 | constexpr operator U() const&& noexcept; // NOLINT 47 | }; 48 | 49 | template 50 | struct any_lref_no_base 51 | { 52 | template 53 | requires (!std::is_base_of_v && !std::same_as) 54 | constexpr operator U&() const&& noexcept; // NOLINT 55 | template 56 | requires (!std::is_base_of_v && !std::same_as) 57 | constexpr operator U&() const& noexcept; // NOLINT 58 | }; 59 | 60 | template 61 | struct any_rref_no_base 62 | { 63 | template 64 | requires (!std::is_base_of_v && !std::same_as) 65 | constexpr operator U() const&& noexcept; // NOLINT 66 | }; 67 | 68 | template 69 | struct any_lref_base 70 | { 71 | template 72 | requires std::is_base_of_v 73 | constexpr operator U&() const&& noexcept; // NOLINT 74 | template 75 | requires std::is_base_of_v 76 | constexpr operator U&() const& noexcept; // NOLINT 77 | }; 78 | 79 | template 80 | struct any_rref_base 81 | { 82 | template 83 | requires std::is_base_of_v 84 | constexpr operator U() const&& noexcept; // NOLINT 85 | }; 86 | #if defined(__GNUC__) || defined(__clang__) 87 | #pragma GCC diagnostic pop 88 | #endif 89 | 90 | template 91 | concept constructible = []() { 92 | if constexpr (ArgNum == 0) 93 | { 94 | return requires { T{}; }; 95 | } 96 | else if constexpr (std::is_copy_constructible_v) 97 | { 98 | return [](std::index_sequence) { 99 | return requires { T{std::declval>(), std::declval>()...}; }; 100 | }(std::make_index_sequence()); 101 | } 102 | else 103 | { 104 | return [](std::index_sequence) { 105 | return requires { T{std::declval>(), std::declval>()...}; }; 106 | }(std::make_index_sequence()); 107 | } 108 | }(); 109 | 110 | template 111 | concept has_base = []() { 112 | if constexpr (std::is_copy_constructible_v) 113 | { 114 | return requires { T{std::declval>()}; }; 115 | } 116 | else 117 | { 118 | return requires { T{std::declval>()}; }; 119 | } 120 | }(); 121 | 122 | constexpr std::size_t macro_max_fields_count = 100; 123 | template 124 | constexpr auto max_field_count = 125 | std::min(std::size_t{macro_max_fields_count}, sizeof(T) * CHAR_BIT); // in consideration of bit field 126 | 127 | template 128 | requires std::is_aggregate_v 129 | constexpr std::size_t field_count_impl = []() { 130 | if constexpr (N >= max_field_count) 131 | { 132 | return std::numeric_limits::max(); 133 | } 134 | else if constexpr (constructible && !constructible) 135 | { 136 | return N; 137 | } 138 | else 139 | { 140 | return field_count_impl; 141 | } 142 | }(); 143 | 144 | template 145 | requires std::is_aggregate_v 146 | constexpr std::size_t field_count_value = field_count_impl; 147 | 148 | template 149 | concept field_countable = 150 | std::is_aggregate_v && requires { requires field_count_value <= max_field_count; }; 151 | 152 | template 153 | constexpr std::size_t field_count = field_count_value; 154 | 155 | template 156 | concept field_referenceable = field_countable && (!has_base); 157 | 158 | template > 159 | constexpr auto to_ptr_tuple(T&&) 160 | { 161 | static_assert([] { return false; }(), "The supported maximum number of fields in struct must be <= 100."); 162 | } 163 | template > 164 | requires (field_count == 0) 165 | constexpr auto to_ptr_tuple(T&&) 166 | { 167 | return std::tie(); 168 | } 169 | template > 170 | requires (field_count == 0) 171 | constexpr auto to_tuple(T&&) 172 | { 173 | return std::tie(); 174 | } 175 | 176 | #pragma region TO_TUPLE_TEMPLATE_MACRO 177 | // map macro: https://github.com/swansontec/map-macro 178 | #define FIELD_RFL_EVAL0(...) __VA_ARGS__ 179 | #define FIELD_RFL_EVAL1(...) FIELD_RFL_EVAL0(FIELD_RFL_EVAL0(FIELD_RFL_EVAL0(__VA_ARGS__))) 180 | #define FIELD_RFL_EVAL2(...) FIELD_RFL_EVAL1(FIELD_RFL_EVAL1(FIELD_RFL_EVAL1(__VA_ARGS__))) 181 | #define FIELD_RFL_EVAL3(...) FIELD_RFL_EVAL2(FIELD_RFL_EVAL2(FIELD_RFL_EVAL2(__VA_ARGS__))) 182 | #define FIELD_RFL_EVAL4(...) FIELD_RFL_EVAL3(FIELD_RFL_EVAL3(FIELD_RFL_EVAL3(__VA_ARGS__))) 183 | #define FIELD_RFL_EVAL(...) FIELD_RFL_EVAL4(FIELD_RFL_EVAL4(FIELD_RFL_EVAL4(__VA_ARGS__))) 184 | 185 | #define FIELD_RFL_MAP_END(...) 186 | #define FIELD_RFL_MAP_OUT 187 | #define FIELD_RFL_MAP_COMMA , 188 | 189 | #define FIELD_RFL_MAP_GET_END2() 0, FIELD_RFL_MAP_END 190 | #define FIELD_RFL_MAP_GET_END1(...) FIELD_RFL_MAP_GET_END2 191 | #define FIELD_RFL_MAP_GET_END(...) FIELD_RFL_MAP_GET_END1 192 | #define FIELD_RFL_MAP_NEXT0(test, next, ...) next FIELD_RFL_MAP_OUT 193 | #define FIELD_RFL_MAP_NEXT1(test, next) FIELD_RFL_MAP_NEXT0(test, next, 0) 194 | #define FIELD_RFL_MAP_NEXT(test, next) FIELD_RFL_MAP_NEXT1(FIELD_RFL_MAP_GET_END test, next) 195 | 196 | #define FIELD_RFL_MAP0(f, x, peek, ...) f(x) FIELD_RFL_MAP_NEXT(peek, FIELD_RFL_MAP1)(f, peek, __VA_ARGS__) 197 | #define FIELD_RFL_MAP1(f, x, peek, ...) f(x) FIELD_RFL_MAP_NEXT(peek, FIELD_RFL_MAP0)(f, peek, __VA_ARGS__) 198 | 199 | #define FIELD_RFL_MAP_LIST_NEXT1(test, next) FIELD_RFL_MAP_NEXT0(test, FIELD_RFL_MAP_COMMA next, 0) 200 | #define FIELD_RFL_MAP_LIST_NEXT(test, next) FIELD_RFL_MAP_LIST_NEXT1(FIELD_RFL_MAP_GET_END test, next) 201 | 202 | #define FIELD_RFL_MAP_LIST0(f, x, peek, ...) \ 203 | f(x) FIELD_RFL_MAP_LIST_NEXT(peek, FIELD_RFL_MAP_LIST1)(f, peek, __VA_ARGS__) 204 | #define FIELD_RFL_MAP_LIST1(f, x, peek, ...) \ 205 | f(x) FIELD_RFL_MAP_LIST_NEXT(peek, FIELD_RFL_MAP_LIST0)(f, peek, __VA_ARGS__) 206 | #define FIELD_RFL_MAP(f, ...) FIELD_RFL_EVAL(FIELD_RFL_MAP1(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) 207 | #define FIELD_RFL_MAP_LIST(f, ...) FIELD_RFL_EVAL(FIELD_RFL_MAP_LIST1(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) 208 | 209 | #define FIELD_RFL_ADDR(x) &x 210 | #define FIELD_RFL_DECLTYPE(x) decltype(x) 211 | #define FIELD_RFL_FORWARD(x) std::forward(x) 212 | 213 | #define TO_TUPLE_TEMPLATE(NUM, ...) \ 214 | template > \ 215 | requires (field_count == NUM) \ 216 | constexpr auto to_ptr_tuple(T&& t) \ 217 | { \ 218 | auto& [__VA_ARGS__] = t; \ 219 | return std::tuple(FIELD_RFL_MAP_LIST(FIELD_RFL_ADDR, __VA_ARGS__)); \ 220 | } \ 221 | template > \ 222 | requires (field_count == NUM) \ 223 | constexpr auto to_tuple(T&& t) \ 224 | { \ 225 | auto [__VA_ARGS__] = std::forward(t); \ 226 | return std::tuple( \ 227 | FIELD_RFL_MAP_LIST(FIELD_RFL_FORWARD, __VA_ARGS__)); \ 228 | } 229 | 230 | TO_TUPLE_TEMPLATE(1, p0) 231 | TO_TUPLE_TEMPLATE(2, p0, p1) 232 | TO_TUPLE_TEMPLATE(3, p0, p1, p2) 233 | TO_TUPLE_TEMPLATE(4, p0, p1, p2, p3) 234 | TO_TUPLE_TEMPLATE(5, p0, p1, p2, p3, p4) 235 | TO_TUPLE_TEMPLATE(6, p0, p1, p2, p3, p4, p5) 236 | TO_TUPLE_TEMPLATE(7, p0, p1, p2, p3, p4, p5, p6) 237 | TO_TUPLE_TEMPLATE(8, p0, p1, p2, p3, p4, p5, p6, p7) 238 | TO_TUPLE_TEMPLATE(9, p0, p1, p2, p3, p4, p5, p6, p7, p8) 239 | TO_TUPLE_TEMPLATE(10, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9) 240 | TO_TUPLE_TEMPLATE(11, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10) 241 | TO_TUPLE_TEMPLATE(12, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11) 242 | TO_TUPLE_TEMPLATE(13, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12) 243 | TO_TUPLE_TEMPLATE(14, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13) 244 | TO_TUPLE_TEMPLATE(15, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14) 245 | TO_TUPLE_TEMPLATE(16, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15) 246 | TO_TUPLE_TEMPLATE(17, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16) 247 | TO_TUPLE_TEMPLATE(18, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17) 248 | TO_TUPLE_TEMPLATE(19, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18) 249 | TO_TUPLE_TEMPLATE(20, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19) 250 | TO_TUPLE_TEMPLATE(21, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 251 | p20) 252 | TO_TUPLE_TEMPLATE(22, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 253 | p20, p21) 254 | TO_TUPLE_TEMPLATE(23, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 255 | p20, p21, p22) 256 | TO_TUPLE_TEMPLATE(24, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 257 | p20, p21, p22, p23) 258 | TO_TUPLE_TEMPLATE(25, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 259 | p20, p21, p22, p23, p24) 260 | TO_TUPLE_TEMPLATE(26, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 261 | p20, p21, p22, p23, p24, p25) 262 | TO_TUPLE_TEMPLATE(27, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 263 | p20, p21, p22, p23, p24, p25, p26) 264 | TO_TUPLE_TEMPLATE(28, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 265 | p20, p21, p22, p23, p24, p25, p26, p27) 266 | TO_TUPLE_TEMPLATE(29, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 267 | p20, p21, p22, p23, p24, p25, p26, p27, p28) 268 | TO_TUPLE_TEMPLATE(30, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 269 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29) 270 | TO_TUPLE_TEMPLATE(31, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 271 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30) 272 | TO_TUPLE_TEMPLATE(32, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 273 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31) 274 | TO_TUPLE_TEMPLATE(33, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 275 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32) 276 | TO_TUPLE_TEMPLATE(34, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 277 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33) 278 | TO_TUPLE_TEMPLATE(35, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 279 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34) 280 | TO_TUPLE_TEMPLATE(36, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 281 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35) 282 | TO_TUPLE_TEMPLATE(37, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 283 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36) 284 | TO_TUPLE_TEMPLATE(38, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 285 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37) 286 | TO_TUPLE_TEMPLATE(39, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 287 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38) 288 | TO_TUPLE_TEMPLATE(40, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 289 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 290 | p39) 291 | TO_TUPLE_TEMPLATE(41, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 292 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 293 | p39, p40) 294 | TO_TUPLE_TEMPLATE(42, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 295 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 296 | p39, p40, p41) 297 | TO_TUPLE_TEMPLATE(43, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 298 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 299 | p39, p40, p41, p42) 300 | TO_TUPLE_TEMPLATE(44, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 301 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 302 | p39, p40, p41, p42, p43) 303 | TO_TUPLE_TEMPLATE(45, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 304 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 305 | p39, p40, p41, p42, p43, p44) 306 | TO_TUPLE_TEMPLATE(46, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 307 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 308 | p39, p40, p41, p42, p43, p44, p45) 309 | TO_TUPLE_TEMPLATE(47, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 310 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 311 | p39, p40, p41, p42, p43, p44, p45, p46) 312 | TO_TUPLE_TEMPLATE(48, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 313 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 314 | p39, p40, p41, p42, p43, p44, p45, p46, p47) 315 | TO_TUPLE_TEMPLATE(49, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 316 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 317 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48) 318 | TO_TUPLE_TEMPLATE(50, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 319 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 320 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49) 321 | TO_TUPLE_TEMPLATE(51, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 322 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 323 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50) 324 | TO_TUPLE_TEMPLATE(52, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 325 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 326 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51) 327 | TO_TUPLE_TEMPLATE(53, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 328 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 329 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52) 330 | TO_TUPLE_TEMPLATE(54, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 331 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 332 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53) 333 | TO_TUPLE_TEMPLATE(55, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 334 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 335 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54) 336 | TO_TUPLE_TEMPLATE(56, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 337 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 338 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55) 339 | TO_TUPLE_TEMPLATE(57, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 340 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 341 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56) 342 | TO_TUPLE_TEMPLATE(58, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 343 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 344 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57) 345 | TO_TUPLE_TEMPLATE(59, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 346 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 347 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 348 | p58) 349 | TO_TUPLE_TEMPLATE(60, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 350 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 351 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 352 | p58, p59) 353 | TO_TUPLE_TEMPLATE(61, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 354 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 355 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 356 | p58, p59, p60) 357 | TO_TUPLE_TEMPLATE(62, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 358 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 359 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 360 | p58, p59, p60, p61) 361 | TO_TUPLE_TEMPLATE(63, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 362 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 363 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 364 | p58, p59, p60, p61, p62) 365 | TO_TUPLE_TEMPLATE(64, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 366 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 367 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 368 | p58, p59, p60, p61, p62, p63) 369 | TO_TUPLE_TEMPLATE(65, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 370 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 371 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 372 | p58, p59, p60, p61, p62, p63, p64) 373 | TO_TUPLE_TEMPLATE(66, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 374 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 375 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 376 | p58, p59, p60, p61, p62, p63, p64, p65) 377 | TO_TUPLE_TEMPLATE(67, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 378 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 379 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 380 | p58, p59, p60, p61, p62, p63, p64, p65, p66) 381 | TO_TUPLE_TEMPLATE(68, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 382 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 383 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 384 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67) 385 | TO_TUPLE_TEMPLATE(69, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 386 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 387 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 388 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68) 389 | TO_TUPLE_TEMPLATE(70, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 390 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 391 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 392 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69) 393 | TO_TUPLE_TEMPLATE(71, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 394 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 395 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 396 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70) 397 | TO_TUPLE_TEMPLATE(72, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 398 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 399 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 400 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71) 401 | TO_TUPLE_TEMPLATE(73, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 402 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 403 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 404 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72) 405 | TO_TUPLE_TEMPLATE(74, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 406 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 407 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 408 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73) 409 | TO_TUPLE_TEMPLATE(75, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 410 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 411 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 412 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74) 413 | TO_TUPLE_TEMPLATE(76, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 414 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 415 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 416 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75) 417 | TO_TUPLE_TEMPLATE(77, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 418 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 419 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 420 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76) 421 | TO_TUPLE_TEMPLATE(78, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 422 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 423 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 424 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, 425 | p77) 426 | TO_TUPLE_TEMPLATE(79, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 427 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 428 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 429 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, 430 | p77, p78) 431 | TO_TUPLE_TEMPLATE(80, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 432 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 433 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 434 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, 435 | p77, p78, p79) 436 | TO_TUPLE_TEMPLATE(81, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 437 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 438 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 439 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, 440 | p77, p78, p79, p80) 441 | TO_TUPLE_TEMPLATE(82, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 442 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 443 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 444 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, 445 | p77, p78, p79, p80, p81) 446 | TO_TUPLE_TEMPLATE(83, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 447 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 448 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 449 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, 450 | p77, p78, p79, p80, p81, p82) 451 | TO_TUPLE_TEMPLATE(84, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 452 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 453 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 454 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, 455 | p77, p78, p79, p80, p81, p82, p83) 456 | TO_TUPLE_TEMPLATE(85, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 457 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 458 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 459 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, 460 | p77, p78, p79, p80, p81, p82, p83, p84) 461 | TO_TUPLE_TEMPLATE(86, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 462 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 463 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 464 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, 465 | p77, p78, p79, p80, p81, p82, p83, p84, p85) 466 | TO_TUPLE_TEMPLATE(87, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 467 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 468 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 469 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, 470 | p77, p78, p79, p80, p81, p82, p83, p84, p85, p86) 471 | TO_TUPLE_TEMPLATE(88, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 472 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 473 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 474 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, 475 | p77, p78, p79, p80, p81, p82, p83, p84, p85, p86, p87) 476 | TO_TUPLE_TEMPLATE(89, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 477 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 478 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 479 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, 480 | p77, p78, p79, p80, p81, p82, p83, p84, p85, p86, p87, p88) 481 | TO_TUPLE_TEMPLATE(90, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 482 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 483 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 484 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, 485 | p77, p78, p79, p80, p81, p82, p83, p84, p85, p86, p87, p88, p89) 486 | TO_TUPLE_TEMPLATE(91, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 487 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 488 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 489 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, 490 | p77, p78, p79, p80, p81, p82, p83, p84, p85, p86, p87, p88, p89, p90) 491 | TO_TUPLE_TEMPLATE(92, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 492 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 493 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 494 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, 495 | p77, p78, p79, p80, p81, p82, p83, p84, p85, p86, p87, p88, p89, p90, p91) 496 | TO_TUPLE_TEMPLATE(93, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 497 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 498 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 499 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, 500 | p77, p78, p79, p80, p81, p82, p83, p84, p85, p86, p87, p88, p89, p90, p91, p92) 501 | TO_TUPLE_TEMPLATE(94, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 502 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 503 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 504 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, 505 | p77, p78, p79, p80, p81, p82, p83, p84, p85, p86, p87, p88, p89, p90, p91, p92, p93) 506 | TO_TUPLE_TEMPLATE(95, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 507 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 508 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 509 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, 510 | p77, p78, p79, p80, p81, p82, p83, p84, p85, p86, p87, p88, p89, p90, p91, p92, p93, p94) 511 | TO_TUPLE_TEMPLATE(96, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 512 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 513 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 514 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, 515 | p77, p78, p79, p80, p81, p82, p83, p84, p85, p86, p87, p88, p89, p90, p91, p92, p93, p94, p95) 516 | TO_TUPLE_TEMPLATE(97, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 517 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 518 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 519 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, 520 | p77, p78, p79, p80, p81, p82, p83, p84, p85, p86, p87, p88, p89, p90, p91, p92, p93, p94, p95, 521 | p96) 522 | TO_TUPLE_TEMPLATE(98, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 523 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 524 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 525 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, 526 | p77, p78, p79, p80, p81, p82, p83, p84, p85, p86, p87, p88, p89, p90, p91, p92, p93, p94, p95, 527 | p96, p97) 528 | TO_TUPLE_TEMPLATE(99, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 529 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 530 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 531 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, 532 | p77, p78, p79, p80, p81, p82, p83, p84, p85, p86, p87, p88, p89, p90, p91, p92, p93, p94, p95, 533 | p96, p97, p98) 534 | TO_TUPLE_TEMPLATE(100, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 535 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 536 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 537 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, 538 | p77, p78, p79, p80, p81, p82, p83, p84, p85, p86, p87, p88, p89, p90, p91, p92, p93, p94, p95, 539 | p96, p97, p98, p99) 540 | #undef FIELD_RFL_EVAL0 541 | #undef FIELD_RFL_EVAL1 542 | #undef FIELD_RFL_EVAL2 543 | #undef FIELD_RFL_EVAL3 544 | #undef FIELD_RFL_EVAL4 545 | #undef FIELD_RFL_EVAL 546 | #undef FIELD_RFL_MAP_END 547 | #undef FIELD_RFL_MAP_OUT 548 | #undef FIELD_RFL_MAP_COMMA 549 | #undef FIELD_RFL_MAP_GET_END2 550 | #undef FIELD_RFL_MAP_GET_END1 551 | #undef FIELD_RFL_MAP_GET_END 552 | #undef FIELD_RFL_MAP_NEXT0 553 | #undef FIELD_RFL_MAP_NEXT1 554 | #undef FIELD_RFL_MAP_NEXT 555 | #undef FIELD_RFL_MAP0 556 | #undef FIELD_RFL_MAP1 557 | #undef FIELD_RFL_MAP_LIST_NEXT1 558 | #undef FIELD_RFL_MAP_LIST_NEXT 559 | #undef FIELD_RFL_MAP_LIST0 560 | #undef FIELD_RFL_MAP_LIST1 561 | #undef FIELD_RFL_MAP 562 | #undef FIELD_RFL_MAP_LIST 563 | #undef FIELD_RFL_DECLTYPE 564 | #undef FIELD_RFL_MOVE 565 | #undef FIELD_RFL_TO_TUPLE_TEMPLATE 566 | #pragma endregion TO_TUPLE_TEMPLATE_MACRO 567 | 568 | #if defined(__clang__) 569 | #pragma clang diagnostic push 570 | #pragma clang diagnostic ignored "-Wundefined-internal" 571 | #pragma clang diagnostic ignored "-Wundefined-var-template" 572 | #elif defined(__GNUC__) 573 | #elif defined(_MSC_VER) 574 | #else 575 | #endif 576 | 577 | template 578 | struct wrapper 579 | { 580 | explicit constexpr wrapper(const T& v) : value(v) {} 581 | T value; 582 | static wrapper fake; // NOLINT 583 | }; 584 | 585 | template // NOLINT 586 | consteval auto get_ptr() noexcept 587 | { 588 | #if defined(__clang__) 589 | return wrapper(std::get(to_ptr_tuple(wrapper::fake.value))); 590 | #else 591 | return std::get(to_ptr_tuple(wrapper::fake.value)); 592 | #endif 593 | } 594 | 595 | #if defined(__clang__) 596 | #pragma clang diagnostic pop 597 | #elif __GNUC__ 598 | #elif defined(_MSC_VER) 599 | #else 600 | #endif 601 | 602 | template 603 | using nontype_template_parameter_helper = void; 604 | 605 | template // clang-format off 606 | concept field_namable = field_referenceable && (field_count > 0) && requires { 607 | typename nontype_template_parameter_helper()>; 608 | }; // clang-format on 609 | 610 | template 611 | consteval std::string_view get_function_name() 612 | { 613 | #if defined(__clang__) && defined(_WIN32) 614 | // clang-cl returns function_name() as __FUNCTION__ instead of __PRETTY_FUNCTION__ 615 | return std::string_view{__PRETTY_FUNCTION__}; 616 | #else 617 | return std::string_view{std::source_location::current().function_name()}; 618 | #endif 619 | } 620 | 621 | template 622 | consteval std::string_view get_field_name() 623 | { 624 | struct field_name_detector 625 | { 626 | void* dummy; 627 | }; 628 | 629 | constexpr auto detector_name = get_function_name()>(); 630 | constexpr auto dummy_begin = detector_name.rfind(std::string_view("dummy")); 631 | constexpr auto suffix = detector_name.substr(dummy_begin + std::string_view("dummy").size()); 632 | constexpr auto begin_sentinel = detector_name[dummy_begin - 1]; 633 | 634 | const auto field_name_raw = get_function_name(); 635 | const auto last = field_name_raw.rfind(suffix); 636 | const auto begin = field_name_raw.rfind(begin_sentinel, last - 1) + 1; 637 | 638 | assert(begin < field_name_raw.size()); 639 | assert(last <= field_name_raw.size()); 640 | assert(begin < last); 641 | 642 | return field_name_raw.substr(begin, last - begin); 643 | } 644 | 645 | template 646 | using remove_rvalue_reference_t = 647 | std::conditional_t, std::remove_reference_t, T>; 648 | 649 | template 650 | constexpr std::string_view field_name = get_field_name()>(); 651 | 652 | template 653 | using field_type = remove_rvalue_reference_t(to_tuple(std::declval())))>; 654 | 655 | template > 656 | constexpr decltype(auto) get_field(T& t) noexcept 657 | { 658 | return *std::get(to_ptr_tuple(t)); 659 | } 660 | 661 | template > 662 | requires std::is_rvalue_reference_v 663 | constexpr auto get_field(T&& t) noexcept 664 | { 665 | return std::get(to_tuple(std::forward(t))); 666 | } 667 | 668 | template > 669 | void for_each_field_impl(T&& t, Func&& func, std::index_sequence) 670 | { 671 | if constexpr (requires { (func(get_field(t)), ...); }) 672 | { 673 | (func(get_field(t)), ...); 674 | } 675 | else if constexpr (requires { (func(field_name, get_field(t)), ...); }) 676 | { 677 | (func(field_name, get_field(t)), ...); 678 | } 679 | else 680 | { 681 | static_assert([] { return false; }(), "invalid function object for call to for_each_field"); 682 | } 683 | } 684 | 685 | template > 687 | void for_each_field_impl(T1&& t1, T2&& t2, Func&& func, std::index_sequence) 688 | { 689 | if constexpr (requires { (func(get_field(t1), get_field(t2)), ...); }) 690 | { 691 | (func(get_field(t1), get_field(t2)), ...); 692 | } 693 | else if constexpr (requires { (func(field_name, get_field(t1), get_field(t2)), ...); }) 694 | { 695 | (func(field_name, get_field(t1), get_field(t2)), ...); 696 | } 697 | else 698 | { 699 | static_assert([] { return false; }(), "invalid function object for call to for_each_field"); 700 | } 701 | } 702 | 703 | template > 704 | bool all_of_field_impl(T&& t, Func&& func, std::index_sequence) 705 | { 706 | if constexpr (requires { (func(get_field(t)) && ...); }) 707 | { 708 | return (func(get_field(t)) && ...); 709 | } 710 | else if constexpr (requires { (func(field_name, get_field(t)) && ...); }) 711 | { 712 | return (func(field_name, get_field(t)) && ...); 713 | } 714 | else 715 | { 716 | static_assert([] { return false; }(), "invalid function object for call to all_of_field"); 717 | } 718 | } 719 | 720 | template > 722 | bool all_of_field_impl(T1&& t1, T2&& t2, Func&& func, std::index_sequence) 723 | { 724 | if constexpr (requires { (func(get_field(t1), get_field(t2)) && ...); }) 725 | { 726 | return (func(get_field(t1), get_field(t2)) && ...); 727 | } 728 | else if constexpr (requires { (func(field_name, get_field(t1), get_field(t2)) && ...); }) 729 | { 730 | return (func(field_name, get_field(t1), get_field(t2)) && ...); 731 | } 732 | else 733 | { 734 | static_assert([] { return false; }(), "invalid function object for call to all_of_field"); 735 | } 736 | } 737 | 738 | template > 739 | bool any_of_field_impl(T&& t, Func&& func, std::index_sequence) 740 | { 741 | if constexpr (requires { (func(get_field(t)) || ...); }) 742 | { 743 | return (func(get_field(t)) || ...); 744 | } 745 | else if constexpr (requires { (func(field_name, get_field(t)) || ...); }) 746 | { 747 | return (func(field_name, get_field(t)) || ...); 748 | } 749 | else 750 | { 751 | static_assert([] { return false; }(), "invalid function object for call to any_of_field"); 752 | } 753 | } 754 | 755 | template > 757 | bool any_of_field_impl(T1&& t1, T2&& t2, Func&& func, std::index_sequence) 758 | { 759 | if constexpr (requires { (func(get_field(t1), get_field(t2)) || ...); }) 760 | { 761 | return (func(get_field(t1), get_field(t2)) || ...); 762 | } 763 | else if constexpr (requires { (func(field_name, get_field(t1), get_field(t2)) || ...); }) 764 | { 765 | return (func(field_name, get_field(t1), get_field(t2)) || ...); 766 | } 767 | else 768 | { 769 | static_assert([] { return false; }(), "invalid function object for call to any_of_field"); 770 | } 771 | } 772 | } // namespace detail 773 | 774 | using detail::field_count; 775 | using detail::field_countable; 776 | using detail::field_namable; 777 | using detail::field_name; 778 | using detail::field_referenceable; 779 | using detail::field_type; 780 | using detail::get_field; 781 | using detail::to_tuple; 782 | 783 | template , 784 | field_referenceable U2 = std::remove_cvref_t> 785 | requires std::is_same_v 786 | void for_each_field(T1&& t1, T2&& t2, Func&& func) 787 | { 788 | detail::for_each_field_impl(std::forward(t1), std::forward(t2), std::forward(func), 789 | std::make_index_sequence>()); 790 | } 791 | 792 | template > 793 | void for_each_field(T&& t, Func&& func) 794 | { 795 | detail::for_each_field_impl(std::forward(t), std::forward(func), 796 | std::make_index_sequence>()); 797 | } 798 | 799 | template , 800 | field_referenceable U2 = std::remove_cvref_t> 801 | requires std::is_same_v 802 | bool all_of_field(T1&& t1, T2&& t2, Func&& func) 803 | { 804 | return detail::all_of_field_impl(std::forward(t1), std::forward(t2), std::forward(func), 805 | std::make_index_sequence>()); 806 | } 807 | 808 | template > 809 | bool all_of_field(T&& t, Func&& func) 810 | { 811 | return detail::all_of_field_impl(std::forward(t), std::forward(func), 812 | std::make_index_sequence>()); 813 | } 814 | 815 | template , 816 | field_referenceable U2 = std::remove_cvref_t> 817 | requires std::is_same_v 818 | bool any_of_field(T1&& t1, T2&& t2, Func&& func) 819 | { 820 | return detail::any_of_field_impl(std::forward(t1), std::forward(t2), std::forward(func), 821 | std::make_index_sequence>()); 822 | } 823 | 824 | template > 825 | bool any_of_field(T&& t, Func&& func) 826 | { 827 | return detail::any_of_field_impl(std::forward(t), std::forward(func), 828 | std::make_index_sequence>()); 829 | } 830 | } // namespace field_reflection 831 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | 3 | # 4 | # COMPILER/LINKER FLAGS 5 | # 6 | set(CMAKE_CXX_STANDARD 20) 7 | set(CMAKE_CXX_EXTENSIONS OFF) 8 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 9 | set(ENV{CMAKE_EXPORT_COMPILE_COMMANDS} ON) 10 | 11 | if(NOT MSVC) 12 | # Warnings 13 | set(CMAKE_CXX_FLAGS 14 | "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wcast-align -Wcast-qual -Wdelete-non-virtual-dtor -Wold-style-cast -Woverloaded-virtual -Wpointer-arith -Wfloat-equal -Winit-self -Wredundant-decls -Wsign-promo -Wswitch-default -Wswitch-enum -Wvariadic-macros -Wwrite-strings -Wno-unknown-pragmas" 15 | ) 16 | 17 | if("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") 18 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wshadow") 19 | elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") 20 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wshadow=local -Wno-pragmas") 21 | endif() 22 | else() # MSVC including clang-cl 23 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4 /utf-8") 24 | set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") 25 | endif() 26 | 27 | # O3 optimization 28 | if(NOT MSVC) 29 | string(REPLACE "-O2" "-O3" CMAKE_CXX_FLAGS_RELWITHDEBINFO 30 | ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}) 31 | string(REPLACE "-O2" "-O3" CMAKE_CXX_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELEASE}) 32 | endif() 33 | 34 | # GTest 35 | find_package(GTest REQUIRED) 36 | include_directories(${GTEST_INCLUDE_DIRS}) 37 | 38 | # executables 39 | add_executable("${PROJECT_NAME}_test" test.cpp) 40 | target_link_libraries("${PROJECT_NAME}_test" 41 | PRIVATE ${PROJECT_NAME} GTest::gtest GTest::gtest_main) 42 | 43 | # add google test 44 | include(GoogleTest) 45 | gtest_discover_tests("${PROJECT_NAME}_test" DISCOVERY_MODE PRE_TEST) 46 | 47 | # benchmark 48 | if(CPPYYJSON_BUILD_BENCH) 49 | # Google benchmark 50 | find_package(benchmark REQUIRED) 51 | 52 | # JSON libraries 53 | find_package(simdjson CONFIG REQUIRED) 54 | find_package(RapidJSON CONFIG REQUIRED) 55 | find_package(nlohmann_json CONFIG REQUIRED) 56 | 57 | # executables 58 | add_executable("${PROJECT_NAME}_bench_read" bench_read.cpp) 59 | target_link_libraries( 60 | "${PROJECT_NAME}_bench_read" PRIVATE ${PROJECT_NAME} benchmark::benchmark 61 | simdjson::simdjson rapidjson) 62 | add_executable("${PROJECT_NAME}_bench_write" bench_write.cpp) 63 | target_link_libraries( 64 | "${PROJECT_NAME}_bench_write" 65 | PRIVATE ${PROJECT_NAME} benchmark::benchmark rapidjson nlohmann_json 66 | nlohmann_json::nlohmann_json) 67 | endif() 68 | 69 | # compile commands 70 | if(CMAKE_EXPORT_COMPILE_COMMANDS) 71 | add_custom_target(gen_compile_commands ALL 72 | COMMENT "Generating compile_commands.json") 73 | 74 | # Generate a compilation database with header files 75 | find_program(COMPDB compdb) 76 | 77 | if(COMPDB) 78 | add_custom_command( 79 | TARGET gen_compile_commands 80 | PRE_BUILD 81 | WORKING_DIRECTORY ${CMAKE_BINARY_DIR} 82 | COMMAND ${COMPDB} list > ${PROJECT_SOURCE_DIR}/compile_commands.json 83 | COMMENT "Running compdb") 84 | 85 | elseif(NOT WIN32) 86 | message(AUTHOR_WARNING "'compdb' not found") 87 | 88 | # Create symbolic link instead of compdb 89 | add_custom_command( 90 | TARGET gen_compile_commands 91 | PRE_BUILD 92 | WORKING_DIRECTORY ${CMAKE_BINARY_DIR} 93 | COMMAND 94 | ${CMAKE_COMMAND} -E create_symlink 95 | ${CMAKE_BINARY_DIR}/compile_commands.json 96 | ${PROJECT_SOURCE_DIR}/compile_commands.json 97 | COMMENT "Creating symbolic link") 98 | endif() 99 | endif() 100 | -------------------------------------------------------------------------------- /test/bench_read.log: -------------------------------------------------------------------------------- 1 | read_cpp_yyjson/0/manual_time_median 1.61 ms 1.61 ms 100 bytes_per_second=1.29879G/s ./test/json/canada.json 2 | read_cpp_yyjson/1/manual_time_median 0.445 ms 0.445 ms 100 bytes_per_second=3.61624G/s ./test/json/citm_catalog.json 3 | read_cpp_yyjson/2/manual_time_median 55.5 ms 55.5 ms 100 bytes_per_second=838.566M/s ./test/json/fgo.json 4 | read_cpp_yyjson/3/manual_time_median 0.017 ms 0.017 ms 100 bytes_per_second=3.58936G/s ./test/json/github_events.json 5 | read_cpp_yyjson/4/manual_time_median 0.924 ms 0.924 ms 100 bytes_per_second=3.35552G/s ./test/json/gsoc-2018.json 6 | read_cpp_yyjson/5/manual_time_median 0.298 ms 0.298 ms 100 bytes_per_second=925.828M/s ./test/json/lottie.json 7 | read_cpp_yyjson/6/manual_time_median 117 ms 117 ms 100 bytes_per_second=539.238M/s ./test/json/otfcc.json 8 | read_cpp_yyjson/7/manual_time_median 0.747 ms 0.747 ms 100 bytes_per_second=4.38201G/s ./test/json/poet.json 9 | read_cpp_yyjson/8/manual_time_median 0.168 ms 0.168 ms 100 bytes_per_second=3.50994G/s ./test/json/twitter.json 10 | read_cpp_yyjson/9/manual_time_median 0.200 ms 0.201 ms 100 bytes_per_second=2.61265G/s ./test/json/twitterescaped.json 11 | read_cpp_yyjson_single/0/manual_time_median 1.61 ms 1.61 ms 100 bytes_per_second=1.29992G/s ./test/json/canada.json 12 | read_cpp_yyjson_single/1/manual_time_median 0.445 ms 0.445 ms 100 bytes_per_second=3.61324G/s ./test/json/citm_catalog.json 13 | read_cpp_yyjson_single/2/manual_time_median 29.1 ms 29.1 ms 100 bytes_per_second=1.56073G/s ./test/json/fgo.json 14 | read_cpp_yyjson_single/3/manual_time_median 0.017 ms 0.017 ms 100 bytes_per_second=3.59239G/s ./test/json/github_events.json 15 | read_cpp_yyjson_single/4/manual_time_median 0.928 ms 0.928 ms 100 bytes_per_second=3.34141G/s ./test/json/gsoc-2018.json 16 | read_cpp_yyjson_single/5/manual_time_median 0.298 ms 0.298 ms 100 bytes_per_second=924.184M/s ./test/json/lottie.json 17 | read_cpp_yyjson_single/6/manual_time_median 64.1 ms 64.1 ms 100 bytes_per_second=987.309M/s ./test/json/otfcc.json 18 | read_cpp_yyjson_single/7/manual_time_median 0.745 ms 0.745 ms 100 bytes_per_second=4.38866G/s ./test/json/poet.json 19 | read_cpp_yyjson_single/8/manual_time_median 0.168 ms 0.168 ms 100 bytes_per_second=3.50462G/s ./test/json/twitter.json 20 | read_cpp_yyjson_single/9/manual_time_median 0.200 ms 0.200 ms 100 bytes_per_second=2.61729G/s ./test/json/twitterescaped.json 21 | read_cpp_yyjson_insitu/0/manual_time_median 1.56 ms 1.61 ms 100 bytes_per_second=1.34282G/s ./test/json/canada.json 22 | read_cpp_yyjson_insitu/1/manual_time_median 0.403 ms 0.445 ms 100 bytes_per_second=3.99221G/s ./test/json/citm_catalog.json 23 | read_cpp_yyjson_insitu/2/manual_time_median 44.2 ms 55.4 ms 100 bytes_per_second=1052.98M/s ./test/json/fgo.json 24 | read_cpp_yyjson_insitu/3/manual_time_median 0.016 ms 0.017 ms 100 bytes_per_second=3.76321G/s ./test/json/github_events.json 25 | read_cpp_yyjson_insitu/4/manual_time_median 0.841 ms 0.924 ms 100 bytes_per_second=3.68555G/s ./test/json/gsoc-2018.json 26 | read_cpp_yyjson_insitu/5/manual_time_median 0.289 ms 0.297 ms 100 bytes_per_second=953.965M/s ./test/json/lottie.json 27 | read_cpp_yyjson_insitu/6/manual_time_median 102 ms 117 ms 100 bytes_per_second=619.611M/s ./test/json/otfcc.json 28 | read_cpp_yyjson_insitu/7/manual_time_median 0.661 ms 0.747 ms 100 bytes_per_second=4.94863G/s ./test/json/poet.json 29 | read_cpp_yyjson_insitu/8/manual_time_median 0.153 ms 0.168 ms 100 bytes_per_second=3.83466G/s ./test/json/twitter.json 30 | read_cpp_yyjson_insitu/9/manual_time_median 0.189 ms 0.201 ms 100 bytes_per_second=2.77022G/s ./test/json/twitterescaped.json 31 | read_cpp_yyjson_insitu_copy/0/manual_time_median 1.61 ms 1.61 ms 100 bytes_per_second=1.29877G/s ./test/json/canada.json 32 | read_cpp_yyjson_insitu_copy/1/manual_time_median 0.445 ms 0.445 ms 100 bytes_per_second=3.61412G/s ./test/json/citm_catalog.json 33 | read_cpp_yyjson_insitu_copy/2/manual_time_median 55.4 ms 55.4 ms 100 bytes_per_second=838.726M/s ./test/json/fgo.json 34 | read_cpp_yyjson_insitu_copy/3/manual_time_median 0.017 ms 0.017 ms 100 bytes_per_second=3.58797G/s ./test/json/github_events.json 35 | read_cpp_yyjson_insitu_copy/4/manual_time_median 0.924 ms 0.924 ms 100 bytes_per_second=3.35273G/s ./test/json/gsoc-2018.json 36 | read_cpp_yyjson_insitu_copy/5/manual_time_median 0.297 ms 0.297 ms 100 bytes_per_second=927.839M/s ./test/json/lottie.json 37 | read_cpp_yyjson_insitu_copy/6/manual_time_median 117 ms 117 ms 100 bytes_per_second=539.609M/s ./test/json/otfcc.json 38 | read_cpp_yyjson_insitu_copy/7/manual_time_median 0.744 ms 0.744 ms 100 bytes_per_second=4.3963G/s ./test/json/poet.json 39 | read_cpp_yyjson_insitu_copy/8/manual_time_median 0.168 ms 0.168 ms 100 bytes_per_second=3.50566G/s ./test/json/twitter.json 40 | read_cpp_yyjson_insitu_copy/9/manual_time_median 0.201 ms 0.201 ms 100 bytes_per_second=2.61122G/s ./test/json/twitterescaped.json 41 | read_cpp_yyjson_insitu_single/0/manual_time_median 1.56 ms 1.61 ms 100 bytes_per_second=1.34546G/s ./test/json/canada.json 42 | read_cpp_yyjson_insitu_single/1/manual_time_median 0.402 ms 0.444 ms 100 bytes_per_second=4.0038G/s ./test/json/citm_catalog.json 43 | read_cpp_yyjson_insitu_single/2/manual_time_median 26.9 ms 38.0 ms 100 bytes_per_second=1.68954G/s ./test/json/fgo.json 44 | read_cpp_yyjson_insitu_single/3/manual_time_median 0.016 ms 0.017 ms 100 bytes_per_second=3.77135G/s ./test/json/github_events.json 45 | read_cpp_yyjson_insitu_single/4/manual_time_median 0.842 ms 0.925 ms 100 bytes_per_second=3.68034G/s ./test/json/gsoc-2018.json 46 | read_cpp_yyjson_insitu_single/5/manual_time_median 0.290 ms 0.298 ms 100 bytes_per_second=951.285M/s ./test/json/lottie.json 47 | read_cpp_yyjson_insitu_single/6/manual_time_median 61.1 ms 76.4 ms 100 bytes_per_second=1037.11M/s ./test/json/otfcc.json 48 | read_cpp_yyjson_insitu_single/7/manual_time_median 0.658 ms 0.745 ms 100 bytes_per_second=4.97516G/s ./test/json/poet.json 49 | read_cpp_yyjson_insitu_single/8/manual_time_median 0.154 ms 0.169 ms 100 bytes_per_second=3.81948G/s ./test/json/twitter.json 50 | read_cpp_yyjson_insitu_single/9/manual_time_median 0.189 ms 0.200 ms 100 bytes_per_second=2.77211G/s ./test/json/twitterescaped.json 51 | read_cpp_yyjson_insitu_single_copy/0/manual_time_median 1.62 ms 1.62 ms 100 bytes_per_second=1.29759G/s ./test/json/canada.json 52 | read_cpp_yyjson_insitu_single_copy/1/manual_time_median 0.446 ms 0.446 ms 100 bytes_per_second=3.6065G/s ./test/json/citm_catalog.json 53 | read_cpp_yyjson_insitu_single_copy/2/manual_time_median 38.1 ms 38.1 ms 100 bytes_per_second=1.19231G/s ./test/json/fgo.json 54 | read_cpp_yyjson_insitu_single_copy/3/manual_time_median 0.017 ms 0.017 ms 100 bytes_per_second=3.58933G/s ./test/json/github_events.json 55 | read_cpp_yyjson_insitu_single_copy/4/manual_time_median 0.926 ms 0.926 ms 100 bytes_per_second=3.34622G/s ./test/json/gsoc-2018.json 56 | read_cpp_yyjson_insitu_single_copy/5/manual_time_median 0.299 ms 0.299 ms 100 bytes_per_second=922.745M/s ./test/json/lottie.json 57 | read_cpp_yyjson_insitu_single_copy/6/manual_time_median 76.4 ms 76.4 ms 100 bytes_per_second=828.846M/s ./test/json/otfcc.json 58 | read_cpp_yyjson_insitu_single_copy/7/manual_time_median 0.747 ms 0.747 ms 100 bytes_per_second=4.3806G/s ./test/json/poet.json 59 | read_cpp_yyjson_insitu_single_copy/8/manual_time_median 0.169 ms 0.169 ms 100 bytes_per_second=3.48908G/s ./test/json/twitter.json 60 | read_cpp_yyjson_insitu_single_copy/9/manual_time_median 0.200 ms 0.200 ms 100 bytes_per_second=2.61558G/s ./test/json/twitterescaped.json 61 | read_c_yyjson/0/manual_time_median 1.63 ms 1.63 ms 100 bytes_per_second=1.28824G/s ./test/json/canada.json 62 | read_c_yyjson/1/manual_time_median 0.442 ms 0.442 ms 100 bytes_per_second=3.6373G/s ./test/json/citm_catalog.json 63 | read_c_yyjson/2/manual_time_median 55.2 ms 55.2 ms 100 bytes_per_second=842.474M/s ./test/json/fgo.json 64 | read_c_yyjson/3/manual_time_median 0.017 ms 0.017 ms 100 bytes_per_second=3.61607G/s ./test/json/github_events.json 65 | read_c_yyjson/4/manual_time_median 0.921 ms 0.921 ms 100 bytes_per_second=3.36385G/s ./test/json/gsoc-2018.json 66 | read_c_yyjson/5/manual_time_median 0.289 ms 0.289 ms 100 bytes_per_second=953.446M/s ./test/json/lottie.json 67 | read_c_yyjson/6/manual_time_median 117 ms 117 ms 100 bytes_per_second=540.518M/s ./test/json/otfcc.json 68 | read_c_yyjson/7/manual_time_median 0.744 ms 0.744 ms 100 bytes_per_second=4.39955G/s ./test/json/poet.json 69 | read_c_yyjson/8/manual_time_median 0.167 ms 0.167 ms 100 bytes_per_second=3.52135G/s ./test/json/twitter.json 70 | read_c_yyjson/9/manual_time_median 0.200 ms 0.200 ms 100 bytes_per_second=2.6146G/s ./test/json/twitterescaped.json 71 | read_c_yyjson_single/0/manual_time_median 1.63 ms 1.63 ms 100 bytes_per_second=1.28891G/s ./test/json/canada.json 72 | read_c_yyjson_single/1/manual_time_median 0.444 ms 0.444 ms 100 bytes_per_second=3.62481G/s ./test/json/citm_catalog.json 73 | read_c_yyjson_single/2/manual_time_median 28.8 ms 28.8 ms 100 bytes_per_second=1.57944G/s ./test/json/fgo.json 74 | read_c_yyjson_single/3/manual_time_median 0.017 ms 0.017 ms 100 bytes_per_second=3.61688G/s ./test/json/github_events.json 75 | read_c_yyjson_single/4/manual_time_median 0.924 ms 0.924 ms 100 bytes_per_second=3.35472G/s ./test/json/gsoc-2018.json 76 | read_c_yyjson_single/5/manual_time_median 0.289 ms 0.289 ms 100 bytes_per_second=952.969M/s ./test/json/lottie.json 77 | read_c_yyjson_single/6/manual_time_median 63.7 ms 63.7 ms 100 bytes_per_second=994.242M/s ./test/json/otfcc.json 78 | read_c_yyjson_single/7/manual_time_median 0.744 ms 0.744 ms 100 bytes_per_second=4.39993G/s ./test/json/poet.json 79 | read_c_yyjson_single/8/manual_time_median 0.167 ms 0.167 ms 100 bytes_per_second=3.52301G/s ./test/json/twitter.json 80 | read_c_yyjson_single/9/manual_time_median 0.200 ms 0.200 ms 100 bytes_per_second=2.62193G/s ./test/json/twitterescaped.json 81 | read_c_yyjson_insitu/0/manual_time_median 1.57 ms 1.63 ms 100 bytes_per_second=1.33184G/s ./test/json/canada.json 82 | read_c_yyjson_insitu/1/manual_time_median 0.401 ms 0.444 ms 100 bytes_per_second=4.00917G/s ./test/json/citm_catalog.json 83 | read_c_yyjson_insitu/2/manual_time_median 43.8 ms 55.1 ms 100 bytes_per_second=1060.92M/s ./test/json/fgo.json 84 | read_c_yyjson_insitu/3/manual_time_median 0.016 ms 0.017 ms 100 bytes_per_second=3.79369G/s ./test/json/github_events.json 85 | read_c_yyjson_insitu/4/manual_time_median 0.839 ms 0.921 ms 100 bytes_per_second=3.69513G/s ./test/json/gsoc-2018.json 86 | read_c_yyjson_insitu/5/manual_time_median 0.281 ms 0.289 ms 100 bytes_per_second=981.251M/s ./test/json/lottie.json 87 | read_c_yyjson_insitu/6/manual_time_median 102 ms 117 ms 100 bytes_per_second=621.887M/s ./test/json/otfcc.json 88 | read_c_yyjson_insitu/7/manual_time_median 0.656 ms 0.742 ms 100 bytes_per_second=4.98601G/s ./test/json/poet.json 89 | read_c_yyjson_insitu/8/manual_time_median 0.153 ms 0.167 ms 100 bytes_per_second=3.84654G/s ./test/json/twitter.json 90 | read_c_yyjson_insitu/9/manual_time_median 0.189 ms 0.200 ms 100 bytes_per_second=2.77367G/s ./test/json/twitterescaped.json 91 | read_c_yyjson_insitu_copy/0/manual_time_median 1.63 ms 1.63 ms 100 bytes_per_second=1.28767G/s ./test/json/canada.json 92 | read_c_yyjson_insitu_copy/1/manual_time_median 0.443 ms 0.443 ms 100 bytes_per_second=3.63112G/s ./test/json/citm_catalog.json 93 | read_c_yyjson_insitu_copy/2/manual_time_median 55.1 ms 55.1 ms 100 bytes_per_second=843.837M/s ./test/json/fgo.json 94 | read_c_yyjson_insitu_copy/3/manual_time_median 0.017 ms 0.017 ms 100 bytes_per_second=3.61578G/s ./test/json/github_events.json 95 | read_c_yyjson_insitu_copy/4/manual_time_median 0.921 ms 0.921 ms 100 bytes_per_second=3.36344G/s ./test/json/gsoc-2018.json 96 | read_c_yyjson_insitu_copy/5/manual_time_median 0.289 ms 0.290 ms 100 bytes_per_second=951.882M/s ./test/json/lottie.json 97 | read_c_yyjson_insitu_copy/6/manual_time_median 117 ms 117 ms 100 bytes_per_second=541.046M/s ./test/json/otfcc.json 98 | read_c_yyjson_insitu_copy/7/manual_time_median 0.742 ms 0.742 ms 100 bytes_per_second=4.40952G/s ./test/json/poet.json 99 | read_c_yyjson_insitu_copy/8/manual_time_median 0.167 ms 0.167 ms 100 bytes_per_second=3.51251G/s ./test/json/twitter.json 100 | read_c_yyjson_insitu_copy/9/manual_time_median 0.201 ms 0.201 ms 100 bytes_per_second=2.61231G/s ./test/json/twitterescaped.json 101 | read_c_yyjson_insitu_single/0/manual_time_median 1.57 ms 1.63 ms 100 bytes_per_second=1.33166G/s ./test/json/canada.json 102 | read_c_yyjson_insitu_single/1/manual_time_median 0.401 ms 0.444 ms 100 bytes_per_second=4.01622G/s ./test/json/citm_catalog.json 103 | read_c_yyjson_insitu_single/2/manual_time_median 26.5 ms 37.7 ms 100 bytes_per_second=1.71127G/s ./test/json/fgo.json 104 | read_c_yyjson_insitu_single/3/manual_time_median 0.016 ms 0.017 ms 100 bytes_per_second=3.80236G/s ./test/json/github_events.json 105 | read_c_yyjson_insitu_single/4/manual_time_median 0.839 ms 0.924 ms 100 bytes_per_second=3.69207G/s ./test/json/gsoc-2018.json 106 | read_c_yyjson_insitu_single/5/manual_time_median 0.280 ms 0.289 ms 100 bytes_per_second=982.818M/s ./test/json/lottie.json 107 | read_c_yyjson_insitu_single/6/manual_time_median 60.6 ms 75.9 ms 100 bytes_per_second=1045.06M/s ./test/json/otfcc.json 108 | read_c_yyjson_insitu_single/7/manual_time_median 0.657 ms 0.744 ms 100 bytes_per_second=4.98333G/s ./test/json/poet.json 109 | read_c_yyjson_insitu_single/8/manual_time_median 0.153 ms 0.168 ms 100 bytes_per_second=3.84353G/s ./test/json/twitter.json 110 | read_c_yyjson_insitu_single/9/manual_time_median 0.189 ms 0.200 ms 100 bytes_per_second=2.77413G/s ./test/json/twitterescaped.json 111 | read_c_yyjson_insitu_single_copy/0/manual_time_median 1.62 ms 1.62 ms 100 bytes_per_second=1.2935G/s ./test/json/canada.json 112 | read_c_yyjson_insitu_single_copy/1/manual_time_median 0.444 ms 0.444 ms 100 bytes_per_second=3.62657G/s ./test/json/citm_catalog.json 113 | read_c_yyjson_insitu_single_copy/2/manual_time_median 37.7 ms 37.7 ms 100 bytes_per_second=1.20511G/s ./test/json/fgo.json 114 | read_c_yyjson_insitu_single_copy/3/manual_time_median 0.017 ms 0.017 ms 100 bytes_per_second=3.6176G/s ./test/json/github_events.json 115 | read_c_yyjson_insitu_single_copy/4/manual_time_median 0.924 ms 0.924 ms 100 bytes_per_second=3.35554G/s ./test/json/gsoc-2018.json 116 | read_c_yyjson_insitu_single_copy/5/manual_time_median 0.290 ms 0.290 ms 100 bytes_per_second=950.97M/s ./test/json/lottie.json 117 | read_c_yyjson_insitu_single_copy/6/manual_time_median 76.0 ms 76.0 ms 100 bytes_per_second=833.651M/s ./test/json/otfcc.json 118 | read_c_yyjson_insitu_single_copy/7/manual_time_median 0.742 ms 0.742 ms 100 bytes_per_second=4.41103G/s ./test/json/poet.json 119 | read_c_yyjson_insitu_single_copy/8/manual_time_median 0.168 ms 0.168 ms 100 bytes_per_second=3.50492G/s ./test/json/twitter.json 120 | read_c_yyjson_insitu_single_copy/9/manual_time_median 0.200 ms 0.200 ms 100 bytes_per_second=2.61557G/s ./test/json/twitterescaped.json 121 | read_rapidjson/0/manual_time_median 2.54 ms 2.54 ms 100 bytes_per_second=845.067M/s ./test/json/canada.json 122 | read_rapidjson/1/manual_time_median 0.979 ms 0.979 ms 100 bytes_per_second=1.6427G/s ./test/json/citm_catalog.json 123 | read_rapidjson/2/manual_time_median 73.1 ms 73.1 ms 100 bytes_per_second=636.127M/s ./test/json/fgo.json 124 | read_rapidjson/3/manual_time_median 0.054 ms 0.054 ms 100 bytes_per_second=1.11728G/s ./test/json/github_events.json 125 | read_rapidjson/4/manual_time_median 2.16 ms 2.16 ms 100 bytes_per_second=1.43552G/s ./test/json/gsoc-2018.json 126 | read_rapidjson/5/manual_time_median 0.561 ms 0.561 ms 100 bytes_per_second=491.571M/s ./test/json/lottie.json 127 | read_rapidjson/6/manual_time_median 147 ms 147 ms 100 bytes_per_second=431.36M/s ./test/json/otfcc.json 128 | read_rapidjson/7/manual_time_median 2.49 ms 2.49 ms 100 bytes_per_second=1.31209G/s ./test/json/poet.json 129 | read_rapidjson/8/manual_time_median 0.502 ms 0.502 ms 100 bytes_per_second=1.17256G/s ./test/json/twitter.json 130 | read_rapidjson/9/manual_time_median 0.565 ms 0.565 ms 100 bytes_per_second=949.9M/s ./test/json/twitterescaped.json 131 | read_rapidjson_single/0/manual_time_median 2.51 ms 2.51 ms 100 bytes_per_second=856.61M/s ./test/json/canada.json 132 | read_rapidjson_single/1/manual_time_median 0.994 ms 0.994 ms 100 bytes_per_second=1.61775G/s ./test/json/citm_catalog.json 133 | read_rapidjson_single/2/manual_time_median 61.8 ms 61.8 ms 100 bytes_per_second=751.974M/s ./test/json/fgo.json 134 | read_rapidjson_single/3/manual_time_median 0.055 ms 0.055 ms 100 bytes_per_second=1125.78M/s ./test/json/github_events.json 135 | read_rapidjson_single/4/manual_time_median 2.17 ms 2.17 ms 100 bytes_per_second=1.4253G/s ./test/json/gsoc-2018.json 136 | read_rapidjson_single/5/manual_time_median 0.570 ms 0.570 ms 100 bytes_per_second=483.036M/s ./test/json/lottie.json 137 | read_rapidjson_single/6/manual_time_median 112 ms 112 ms 100 bytes_per_second=565.763M/s ./test/json/otfcc.json 138 | read_rapidjson_single/7/manual_time_median 2.53 ms 2.53 ms 100 bytes_per_second=1.29444G/s ./test/json/poet.json 139 | read_rapidjson_single/8/manual_time_median 0.505 ms 0.505 ms 100 bytes_per_second=1.16485G/s ./test/json/twitter.json 140 | read_rapidjson_single/9/manual_time_median 0.573 ms 0.573 ms 100 bytes_per_second=935.886M/s ./test/json/twitterescaped.json 141 | read_rapidjson_insitu/0/manual_time_median 2.56 ms 2.62 ms 100 bytes_per_second=837.993M/s ./test/json/canada.json 142 | read_rapidjson_insitu/1/manual_time_median 0.816 ms 0.876 ms 100 bytes_per_second=1.9717G/s ./test/json/citm_catalog.json 143 | read_rapidjson_insitu/2/manual_time_median 58.4 ms 68.9 ms 100 bytes_per_second=795.892M/s ./test/json/fgo.json 144 | read_rapidjson_insitu/3/manual_time_median 0.037 ms 0.038 ms 100 bytes_per_second=1.65107G/s ./test/json/github_events.json 145 | read_rapidjson_insitu/4/manual_time_median 1.43 ms 1.55 ms 100 bytes_per_second=2.16363G/s ./test/json/gsoc-2018.json 146 | read_rapidjson_insitu/5/manual_time_median 0.481 ms 0.488 ms 100 bytes_per_second=572.499M/s ./test/json/lottie.json 147 | read_rapidjson_insitu/6/manual_time_median 132 ms 147 ms 100 bytes_per_second=480.705M/s ./test/json/otfcc.json 148 | read_rapidjson_insitu/7/manual_time_median 1.56 ms 1.68 ms 100 bytes_per_second=2.09745G/s ./test/json/poet.json 149 | read_rapidjson_insitu/8/manual_time_median 0.352 ms 0.368 ms 100 bytes_per_second=1.67102G/s ./test/json/twitter.json 150 | read_rapidjson_insitu/9/manual_time_median 0.440 ms 0.454 ms 100 bytes_per_second=1.19079G/s ./test/json/twitterescaped.json 151 | read_rapidjson_insitu_copy/0/manual_time_median 2.61 ms 2.61 ms 100 bytes_per_second=821.606M/s ./test/json/canada.json 152 | read_rapidjson_insitu_copy/1/manual_time_median 0.876 ms 0.876 ms 100 bytes_per_second=1.83683G/s ./test/json/citm_catalog.json 153 | read_rapidjson_insitu_copy/2/manual_time_median 68.9 ms 68.9 ms 100 bytes_per_second=674.95M/s ./test/json/fgo.json 154 | read_rapidjson_insitu_copy/3/manual_time_median 0.038 ms 0.038 ms 100 bytes_per_second=1.61034G/s ./test/json/github_events.json 155 | read_rapidjson_insitu_copy/4/manual_time_median 1.54 ms 1.54 ms 100 bytes_per_second=2.00849G/s ./test/json/gsoc-2018.json 156 | read_rapidjson_insitu_copy/5/manual_time_median 0.488 ms 0.488 ms 100 bytes_per_second=564.422M/s ./test/json/lottie.json 157 | read_rapidjson_insitu_copy/6/manual_time_median 147 ms 147 ms 100 bytes_per_second=430.99M/s ./test/json/otfcc.json 158 | read_rapidjson_insitu_copy/7/manual_time_median 1.68 ms 1.68 ms 100 bytes_per_second=1.94513G/s ./test/json/poet.json 159 | read_rapidjson_insitu_copy/8/manual_time_median 0.368 ms 0.368 ms 100 bytes_per_second=1.5979G/s ./test/json/twitter.json 160 | read_rapidjson_insitu_copy/9/manual_time_median 0.454 ms 0.454 ms 100 bytes_per_second=1.15367G/s ./test/json/twitterescaped.json 161 | read_rapidjson_insitu_single/0/manual_time_median 2.54 ms 2.59 ms 100 bytes_per_second=846.451M/s ./test/json/canada.json 162 | read_rapidjson_insitu_single/1/manual_time_median 0.898 ms 0.958 ms 100 bytes_per_second=1.7914G/s ./test/json/citm_catalog.json 163 | read_rapidjson_insitu_single/2/manual_time_median 47.5 ms 49.7 ms 100 bytes_per_second=978.484M/s ./test/json/fgo.json 164 | read_rapidjson_insitu_single/3/manual_time_median 0.039 ms 0.040 ms 100 bytes_per_second=1.54186G/s ./test/json/github_events.json 165 | read_rapidjson_insitu_single/4/manual_time_median 1.45 ms 1.57 ms 100 bytes_per_second=2.13602G/s ./test/json/gsoc-2018.json 166 | read_rapidjson_insitu_single/5/manual_time_median 0.490 ms 0.497 ms 100 bytes_per_second=562.572M/s ./test/json/lottie.json 167 | read_rapidjson_insitu_single/6/manual_time_median 98.6 ms 114 ms 100 bytes_per_second=642.047M/s ./test/json/otfcc.json 168 | read_rapidjson_insitu_single/7/manual_time_median 1.66 ms 1.78 ms 100 bytes_per_second=1.96859G/s ./test/json/poet.json 169 | read_rapidjson_insitu_single/8/manual_time_median 0.386 ms 0.403 ms 100 bytes_per_second=1.52205G/s ./test/json/twitter.json 170 | read_rapidjson_insitu_single/9/manual_time_median 0.456 ms 0.471 ms 100 bytes_per_second=1.14753G/s ./test/json/twitterescaped.json 171 | read_rapidjson_insitu_single_copy/0/manual_time_median 2.59 ms 2.59 ms 100 bytes_per_second=830.079M/s ./test/json/canada.json 172 | read_rapidjson_insitu_single_copy/1/manual_time_median 0.957 ms 0.957 ms 100 bytes_per_second=1.68101G/s ./test/json/citm_catalog.json 173 | read_rapidjson_insitu_single_copy/2/manual_time_median 49.7 ms 49.7 ms 100 bytes_per_second=935.056M/s ./test/json/fgo.json 174 | read_rapidjson_insitu_single_copy/3/manual_time_median 0.040 ms 0.040 ms 100 bytes_per_second=1.5084G/s ./test/json/github_events.json 175 | read_rapidjson_insitu_single_copy/4/manual_time_median 1.57 ms 1.57 ms 100 bytes_per_second=1.97713G/s ./test/json/gsoc-2018.json 176 | read_rapidjson_insitu_single_copy/5/manual_time_median 0.497 ms 0.497 ms 100 bytes_per_second=553.959M/s ./test/json/lottie.json 177 | read_rapidjson_insitu_single_copy/6/manual_time_median 114 ms 114 ms 100 bytes_per_second=554.376M/s ./test/json/otfcc.json 178 | read_rapidjson_insitu_single_copy/7/manual_time_median 1.78 ms 1.78 ms 100 bytes_per_second=1.83325G/s ./test/json/poet.json 179 | read_rapidjson_insitu_single_copy/8/manual_time_median 0.403 ms 0.403 ms 100 bytes_per_second=1.45918G/s ./test/json/twitter.json 180 | read_rapidjson_insitu_single_copy/9/manual_time_median 0.472 ms 0.472 ms 100 bytes_per_second=1.11086G/s ./test/json/twitterescaped.json 181 | read_simdjson_dom/0/manual_time_median 2.19 ms 2.19 ms 100 bytes_per_second=978.289M/s ./test/json/canada.json 182 | read_simdjson_dom/1/manual_time_median 0.527 ms 0.527 ms 100 bytes_per_second=3.05454G/s ./test/json/citm_catalog.json 183 | read_simdjson_dom/2/manual_time_median 71.6 ms 71.6 ms 100 bytes_per_second=649.457M/s ./test/json/fgo.json 184 | read_simdjson_dom/3/manual_time_median 0.016 ms 0.016 ms 100 bytes_per_second=3.71642G/s ./test/json/github_events.json 185 | read_simdjson_dom/4/manual_time_median 0.688 ms 0.688 ms 100 bytes_per_second=4.50702G/s ./test/json/gsoc-2018.json 186 | read_simdjson_dom/5/manual_time_median 0.480 ms 0.480 ms 100 bytes_per_second=574.554M/s ./test/json/lottie.json 187 | read_simdjson_dom/6/manual_time_median 166 ms 166 ms 100 bytes_per_second=381.273M/s ./test/json/otfcc.json 188 | read_simdjson_dom/7/manual_time_median 0.825 ms 0.825 ms 100 bytes_per_second=3.96725G/s ./test/json/poet.json 189 | read_simdjson_dom/8/manual_time_median 0.181 ms 0.181 ms 100 bytes_per_second=3.25519G/s ./test/json/twitter.json 190 | read_simdjson_dom/9/manual_time_median 0.304 ms 0.304 ms 100 bytes_per_second=1.72416G/s ./test/json/twitterescaped.json 191 | read_simdjson_ond_pad/0/manual_time_median 1.82 ms 1.89 ms 100 bytes_per_second=1.15451G/s ./test/json/canada.json 192 | read_simdjson_ond_pad/1/manual_time_median 0.338 ms 0.397 ms 100 bytes_per_second=4.75658G/s ./test/json/citm_catalog.json 193 | read_simdjson_ond_pad/2/manual_time_median 41.4 ms 43.6 ms 100 bytes_per_second=1123.93M/s ./test/json/fgo.json 194 | read_simdjson_ond_pad/3/manual_time_median 0.014 ms 0.015 ms 100 bytes_per_second=4.29817G/s ./test/json/github_events.json 195 | read_simdjson_ond_pad/4/manual_time_median 0.573 ms 0.688 ms 100 bytes_per_second=5.41041G/s ./test/json/gsoc-2018.json 196 | read_simdjson_ond_pad/5/manual_time_median 0.338 ms 0.345 ms 100 bytes_per_second=815.944M/s ./test/json/lottie.json 197 | read_simdjson_ond_pad/6/manual_time_median 87.8 ms 103 ms 100 bytes_per_second=721.494M/s ./test/json/otfcc.json 198 | read_simdjson_ond_pad/7/manual_time_median 0.654 ms 0.775 ms 100 bytes_per_second=5.00103G/s ./test/json/poet.json 199 | read_simdjson_ond_pad/8/manual_time_median 0.150 ms 0.167 ms 100 bytes_per_second=3.92515G/s ./test/json/twitter.json 200 | read_simdjson_ond_pad/9/manual_time_median 0.280 ms 0.295 ms 100 bytes_per_second=1.87284G/s ./test/json/twitterescaped.json 201 | read_simdjson_ond_pad_copy/0/manual_time_median 1.89 ms 1.89 ms 100 bytes_per_second=1.10913G/s ./test/json/canada.json 202 | read_simdjson_ond_pad_copy/1/manual_time_median 0.399 ms 0.399 ms 100 bytes_per_second=4.03639G/s ./test/json/citm_catalog.json 203 | read_simdjson_ond_pad_copy/2/manual_time_median 43.6 ms 43.6 ms 100 bytes_per_second=1067.25M/s ./test/json/fgo.json 204 | read_simdjson_ond_pad_copy/3/manual_time_median 0.015 ms 0.015 ms 100 bytes_per_second=4.04935G/s ./test/json/github_events.json 205 | read_simdjson_ond_pad_copy/4/manual_time_median 0.691 ms 0.691 ms 100 bytes_per_second=4.48429G/s ./test/json/gsoc-2018.json 206 | read_simdjson_ond_pad_copy/5/manual_time_median 0.345 ms 0.345 ms 100 bytes_per_second=799.443M/s ./test/json/lottie.json 207 | read_simdjson_ond_pad_copy/6/manual_time_median 103 ms 103 ms 100 bytes_per_second=615.03M/s ./test/json/otfcc.json 208 | read_simdjson_ond_pad_copy/7/manual_time_median 0.775 ms 0.775 ms 100 bytes_per_second=4.21959G/s ./test/json/poet.json 209 | read_simdjson_ond_pad_copy/8/manual_time_median 0.167 ms 0.167 ms 100 bytes_per_second=3.5283G/s ./test/json/twitter.json 210 | read_simdjson_ond_pad_copy/9/manual_time_median 0.295 ms 0.295 ms 100 bytes_per_second=1.7728G/s ./test/json/twitterescaped.json 211 | read_simdjson_dom_single/0/manual_time_median 2.20 ms 2.20 ms 100 bytes_per_second=976.808M/s ./test/json/canada.json 212 | read_simdjson_dom_single/1/manual_time_median 0.528 ms 0.528 ms 100 bytes_per_second=3.04891G/s ./test/json/citm_catalog.json 213 | read_simdjson_dom_single/2/manual_time_median 45.3 ms 45.3 ms 100 bytes_per_second=1027.46M/s ./test/json/fgo.json 214 | read_simdjson_dom_single/3/manual_time_median 0.016 ms 0.016 ms 100 bytes_per_second=3.77074G/s ./test/json/github_events.json 215 | read_simdjson_dom_single/4/manual_time_median 0.687 ms 0.687 ms 100 bytes_per_second=4.50914G/s ./test/json/gsoc-2018.json 216 | read_simdjson_dom_single/5/manual_time_median 0.478 ms 0.478 ms 100 bytes_per_second=576.138M/s ./test/json/lottie.json 217 | read_simdjson_dom_single/6/manual_time_median 108 ms 108 ms 100 bytes_per_second=583.751M/s ./test/json/otfcc.json 218 | read_simdjson_dom_single/7/manual_time_median 0.822 ms 0.822 ms 100 bytes_per_second=3.97926G/s ./test/json/poet.json 219 | read_simdjson_dom_single/8/manual_time_median 0.180 ms 0.180 ms 100 bytes_per_second=3.27062G/s ./test/json/twitter.json 220 | read_simdjson_dom_single/9/manual_time_median 0.302 ms 0.302 ms 100 bytes_per_second=1.73291G/s ./test/json/twitterescaped.json 221 | read_simdjson_ond_pad_single/0/manual_time_median 1.81 ms 1.89 ms 100 bytes_per_second=1.1567G/s ./test/json/canada.json 222 | read_simdjson_ond_pad_single/1/manual_time_median 0.339 ms 0.398 ms 100 bytes_per_second=4.74027G/s ./test/json/citm_catalog.json 223 | read_simdjson_ond_pad_single/2/manual_time_median 29.8 ms 32.0 ms 100 bytes_per_second=1.52207G/s ./test/json/fgo.json 224 | read_simdjson_ond_pad_single/3/manual_time_median 0.014 ms 0.015 ms 100 bytes_per_second=4.35618G/s ./test/json/github_events.json 225 | read_simdjson_ond_pad_single/4/manual_time_median 0.576 ms 0.691 ms 100 bytes_per_second=5.38128G/s ./test/json/gsoc-2018.json 226 | read_simdjson_ond_pad_single/5/manual_time_median 0.337 ms 0.344 ms 100 bytes_per_second=817.679M/s ./test/json/lottie.json 227 | read_simdjson_ond_pad_single/6/manual_time_median 68.6 ms 83.7 ms 100 bytes_per_second=923.197M/s ./test/json/otfcc.json 228 | read_simdjson_ond_pad_single/7/manual_time_median 0.654 ms 0.775 ms 100 bytes_per_second=5.00116G/s ./test/json/poet.json 229 | read_simdjson_ond_pad_single/8/manual_time_median 0.150 ms 0.167 ms 100 bytes_per_second=3.91134G/s ./test/json/twitter.json 230 | read_simdjson_ond_pad_single/9/manual_time_median 0.280 ms 0.296 ms 100 bytes_per_second=1.86776G/s ./test/json/twitterescaped.json 231 | read_simdjson_ond_pad_single_copy/0/manual_time_median 1.89 ms 1.89 ms 100 bytes_per_second=1.10921G/s ./test/json/canada.json 232 | read_simdjson_ond_pad_single_copy/1/manual_time_median 0.397 ms 0.397 ms 100 bytes_per_second=4.04947G/s ./test/json/citm_catalog.json 233 | read_simdjson_ond_pad_single_copy/2/manual_time_median 32.0 ms 32.0 ms 100 bytes_per_second=1.41753G/s ./test/json/fgo.json 234 | read_simdjson_ond_pad_single_copy/3/manual_time_median 0.015 ms 0.015 ms 100 bytes_per_second=4.08492G/s ./test/json/github_events.json 235 | read_simdjson_ond_pad_single_copy/4/manual_time_median 0.686 ms 0.686 ms 100 bytes_per_second=4.51673G/s ./test/json/gsoc-2018.json 236 | read_simdjson_ond_pad_single_copy/5/manual_time_median 0.344 ms 0.344 ms 100 bytes_per_second=801.501M/s ./test/json/lottie.json 237 | read_simdjson_ond_pad_single_copy/6/manual_time_median 71.3 ms 71.3 ms 100 bytes_per_second=888.095M/s ./test/json/otfcc.json 238 | read_simdjson_ond_pad_single_copy/7/manual_time_median 0.776 ms 0.776 ms 100 bytes_per_second=4.2146G/s ./test/json/poet.json 239 | read_simdjson_ond_pad_single_copy/8/manual_time_median 0.169 ms 0.169 ms 100 bytes_per_second=3.48481G/s ./test/json/twitter.json 240 | read_simdjson_ond_pad_single_copy/9/manual_time_median 0.297 ms 0.297 ms 100 bytes_per_second=1.76545G/s ./test/json/twitterescaped.json 241 | read_simdjson_dom_pad/0/manual_time_median 2.12 ms 2.20 ms 100 bytes_per_second=1010.81M/s ./test/json/canada.json 242 | read_simdjson_dom_pad/1/manual_time_median 0.469 ms 0.528 ms 100 bytes_per_second=3.42804G/s ./test/json/citm_catalog.json 243 | read_simdjson_dom_pad/2/manual_time_median 69.3 ms 71.6 ms 100 bytes_per_second=670.858M/s ./test/json/fgo.json 244 | read_simdjson_dom_pad/3/manual_time_median 0.015 ms 0.016 ms 100 bytes_per_second=3.91909G/s ./test/json/github_events.json 245 | read_simdjson_dom_pad/4/manual_time_median 0.583 ms 0.697 ms 100 bytes_per_second=5.31264G/s ./test/json/gsoc-2018.json 246 | read_simdjson_dom_pad/5/manual_time_median 0.473 ms 0.480 ms 100 bytes_per_second=582.915M/s ./test/json/lottie.json 247 | read_simdjson_dom_pad/6/manual_time_median 151 ms 166 ms 100 bytes_per_second=419.812M/s ./test/json/otfcc.json 248 | read_simdjson_dom_pad/7/manual_time_median 0.708 ms 0.829 ms 100 bytes_per_second=4.61872G/s ./test/json/poet.json 249 | read_simdjson_dom_pad/8/manual_time_median 0.166 ms 0.182 ms 100 bytes_per_second=3.55065G/s ./test/json/twitter.json 250 | read_simdjson_dom_pad/9/manual_time_median 0.289 ms 0.303 ms 100 bytes_per_second=1.81499G/s ./test/json/twitterescaped.json 251 | read_simdjson_dom_pad_copy/0/manual_time_median 2.19 ms 2.19 ms 100 bytes_per_second=982.104M/s ./test/json/canada.json 252 | read_simdjson_dom_pad_copy/1/manual_time_median 0.529 ms 0.529 ms 100 bytes_per_second=3.04194G/s ./test/json/citm_catalog.json 253 | read_simdjson_dom_pad_copy/2/manual_time_median 71.6 ms 71.6 ms 100 bytes_per_second=649.314M/s ./test/json/fgo.json 254 | read_simdjson_dom_pad_copy/3/manual_time_median 0.016 ms 0.016 ms 100 bytes_per_second=3.72996G/s ./test/json/github_events.json 255 | read_simdjson_dom_pad_copy/4/manual_time_median 0.698 ms 0.698 ms 100 bytes_per_second=4.43996G/s ./test/json/gsoc-2018.json 256 | read_simdjson_dom_pad_copy/5/manual_time_median 0.480 ms 0.480 ms 100 bytes_per_second=573.94M/s ./test/json/lottie.json 257 | read_simdjson_dom_pad_copy/6/manual_time_median 166 ms 166 ms 100 bytes_per_second=380.992M/s ./test/json/otfcc.json 258 | read_simdjson_dom_pad_copy/7/manual_time_median 0.828 ms 0.828 ms 100 bytes_per_second=3.95101G/s ./test/json/poet.json 259 | read_simdjson_dom_pad_copy/8/manual_time_median 0.182 ms 0.182 ms 100 bytes_per_second=3.23529G/s ./test/json/twitter.json 260 | read_simdjson_dom_pad_copy/9/manual_time_median 0.303 ms 0.303 ms 100 bytes_per_second=1.72825G/s ./test/json/twitterescaped.json 261 | read_simdjson_dom_pad_single/0/manual_time_median 2.12 ms 2.20 ms 100 bytes_per_second=1012.12M/s ./test/json/canada.json 262 | read_simdjson_dom_pad_single/1/manual_time_median 0.470 ms 0.529 ms 100 bytes_per_second=3.42489G/s ./test/json/citm_catalog.json 263 | read_simdjson_dom_pad_single/2/manual_time_median 42.9 ms 45.2 ms 100 bytes_per_second=1083.08M/s ./test/json/fgo.json 264 | read_simdjson_dom_pad_single/3/manual_time_median 0.015 ms 0.016 ms 100 bytes_per_second=3.93307G/s ./test/json/github_events.json 265 | read_simdjson_dom_pad_single/4/manual_time_median 0.585 ms 0.699 ms 100 bytes_per_second=5.30061G/s ./test/json/gsoc-2018.json 266 | read_simdjson_dom_pad_single/5/manual_time_median 0.472 ms 0.479 ms 100 bytes_per_second=583.597M/s ./test/json/lottie.json 267 | read_simdjson_dom_pad_single/6/manual_time_median 106 ms 121 ms 100 bytes_per_second=600.161M/s ./test/json/otfcc.json 268 | read_simdjson_dom_pad_single/7/manual_time_median 0.710 ms 0.830 ms 100 bytes_per_second=4.60852G/s ./test/json/poet.json 269 | read_simdjson_dom_pad_single/8/manual_time_median 0.166 ms 0.182 ms 100 bytes_per_second=3.54465G/s ./test/json/twitter.json 270 | read_simdjson_dom_pad_single/9/manual_time_median 0.289 ms 0.303 ms 100 bytes_per_second=1.81301G/s ./test/json/twitterescaped.json 271 | read_simdjson_dom_pad_single_copy/0/manual_time_median 2.19 ms 2.19 ms 100 bytes_per_second=978.832M/s ./test/json/canada.json 272 | read_simdjson_dom_pad_single_copy/1/manual_time_median 0.526 ms 0.526 ms 100 bytes_per_second=3.05879G/s ./test/json/citm_catalog.json 273 | read_simdjson_dom_pad_single_copy/2/manual_time_median 45.3 ms 45.3 ms 100 bytes_per_second=1026.6M/s ./test/json/fgo.json 274 | read_simdjson_dom_pad_single_copy/3/manual_time_median 0.016 ms 0.016 ms 100 bytes_per_second=3.71931G/s ./test/json/github_events.json 275 | read_simdjson_dom_pad_single_copy/4/manual_time_median 0.694 ms 0.694 ms 100 bytes_per_second=4.46836G/s ./test/json/gsoc-2018.json 276 | read_simdjson_dom_pad_single_copy/5/manual_time_median 0.480 ms 0.480 ms 100 bytes_per_second=574.29M/s ./test/json/lottie.json 277 | read_simdjson_dom_pad_single_copy/6/manual_time_median 108 ms 108 ms 100 bytes_per_second=584.622M/s ./test/json/otfcc.json 278 | read_simdjson_dom_pad_single_copy/7/manual_time_median 0.832 ms 0.832 ms 100 bytes_per_second=3.93106G/s ./test/json/poet.json 279 | read_simdjson_dom_pad_single_copy/8/manual_time_median 0.183 ms 0.183 ms 100 bytes_per_second=3.21786G/s ./test/json/twitter.json 280 | read_simdjson_dom_pad_single_copy/9/manual_time_median 0.304 ms 0.304 ms 100 bytes_per_second=1.72078G/s ./test/json/twitterescaped.json 281 | -------------------------------------------------------------------------------- /test/bench_write.cpp: -------------------------------------------------------------------------------- 1 | // NOLINTBEGIN 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | constexpr auto VEC_SIZE = 1'000'000; 13 | auto vec_int64 = std::vector(VEC_SIZE); 14 | auto vec_double = std::vector(VEC_SIZE); 15 | auto vec_string = std::vector(VEC_SIZE); 16 | auto vec_tuple = std::vector>(VEC_SIZE); 17 | struct X 18 | { 19 | int i = 1; 20 | double j = 2.5; 21 | std::string k = "4.0"; 22 | }; 23 | VISITABLE_STRUCT(X, i, j, k); 24 | auto vec_object = std::vector(VEC_SIZE); 25 | 26 | // JSON string size for validator 27 | constexpr auto json_size_arr_int64 = 6888891; 28 | constexpr auto json_size_arr_double = 8888891; 29 | constexpr auto json_size_arr_string = 8888891; 30 | constexpr auto json_size_arr_tuple = 26666695; 31 | constexpr auto json_size_arr_object = 38666695; 32 | constexpr auto json_size_arr_double_append = 9259259; 33 | constexpr auto json_size_obj_int64 = 15777781; 34 | constexpr auto json_size_obj_double = 17777781; 35 | constexpr auto json_size_obj_string = 17777781; 36 | 37 | void write_c_yyjson_array_int64(benchmark::State& state) 38 | { 39 | std::iota(vec_int64.begin(), vec_int64.end(), 0); 40 | for (auto _ : state) 41 | { 42 | yyjson_mut_doc* doc = yyjson_mut_doc_new(NULL); 43 | auto root = yyjson_mut_arr_with_sint64(doc, vec_int64.data(), vec_int64.size()); 44 | yyjson_mut_doc_set_root(doc, root); 45 | const char* json = yyjson_mut_write(doc, 0, NULL); 46 | auto result = std::string_view(json); 47 | if (result.size() != json_size_arr_int64) 48 | { 49 | state.SkipWithError("Invalid JSON string"); 50 | break; 51 | } 52 | free(const_cast(static_cast(json))); 53 | yyjson_mut_doc_free(doc); 54 | } 55 | } 56 | 57 | void write_cpp_yyjson_array_int64(benchmark::State& state) 58 | { 59 | using namespace yyjson; 60 | std::iota(vec_int64.begin(), vec_int64.end(), 0); 61 | for (auto _ : state) 62 | { 63 | auto array = yyjson::array(vec_int64); 64 | auto result = array.write(); 65 | if (result.size() != json_size_arr_int64) 66 | { 67 | state.SkipWithError("Invalid JSON string"); 68 | break; 69 | } 70 | } 71 | } 72 | 73 | void write_cpp_yyjson_single_array_int64(benchmark::State& state) 74 | { 75 | using namespace yyjson; 76 | std::iota(vec_int64.begin(), vec_int64.end(), 0); 77 | auto alc = dynamic_allocator(); 78 | for (auto _ : state) 79 | { 80 | auto array = yyjson::array(vec_int64); 81 | auto result = array.write(alc); 82 | if (result.size() != json_size_arr_int64) 83 | { 84 | state.SkipWithError("Invalid JSON string"); 85 | break; 86 | } 87 | } 88 | } 89 | 90 | void write_rapidjson_array_int64(benchmark::State& state) 91 | { 92 | using namespace rapidjson; 93 | std::iota(vec_int64.begin(), vec_int64.end(), 0); 94 | for (auto _ : state) 95 | { 96 | Document doc; 97 | doc.SetArray(); 98 | for (const auto& v : vec_int64) doc.PushBack(v, doc.GetAllocator()); 99 | 100 | StringBuffer buffer; 101 | Writer writer(buffer); 102 | doc.Accept(writer); 103 | auto result = std::string_view(buffer.GetString(), buffer.GetSize()); 104 | if (result.size() != json_size_arr_int64) 105 | { 106 | state.SkipWithError("Invalid JSON string"); 107 | break; 108 | } 109 | } 110 | } 111 | 112 | void write_nlohmann_array_int64(benchmark::State& state) 113 | { 114 | using namespace nlohmann; 115 | std::iota(vec_int64.begin(), vec_int64.end(), 0); 116 | for (auto _ : state) 117 | { 118 | auto array = json(vec_int64); 119 | auto result = array.dump(); 120 | if (result.size() != json_size_arr_int64) 121 | { 122 | state.SkipWithError("Invalid JSON string"); 123 | break; 124 | } 125 | } 126 | } 127 | 128 | void write_c_yyjson_array_double(benchmark::State& state) 129 | { 130 | std::iota(vec_double.begin(), vec_double.end(), 0); 131 | for (auto _ : state) 132 | { 133 | yyjson_mut_doc* doc = yyjson_mut_doc_new(NULL); 134 | auto root = yyjson_mut_arr_with_double(doc, vec_double.data(), vec_double.size()); 135 | yyjson_mut_doc_set_root(doc, root); 136 | const char* json = yyjson_mut_write(doc, 0, NULL); 137 | auto result = std::string_view(json); 138 | if (result.size() != json_size_arr_double) 139 | { 140 | state.SkipWithError("Invalid JSON string"); 141 | break; 142 | } 143 | free(const_cast(static_cast(json))); 144 | yyjson_mut_doc_free(doc); 145 | } 146 | } 147 | 148 | void write_cpp_yyjson_array_double(benchmark::State& state) 149 | { 150 | using namespace yyjson; 151 | std::iota(vec_double.begin(), vec_double.end(), 0); 152 | for (auto _ : state) 153 | { 154 | auto array = yyjson::array(vec_double); 155 | auto result = array.write(); 156 | if (result.size() != json_size_arr_double) 157 | { 158 | state.SkipWithError("Invalid JSON string"); 159 | break; 160 | } 161 | } 162 | } 163 | 164 | void write_cpp_yyjson_single_array_double(benchmark::State& state) 165 | { 166 | using namespace yyjson; 167 | std::iota(vec_double.begin(), vec_double.end(), 0); 168 | auto alc = dynamic_allocator(); 169 | for (auto _ : state) 170 | { 171 | auto array = yyjson::array(vec_double); 172 | auto result = array.write(alc); 173 | if (result.size() != json_size_arr_double) 174 | { 175 | state.SkipWithError("Invalid JSON string"); 176 | break; 177 | } 178 | } 179 | } 180 | 181 | void write_rapidjson_array_double(benchmark::State& state) 182 | { 183 | using namespace rapidjson; 184 | std::iota(vec_double.begin(), vec_double.end(), 0); 185 | for (auto _ : state) 186 | { 187 | Document doc; 188 | doc.SetArray(); 189 | for (const auto v : vec_double) doc.PushBack(v, doc.GetAllocator()); 190 | 191 | StringBuffer buffer; 192 | auto writer = Writer(buffer); 193 | doc.Accept(writer); 194 | auto result = std::string_view(buffer.GetString(), buffer.GetSize()); 195 | 196 | if (result.size() != json_size_arr_double) 197 | { 198 | state.SkipWithError("Invalid JSON string"); 199 | break; 200 | } 201 | } 202 | } 203 | 204 | void write_nlohmann_array_double(benchmark::State& state) 205 | { 206 | using namespace nlohmann; 207 | std::iota(vec_double.begin(), vec_double.end(), 0); 208 | for (auto _ : state) 209 | { 210 | auto array = json(vec_double); 211 | auto result = array.dump(); 212 | if (result.size() != json_size_arr_double) 213 | { 214 | state.SkipWithError("Invalid JSON string"); 215 | break; 216 | } 217 | } 218 | } 219 | 220 | void write_c_yyjson_array_string(benchmark::State& state) 221 | { 222 | std::iota(vec_int64.begin(), vec_int64.end(), 0); 223 | std::ranges::transform(vec_int64, vec_string.begin(), [](const auto n) { return fmt::format("{}", n); }); 224 | for (auto _ : state) 225 | { 226 | yyjson_mut_doc* doc = yyjson_mut_doc_new(NULL); 227 | auto root = yyjson_mut_arr(doc); 228 | for (const auto& s : vec_string) yyjson_mut_arr_add_strn(doc, root, s.c_str(), s.size()); 229 | yyjson_mut_doc_set_root(doc, root); 230 | const char* json = yyjson_mut_write(doc, 0, NULL); 231 | auto result = std::string_view(json); 232 | if (result.size() != json_size_arr_string) 233 | { 234 | state.SkipWithError("Invalid JSON string"); 235 | break; 236 | } 237 | free(const_cast(static_cast(json))); 238 | yyjson_mut_doc_free(doc); 239 | } 240 | } 241 | 242 | void write_cpp_yyjson_array_string(benchmark::State& state) 243 | { 244 | using namespace yyjson; 245 | std::iota(vec_int64.begin(), vec_int64.end(), 0); 246 | std::ranges::transform(vec_int64, vec_string.begin(), [](const auto n) { return fmt::format("{}", n); }); 247 | for (auto _ : state) 248 | { 249 | auto array = yyjson::array(vec_string); 250 | auto result = array.write(); 251 | if (result.size() != json_size_arr_string) 252 | { 253 | state.SkipWithError("Invalid JSON string"); 254 | break; 255 | } 256 | } 257 | } 258 | 259 | void write_cpp_yyjson_single_array_string(benchmark::State& state) 260 | { 261 | using namespace yyjson; 262 | std::iota(vec_int64.begin(), vec_int64.end(), 0); 263 | auto alc = dynamic_allocator(); 264 | std::ranges::transform(vec_int64, vec_string.begin(), [](const auto n) { return fmt::format("{}", n); }); 265 | for (auto _ : state) 266 | { 267 | auto array = yyjson::array(vec_string); 268 | auto result = array.write(alc); 269 | if (result.size() != json_size_arr_string) 270 | { 271 | state.SkipWithError("Invalid JSON string"); 272 | break; 273 | } 274 | } 275 | } 276 | 277 | void write_rapidjson_array_string(benchmark::State& state) 278 | { 279 | using namespace rapidjson; 280 | std::iota(vec_int64.begin(), vec_int64.end(), 0); 281 | std::ranges::transform(vec_int64, vec_string.begin(), [](const auto n) { return fmt::format("{}", n); }); 282 | for (auto _ : state) 283 | { 284 | Document doc; 285 | doc.SetArray(); 286 | for (const auto& s : vec_string) doc.PushBack(StringRef(s.c_str()), doc.GetAllocator()); 287 | 288 | StringBuffer buffer; 289 | Writer writer(buffer); 290 | doc.Accept(writer); 291 | auto result = std::string_view(buffer.GetString(), buffer.GetSize()); 292 | 293 | if (result.size() != json_size_arr_string) 294 | { 295 | state.SkipWithError("Invalid JSON string"); 296 | break; 297 | } 298 | } 299 | } 300 | 301 | void write_c_yyjson_array_string_copy(benchmark::State& state) 302 | { 303 | std::iota(vec_int64.begin(), vec_int64.end(), 0); 304 | std::ranges::transform(vec_int64, vec_string.begin(), [](const auto n) { return fmt::format("{}", n); }); 305 | for (auto _ : state) 306 | { 307 | yyjson_mut_doc* doc = yyjson_mut_doc_new(NULL); 308 | auto root = yyjson_mut_arr(doc); 309 | for (const auto& s : vec_string) yyjson_mut_arr_add_strncpy(doc, root, s.c_str(), s.size()); 310 | yyjson_mut_doc_set_root(doc, root); 311 | const char* json = yyjson_mut_write(doc, 0, NULL); 312 | auto result = std::string_view(json); 313 | if (result.size() != json_size_arr_string) 314 | { 315 | state.SkipWithError("Invalid JSON string"); 316 | break; 317 | } 318 | free(const_cast(static_cast(json))); 319 | yyjson_mut_doc_free(doc); 320 | } 321 | } 322 | 323 | void write_cpp_yyjson_array_string_copy(benchmark::State& state) 324 | { 325 | using namespace yyjson; 326 | std::iota(vec_int64.begin(), vec_int64.end(), 0); 327 | std::ranges::transform(vec_int64, vec_string.begin(), [](const auto n) { return fmt::format("{}", n); }); 328 | for (auto _ : state) 329 | { 330 | auto array = yyjson::array(vec_string, copy_string); 331 | auto result = array.write(); 332 | if (result.size() != json_size_arr_string) 333 | { 334 | state.SkipWithError("Invalid JSON string"); 335 | break; 336 | } 337 | } 338 | } 339 | 340 | void write_rapidjson_array_string_copy(benchmark::State& state) 341 | { 342 | using namespace rapidjson; 343 | std::ranges::transform(vec_int64, vec_string.begin(), [](const auto n) { return fmt::format("{}", n); }); 344 | for (auto _ : state) 345 | { 346 | Document doc; 347 | doc.SetArray(); 348 | for (const auto& s : vec_string) 349 | { 350 | Value str; 351 | str.SetString(s.c_str(), s.size(), doc.GetAllocator()); 352 | doc.PushBack(str.Move(), doc.GetAllocator()); 353 | } 354 | 355 | StringBuffer buffer; 356 | Writer writer(buffer); 357 | doc.Accept(writer); 358 | auto result = std::string_view(buffer.GetString(), buffer.GetSize()); 359 | 360 | if (result.size() != json_size_arr_string) 361 | { 362 | state.SkipWithError("Invalid JSON string"); 363 | break; 364 | } 365 | } 366 | } 367 | 368 | void write_nlohmann_array_string_copy(benchmark::State& state) 369 | { 370 | using namespace nlohmann; 371 | std::iota(vec_int64.begin(), vec_int64.end(), 0); 372 | std::ranges::transform(vec_int64, vec_string.begin(), [](const auto n) { return fmt::format("{}", n); }); 373 | for (auto _ : state) 374 | { 375 | auto array = json(vec_string); 376 | auto result = array.dump(); 377 | if (result.size() != json_size_arr_string) 378 | { 379 | state.SkipWithError("Invalid JSON string"); 380 | break; 381 | } 382 | } 383 | } 384 | 385 | void write_c_yyjson_array_tuple(benchmark::State& state) 386 | { 387 | for (auto i = 0; auto&& t : vec_tuple) 388 | { 389 | std::get<0>(t) = i; 390 | std::get<1>(t) = i + 1.5; 391 | std::get<2>(t) = fmt::format("{}", i + 3.0); 392 | ++i; 393 | } 394 | for (auto _ : state) 395 | { 396 | yyjson_mut_doc* doc = yyjson_mut_doc_new(NULL); 397 | auto root = yyjson_mut_arr(doc); 398 | for (const auto& t : vec_tuple) 399 | { 400 | auto* arr = yyjson_mut_arr_add_arr(doc, root); 401 | yyjson_mut_arr_add_sint(doc, arr, std::get<0>(t)); 402 | yyjson_mut_arr_add_real(doc, arr, std::get<1>(t)); 403 | yyjson_mut_arr_add_strn(doc, arr, std::get<2>(t).c_str(), std::get<2>(t).size()); 404 | } 405 | yyjson_mut_doc_set_root(doc, root); 406 | const char* json = yyjson_mut_write(doc, 0, NULL); 407 | auto result = std::string_view(json); 408 | if (result.size() != json_size_arr_tuple) 409 | { 410 | state.SkipWithError("Invalid JSON string"); 411 | break; 412 | } 413 | free(const_cast(static_cast(json))); 414 | yyjson_mut_doc_free(doc); 415 | } 416 | } 417 | 418 | void write_cpp_yyjson_array_tuple(benchmark::State& state) 419 | { 420 | using namespace yyjson; 421 | for (auto i = 0; auto&& t : vec_tuple) 422 | { 423 | std::get<0>(t) = i; 424 | std::get<1>(t) = i + 1.5; 425 | std::get<2>(t) = fmt::format("{}", i + 3.0); 426 | ++i; 427 | } 428 | for (auto _ : state) 429 | { 430 | auto array = yyjson::array(vec_tuple); 431 | auto result = array.write(); 432 | if (result.size() != json_size_arr_tuple) 433 | { 434 | state.SkipWithError("Invalid JSON string"); 435 | break; 436 | } 437 | } 438 | } 439 | 440 | void write_rapidjson_array_tuple(benchmark::State& state) 441 | { 442 | using namespace rapidjson; 443 | for (auto i = 0; auto&& t : vec_tuple) 444 | { 445 | std::get<0>(t) = i; 446 | std::get<1>(t) = i + 1.5; 447 | std::get<2>(t) = fmt::format("{}", i + 3.0); 448 | ++i; 449 | } 450 | for (auto _ : state) 451 | { 452 | Document doc; 453 | doc.SetArray(); 454 | for (const auto& t : vec_tuple) 455 | { 456 | auto arr = Value(kArrayType); 457 | arr.PushBack(std::get<0>(t), doc.GetAllocator()); 458 | arr.PushBack(std::get<1>(t), doc.GetAllocator()); 459 | arr.PushBack(StringRef(std::get<2>(t).c_str()), doc.GetAllocator()); 460 | doc.PushBack(arr, doc.GetAllocator()); 461 | } 462 | 463 | StringBuffer buffer; 464 | Writer writer(buffer); 465 | doc.Accept(writer); 466 | auto result = std::string_view(buffer.GetString(), buffer.GetSize()); 467 | 468 | if (result.size() != json_size_arr_tuple) 469 | { 470 | state.SkipWithError("Invalid JSON string"); 471 | break; 472 | } 473 | } 474 | } 475 | 476 | void write_nlohmann_array_tuple(benchmark::State& state) 477 | { 478 | using namespace nlohmann; 479 | for (auto i = 0; auto&& t : vec_tuple) 480 | { 481 | std::get<0>(t) = i; 482 | std::get<1>(t) = i + 1.5; 483 | std::get<2>(t) = fmt::format("{}", i + 3.0); 484 | ++i; 485 | } 486 | for (auto _ : state) 487 | { 488 | auto array = json(vec_tuple); 489 | auto result = array.dump(); 490 | if (result.size() != json_size_arr_tuple) 491 | { 492 | state.SkipWithError("Invalid JSON string"); 493 | break; 494 | } 495 | } 496 | } 497 | 498 | void write_c_yyjson_array_object(benchmark::State& state) 499 | { 500 | for (auto i = 0; auto&& t : vec_object) 501 | { 502 | t.i = i; 503 | t.j = i + 1.5; 504 | t.k = fmt::format("{}", i + 3.0); 505 | ++i; 506 | } 507 | for (auto _ : state) 508 | { 509 | yyjson_mut_doc* doc = yyjson_mut_doc_new(NULL); 510 | auto root = yyjson_mut_arr(doc); 511 | for (const auto& t : vec_object) 512 | { 513 | auto* obj = yyjson_mut_arr_add_obj(doc, root); 514 | yyjson_mut_obj_add_sint(doc, obj, "i", t.i); 515 | yyjson_mut_obj_add_real(doc, obj, "j", t.j); 516 | yyjson_mut_obj_add_strn(doc, obj, "k", t.k.c_str(), t.k.size()); 517 | } 518 | yyjson_mut_doc_set_root(doc, root); 519 | const char* json = yyjson_mut_write(doc, 0, NULL); 520 | auto result = std::string_view(json); 521 | if (result.size() != json_size_arr_object) 522 | { 523 | fmt::print("{}\n", result.size()); 524 | state.SkipWithError("Invalid JSON string"); 525 | break; 526 | } 527 | free(const_cast(static_cast(json))); 528 | yyjson_mut_doc_free(doc); 529 | } 530 | } 531 | 532 | void write_cpp_yyjson_array_object(benchmark::State& state) 533 | { 534 | using namespace yyjson; 535 | for (auto i = 0; auto&& t : vec_object) 536 | { 537 | t.i = i; 538 | t.j = i + 1.5; 539 | t.k = fmt::format("{}", i + 3.0); 540 | ++i; 541 | } 542 | for (auto _ : state) 543 | { 544 | auto array = yyjson::array(vec_object); 545 | auto result = array.write(); 546 | if (result.size() != json_size_arr_object) 547 | { 548 | state.SkipWithError("Invalid JSON string"); 549 | break; 550 | } 551 | } 552 | } 553 | 554 | void write_rapidjson_array_object(benchmark::State& state) 555 | { 556 | using namespace rapidjson; 557 | for (auto i = 0; auto&& t : vec_object) 558 | { 559 | t.i = i; 560 | t.j = i + 1.5; 561 | t.k = fmt::format("{}", i + 3.0); 562 | ++i; 563 | } 564 | for (auto _ : state) 565 | { 566 | Document doc; 567 | doc.SetArray(); 568 | for (const auto& t : vec_object) 569 | { 570 | auto obj = Value(kObjectType); 571 | obj.AddMember("i", t.i, doc.GetAllocator()); 572 | obj.AddMember("j", t.j, doc.GetAllocator()); 573 | obj.AddMember("k", StringRef(t.k.c_str()), doc.GetAllocator()); 574 | doc.PushBack(obj, doc.GetAllocator()); 575 | } 576 | 577 | StringBuffer buffer; 578 | Writer writer(buffer); 579 | doc.Accept(writer); 580 | auto result = std::string_view(buffer.GetString(), buffer.GetSize()); 581 | 582 | if (result.size() != json_size_arr_object) 583 | { 584 | state.SkipWithError("Invalid JSON string"); 585 | break; 586 | } 587 | } 588 | } 589 | 590 | void write_nlohmann_array_object(benchmark::State& state) 591 | { 592 | using namespace nlohmann; 593 | for (auto i = 0; auto&& t : vec_object) 594 | { 595 | t.i = i; 596 | t.j = i + 1.5; 597 | t.k = fmt::format("{}", i + 3.0); 598 | ++i; 599 | } 600 | for (auto _ : state) 601 | { 602 | auto array = json::array(); 603 | for (const auto& t : vec_object) 604 | { 605 | auto obj = json::object(); 606 | obj["i"] = t.i; 607 | obj["j"] = t.j; 608 | obj["k"] = t.k; 609 | array.push_back(obj); 610 | } 611 | auto result = array.dump(); 612 | if (result.size() != json_size_arr_object) 613 | { 614 | state.SkipWithError("Invalid JSON string"); 615 | break; 616 | } 617 | } 618 | } 619 | 620 | void write_c_yyjson_array_double_append(benchmark::State& state) 621 | { 622 | std::iota(vec_double.begin(), vec_double.end(), 0); 623 | for (auto _ : state) 624 | { 625 | yyjson_mut_doc* doc = yyjson_mut_doc_new(NULL); 626 | auto root = yyjson_mut_arr(doc); 627 | for (const auto n : vec_double) yyjson_mut_arr_add_real(doc, root, 1.5 * n); 628 | yyjson_mut_doc_set_root(doc, root); 629 | const char* json = yyjson_mut_write(doc, 0, NULL); 630 | auto result = std::string_view(json); 631 | if (result.size() != json_size_arr_double_append) 632 | { 633 | state.SkipWithError("Invalid JSON string"); 634 | break; 635 | } 636 | free(const_cast(static_cast(json))); 637 | yyjson_mut_doc_free(doc); 638 | } 639 | } 640 | 641 | #if (!defined(__clang__) || __clang_major__ >= 16) || (__GNUC__ >= 12) 642 | void write_cpp_yyjson_array_double_append_range(benchmark::State& state) 643 | { 644 | std::iota(vec_double.begin(), vec_double.end(), 0); 645 | for (auto _ : state) 646 | { 647 | auto array = yyjson::array(vec_double | std::ranges::views::transform([](const auto n) { return 1.5 * n; })); 648 | auto result = array.write(); 649 | if (result.size() != json_size_arr_double_append) 650 | { 651 | state.SkipWithError("Invalid JSON string"); 652 | break; 653 | } 654 | } 655 | } 656 | #endif 657 | 658 | void write_cpp_yyjson_array_double_append(benchmark::State& state) 659 | { 660 | std::iota(vec_double.begin(), vec_double.end(), 0); 661 | for (auto _ : state) 662 | { 663 | auto array = yyjson::array(); 664 | for (const auto n : vec_double) array.emplace_back(1.5 * n); 665 | auto result = array.write(); 666 | if (result.size() != json_size_arr_double_append) 667 | { 668 | state.SkipWithError("Invalid JSON string"); 669 | break; 670 | } 671 | } 672 | } 673 | 674 | void write_rapidjson_array_double_append(benchmark::State& state) 675 | { 676 | using namespace rapidjson; 677 | std::iota(vec_double.begin(), vec_double.end(), 0); 678 | for (auto _ : state) 679 | { 680 | Document doc; 681 | doc.SetArray(); 682 | for (const auto n : vec_double) doc.PushBack(1.5 * n, doc.GetAllocator()); 683 | StringBuffer buffer; 684 | auto writer = Writer(buffer); 685 | doc.Accept(writer); 686 | auto result = std::string_view(buffer.GetString(), buffer.GetSize()); 687 | if (result.size() != json_size_arr_double_append) 688 | { 689 | state.SkipWithError("Invalid JSON string"); 690 | break; 691 | } 692 | } 693 | } 694 | 695 | void write_nlohmann_array_double_append(benchmark::State& state) 696 | { 697 | using namespace nlohmann; 698 | std::iota(vec_double.begin(), vec_double.end(), 0); 699 | for (auto _ : state) 700 | { 701 | auto array = json::array(); 702 | for (const auto n : vec_double) array.emplace_back(1.5 * n); 703 | auto result = array.dump(); 704 | if (result.size() != json_size_arr_double_append) 705 | { 706 | state.SkipWithError("Invalid JSON string"); 707 | break; 708 | } 709 | } 710 | } 711 | 712 | void write_c_yyjson_object_int64(benchmark::State& state) 713 | { 714 | std::iota(vec_int64.begin(), vec_int64.end(), 0); 715 | for (auto _ : state) 716 | { 717 | yyjson_mut_doc* doc = yyjson_mut_doc_new(NULL); 718 | auto root = yyjson_mut_obj(doc); 719 | for (auto n : vec_int64) 720 | { 721 | auto key_str = fmt::format("{}", n); 722 | auto key = yyjson_mut_strncpy(doc, key_str.c_str(), key_str.size()); 723 | auto val = yyjson_mut_sint(doc, n); 724 | yyjson_mut_obj_add(root, key, val); 725 | } 726 | yyjson_mut_doc_set_root(doc, root); 727 | const char* json = yyjson_mut_write(doc, 0, NULL); 728 | auto result = std::string_view(json); 729 | if (result.size() != json_size_obj_int64) 730 | { 731 | state.SkipWithError("Invalid JSON string"); 732 | break; 733 | } 734 | free(const_cast(static_cast(json))); 735 | yyjson_mut_doc_free(doc); 736 | } 737 | } 738 | 739 | void write_cpp_yyjson_object_int64(benchmark::State& state) 740 | { 741 | using namespace yyjson; 742 | std::iota(vec_int64.begin(), vec_int64.end(), 0); 743 | for (auto _ : state) 744 | { 745 | auto object = yyjson::object(); 746 | for (auto n : vec_int64) object.emplace(fmt::format("{}", n), n); 747 | auto result = object.write(); 748 | if (result.size() != json_size_obj_int64) 749 | { 750 | state.SkipWithError("Invalid JSON string"); 751 | break; 752 | } 753 | } 754 | } 755 | 756 | void write_rapidjson_object_int64(benchmark::State& state) 757 | { 758 | using namespace rapidjson; 759 | std::iota(vec_int64.begin(), vec_int64.end(), 0); 760 | for (auto _ : state) 761 | { 762 | Document doc; 763 | doc.SetObject(); 764 | for (auto n : vec_int64) 765 | doc.AddMember(Value(fmt::format("{}", n).c_str(), doc.GetAllocator()).Move(), n, doc.GetAllocator()); 766 | 767 | StringBuffer buffer; 768 | Writer writer(buffer); 769 | doc.Accept(writer); 770 | auto result = std::string_view(buffer.GetString(), buffer.GetSize()); 771 | 772 | if (result.size() != json_size_obj_int64) 773 | { 774 | state.SkipWithError("Invalid JSON string"); 775 | break; 776 | } 777 | } 778 | } 779 | 780 | void write_nlohmann_object_int64(benchmark::State& state) 781 | { 782 | using namespace nlohmann; 783 | std::iota(vec_int64.begin(), vec_int64.end(), 0); 784 | for (auto _ : state) 785 | { 786 | auto object = json(); 787 | for (auto n : vec_int64) object[fmt::format("{}", n)] = n; 788 | auto result = object.dump(); 789 | if (result.size() != json_size_obj_int64) 790 | { 791 | state.SkipWithError("Invalid JSON string"); 792 | break; 793 | } 794 | } 795 | } 796 | 797 | void write_c_yyjson_object_double(benchmark::State& state) 798 | { 799 | std::iota(vec_double.begin(), vec_double.end(), 0); 800 | for (auto _ : state) 801 | { 802 | yyjson_mut_doc* doc = yyjson_mut_doc_new(NULL); 803 | auto root = yyjson_mut_obj(doc); 804 | for (auto n : vec_double) 805 | { 806 | auto key_str = fmt::format("{}", n); 807 | auto key = yyjson_mut_strncpy(doc, key_str.c_str(), key_str.size()); 808 | auto val = yyjson_mut_real(doc, n); 809 | yyjson_mut_obj_add(root, key, val); 810 | } 811 | yyjson_mut_doc_set_root(doc, root); 812 | const char* json = yyjson_mut_write(doc, 0, NULL); 813 | auto result = std::string_view(json); 814 | if (result.size() != json_size_obj_double) 815 | { 816 | state.SkipWithError("Invalid JSON string"); 817 | break; 818 | } 819 | free(const_cast(static_cast(json))); 820 | yyjson_mut_doc_free(doc); 821 | } 822 | } 823 | 824 | void write_cpp_yyjson_object_double(benchmark::State& state) 825 | { 826 | using namespace yyjson; 827 | std::iota(vec_double.begin(), vec_double.end(), 0); 828 | for (auto _ : state) 829 | { 830 | auto object = yyjson::object(); 831 | for (auto n : vec_double) object.emplace(fmt::format("{}", n), n); 832 | auto result = object.write(); 833 | if (result.size() != json_size_obj_double) 834 | { 835 | state.SkipWithError("Invalid JSON string"); 836 | break; 837 | } 838 | } 839 | } 840 | 841 | void write_rapidjson_object_double(benchmark::State& state) 842 | { 843 | using namespace rapidjson; 844 | std::iota(vec_double.begin(), vec_double.end(), 0); 845 | for (auto _ : state) 846 | { 847 | Document doc; 848 | doc.SetObject(); 849 | for (auto n : vec_double) 850 | doc.AddMember(Value(fmt::format("{}", n).c_str(), doc.GetAllocator()).Move(), n, doc.GetAllocator()); 851 | 852 | StringBuffer buffer; 853 | Writer writer(buffer); 854 | doc.Accept(writer); 855 | auto result = std::string_view(buffer.GetString(), buffer.GetSize()); 856 | 857 | if (result.size() != json_size_obj_double) 858 | { 859 | state.SkipWithError("Invalid JSON string"); 860 | break; 861 | } 862 | } 863 | } 864 | 865 | void write_nlohmann_object_double(benchmark::State& state) 866 | { 867 | using namespace nlohmann; 868 | std::iota(vec_double.begin(), vec_double.end(), 0); 869 | for (auto _ : state) 870 | { 871 | auto object = json(); 872 | for (auto n : vec_double) object[fmt::format("{}", n)] = n; 873 | auto result = object.dump(); 874 | if (result.size() != json_size_obj_double) 875 | { 876 | state.SkipWithError("Invalid JSON string"); 877 | break; 878 | } 879 | } 880 | } 881 | 882 | void write_c_yyjson_object_string(benchmark::State& state) 883 | { 884 | std::iota(vec_int64.begin(), vec_int64.end(), 0); 885 | std::ranges::transform(vec_int64, vec_string.begin(), [](const auto n) { return fmt::format("{}", n); }); 886 | for (auto _ : state) 887 | { 888 | yyjson_mut_doc* doc = yyjson_mut_doc_new(NULL); 889 | auto root = yyjson_mut_obj(doc); 890 | for (auto n : vec_string) 891 | { 892 | auto key = yyjson_mut_strn(doc, n.c_str(), n.size()); 893 | auto val = yyjson_mut_strn(doc, n.c_str(), n.size()); 894 | yyjson_mut_obj_add(root, key, val); 895 | } 896 | yyjson_mut_doc_set_root(doc, root); 897 | const char* json = yyjson_mut_write(doc, 0, NULL); 898 | auto result = std::string_view(json); 899 | if (result.size() != json_size_obj_string) 900 | { 901 | state.SkipWithError("Invalid JSON string"); 902 | break; 903 | } 904 | free(const_cast(static_cast(json))); 905 | yyjson_mut_doc_free(doc); 906 | } 907 | } 908 | 909 | void write_cpp_yyjson_object_string(benchmark::State& state) 910 | { 911 | using namespace yyjson; 912 | std::iota(vec_int64.begin(), vec_int64.end(), 0); 913 | std::ranges::transform(vec_int64, vec_string.begin(), [](const auto n) { return fmt::format("{}", n); }); 914 | for (auto _ : state) 915 | { 916 | auto object = yyjson::object(); 917 | for (auto n : vec_string) 918 | { 919 | object.emplace(n, n); 920 | } 921 | auto result = object.write(); 922 | if (result.size() != json_size_obj_string) 923 | { 924 | state.SkipWithError("Invalid JSON string"); 925 | break; 926 | } 927 | } 928 | } 929 | 930 | void write_rapidjson_object_string(benchmark::State& state) 931 | { 932 | using namespace rapidjson; 933 | std::iota(vec_int64.begin(), vec_int64.end(), 0); 934 | std::ranges::transform(vec_int64, vec_string.begin(), [](const auto n) { return fmt::format("{}", n); }); 935 | for (auto _ : state) 936 | { 937 | Document doc; 938 | doc.SetObject(); 939 | for (auto n : vec_string) 940 | { 941 | doc.AddMember(StringRef(n.c_str()), StringRef(n.c_str()), doc.GetAllocator()); 942 | } 943 | 944 | StringBuffer buffer; 945 | Writer writer(buffer); 946 | doc.Accept(writer); 947 | auto result = std::string_view(buffer.GetString(), buffer.GetSize()); 948 | 949 | if (result.size() != json_size_obj_string) 950 | { 951 | state.SkipWithError("Invalid JSON string"); 952 | break; 953 | } 954 | } 955 | } 956 | 957 | void write_c_yyjson_object_string_copy(benchmark::State& state) 958 | { 959 | std::iota(vec_int64.begin(), vec_int64.end(), 0); 960 | std::ranges::transform(vec_int64, vec_string.begin(), [](const auto n) { return fmt::format("{}", n); }); 961 | for (auto _ : state) 962 | { 963 | yyjson_mut_doc* doc = yyjson_mut_doc_new(NULL); 964 | auto root = yyjson_mut_obj(doc); 965 | for (auto n : vec_string) 966 | { 967 | auto key = yyjson_mut_strncpy(doc, n.c_str(), n.size()); 968 | auto val = yyjson_mut_strncpy(doc, n.c_str(), n.size()); 969 | yyjson_mut_obj_add(root, key, val); 970 | } 971 | yyjson_mut_doc_set_root(doc, root); 972 | const char* json = yyjson_mut_write(doc, 0, NULL); 973 | auto result = std::string_view(json); 974 | if (result.size() != json_size_obj_string) 975 | { 976 | state.SkipWithError("Invalid JSON string"); 977 | break; 978 | } 979 | free(const_cast(static_cast(json))); 980 | yyjson_mut_doc_free(doc); 981 | } 982 | } 983 | 984 | void write_cpp_yyjson_object_string_copy(benchmark::State& state) 985 | { 986 | using namespace yyjson; 987 | std::iota(vec_int64.begin(), vec_int64.end(), 0); 988 | std::ranges::transform(vec_int64, vec_string.begin(), [](const auto n) { return fmt::format("{}", n); }); 989 | for (auto _ : state) 990 | { 991 | auto object = yyjson::object(); 992 | for (auto n : vec_string) 993 | { 994 | object.emplace(n, n, copy_string); 995 | } 996 | auto result = object.write(); 997 | if (result.size() != json_size_obj_string) 998 | { 999 | state.SkipWithError("Invalid JSON string"); 1000 | break; 1001 | } 1002 | } 1003 | } 1004 | 1005 | void write_rapidjson_object_string_copy(benchmark::State& state) 1006 | { 1007 | using namespace rapidjson; 1008 | std::iota(vec_int64.begin(), vec_int64.end(), 0); 1009 | std::ranges::transform(vec_int64, vec_string.begin(), [](const auto n) { return fmt::format("{}", n); }); 1010 | for (auto _ : state) 1011 | { 1012 | Document doc; 1013 | doc.SetObject(); 1014 | for (auto n : vec_string) 1015 | { 1016 | doc.AddMember(Value(n.c_str(), doc.GetAllocator()).Move(), Value(n.c_str(), doc.GetAllocator()).Move(), 1017 | doc.GetAllocator()); 1018 | } 1019 | 1020 | StringBuffer buffer; 1021 | Writer writer(buffer); 1022 | doc.Accept(writer); 1023 | auto result = std::string_view(buffer.GetString(), buffer.GetSize()); 1024 | 1025 | if (result.size() != json_size_obj_string) 1026 | { 1027 | state.SkipWithError("Invalid JSON string"); 1028 | break; 1029 | } 1030 | } 1031 | } 1032 | 1033 | void write_nlohmann_object_string_copy(benchmark::State& state) 1034 | { 1035 | using namespace nlohmann; 1036 | std::iota(vec_int64.begin(), vec_int64.end(), 0); 1037 | std::ranges::transform(vec_int64, vec_string.begin(), [](const auto n) { return fmt::format("{}", n); }); 1038 | for (auto _ : state) 1039 | { 1040 | auto object = json(); 1041 | for (auto n : vec_string) 1042 | { 1043 | object[n] = n; 1044 | } 1045 | auto result = object.dump(); 1046 | if (result.size() != json_size_obj_string) 1047 | { 1048 | state.SkipWithError("Invalid JSON string"); 1049 | break; 1050 | } 1051 | } 1052 | } 1053 | 1054 | BENCHMARK(write_cpp_yyjson_array_int64)->Unit(benchmark::kMillisecond); 1055 | BENCHMARK(write_cpp_yyjson_single_array_int64)->Unit(benchmark::kMillisecond); 1056 | BENCHMARK(write_c_yyjson_array_int64)->Unit(benchmark::kMillisecond); 1057 | BENCHMARK(write_rapidjson_array_int64)->Unit(benchmark::kMillisecond); 1058 | BENCHMARK(write_nlohmann_array_int64)->Unit(benchmark::kMillisecond); 1059 | BENCHMARK(write_cpp_yyjson_array_double)->Unit(benchmark::kMillisecond); 1060 | BENCHMARK(write_cpp_yyjson_single_array_double)->Unit(benchmark::kMillisecond); 1061 | BENCHMARK(write_c_yyjson_array_double)->Unit(benchmark::kMillisecond); 1062 | BENCHMARK(write_rapidjson_array_double)->Unit(benchmark::kMillisecond); 1063 | BENCHMARK(write_nlohmann_array_double)->Unit(benchmark::kMillisecond); 1064 | BENCHMARK(write_cpp_yyjson_array_string)->Unit(benchmark::kMillisecond); 1065 | BENCHMARK(write_cpp_yyjson_single_array_string)->Unit(benchmark::kMillisecond); 1066 | BENCHMARK(write_c_yyjson_array_string)->Unit(benchmark::kMillisecond); 1067 | BENCHMARK(write_rapidjson_array_string)->Unit(benchmark::kMillisecond); 1068 | BENCHMARK(write_cpp_yyjson_array_string_copy)->Unit(benchmark::kMillisecond); 1069 | BENCHMARK(write_c_yyjson_array_string_copy)->Unit(benchmark::kMillisecond); 1070 | BENCHMARK(write_rapidjson_array_string_copy)->Unit(benchmark::kMillisecond); 1071 | BENCHMARK(write_nlohmann_array_string_copy)->Unit(benchmark::kMillisecond); 1072 | BENCHMARK(write_cpp_yyjson_array_tuple)->Unit(benchmark::kMillisecond); 1073 | BENCHMARK(write_c_yyjson_array_tuple)->Unit(benchmark::kMillisecond); 1074 | BENCHMARK(write_rapidjson_array_tuple)->Unit(benchmark::kMillisecond); 1075 | BENCHMARK(write_nlohmann_array_tuple)->Unit(benchmark::kMillisecond); 1076 | BENCHMARK(write_cpp_yyjson_array_object)->Unit(benchmark::kMillisecond); 1077 | BENCHMARK(write_c_yyjson_array_object)->Unit(benchmark::kMillisecond); 1078 | BENCHMARK(write_rapidjson_array_object)->Unit(benchmark::kMillisecond); 1079 | BENCHMARK(write_nlohmann_array_object)->Unit(benchmark::kMillisecond); 1080 | 1081 | #if (!defined(__clang__) || __clang_major__ >= 16) || (__GNUC__ >= 12) 1082 | BENCHMARK(write_cpp_yyjson_array_double_append_range)->Unit(benchmark::kMillisecond); 1083 | #endif 1084 | BENCHMARK(write_cpp_yyjson_array_double_append)->Unit(benchmark::kMillisecond); 1085 | BENCHMARK(write_c_yyjson_array_double_append)->Unit(benchmark::kMillisecond); 1086 | BENCHMARK(write_rapidjson_array_double_append)->Unit(benchmark::kMillisecond); 1087 | BENCHMARK(write_nlohmann_array_double_append)->Unit(benchmark::kMillisecond); 1088 | 1089 | BENCHMARK(write_cpp_yyjson_object_int64)->Unit(benchmark::kMillisecond); 1090 | BENCHMARK(write_c_yyjson_object_int64)->Unit(benchmark::kMillisecond); 1091 | BENCHMARK(write_rapidjson_object_int64)->Unit(benchmark::kMillisecond); 1092 | BENCHMARK(write_nlohmann_object_int64)->Unit(benchmark::kMillisecond); 1093 | BENCHMARK(write_cpp_yyjson_object_double)->Unit(benchmark::kMillisecond); 1094 | BENCHMARK(write_c_yyjson_object_double)->Unit(benchmark::kMillisecond); 1095 | BENCHMARK(write_rapidjson_object_double)->Unit(benchmark::kMillisecond); 1096 | BENCHMARK(write_nlohmann_object_double)->Unit(benchmark::kMillisecond); 1097 | BENCHMARK(write_cpp_yyjson_object_string)->Unit(benchmark::kMillisecond); 1098 | BENCHMARK(write_c_yyjson_object_string)->Unit(benchmark::kMillisecond); 1099 | BENCHMARK(write_rapidjson_object_string)->Unit(benchmark::kMillisecond); 1100 | BENCHMARK(write_cpp_yyjson_object_string_copy)->Unit(benchmark::kMillisecond); 1101 | BENCHMARK(write_c_yyjson_object_string_copy)->Unit(benchmark::kMillisecond); 1102 | BENCHMARK(write_rapidjson_object_string_copy)->Unit(benchmark::kMillisecond); 1103 | BENCHMARK(write_nlohmann_object_string_copy)->Unit(benchmark::kMillisecond); 1104 | 1105 | BENCHMARK_MAIN(); 1106 | // NOLINTEND 1107 | -------------------------------------------------------------------------------- /test/bench_write.log: -------------------------------------------------------------------------------- 1 | write_cpp_yyjson_array_int64_median 2.73 ms 2.73 ms 100 2 | write_c_yyjson_array_int64_median 2.92 ms 2.92 ms 100 3 | write_rapidjson_array_int64_median 20.3 ms 20.3 ms 100 4 | write_nlohmann_array_int64_median 15.1 ms 15.1 ms 100 5 | write_cpp_yyjson_array_double_median 4.12 ms 4.11 ms 100 6 | write_c_yyjson_array_double_median 4.35 ms 4.35 ms 100 7 | write_rapidjson_array_double_median 34.6 ms 34.6 ms 100 8 | write_nlohmann_array_double_median 32.0 ms 32.0 ms 100 9 | write_cpp_yyjson_array_string_median 5.09 ms 5.09 ms 100 10 | write_c_yyjson_array_string_median 6.08 ms 6.08 ms 100 11 | write_rapidjson_array_string_median 20.6 ms 20.6 ms 100 12 | write_cpp_yyjson_array_string_copy_median 12.1 ms 12.1 ms 100 13 | write_c_yyjson_array_string_copy_median 12.4 ms 12.4 ms 100 14 | write_rapidjson_array_string_copy_median 23.1 ms 23.1 ms 100 15 | write_nlohmann_array_string_copy_median 38.9 ms 38.9 ms 100 16 | write_cpp_yyjson_array_tuple_median 36.1 ms 36.1 ms 100 17 | write_c_yyjson_array_tuple_median 36.9 ms 36.9 ms 100 18 | write_rapidjson_array_tuple_median 95.7 ms 95.7 ms 100 19 | write_nlohmann_array_tuple_median 147 ms 147 ms 100 20 | write_cpp_yyjson_array_object_median 46.7 ms 46.7 ms 100 21 | write_c_yyjson_array_object_median 48.1 ms 48.1 ms 100 22 | write_rapidjson_array_object_median 151 ms 151 ms 100 23 | write_nlohmann_array_object_median 401 ms 401 ms 100 24 | write_cpp_yyjson_array_double_append_range_median 8.51 ms 8.51 ms 100 25 | write_cpp_yyjson_array_double_append_median 9.58 ms 9.58 ms 100 26 | write_c_yyjson_array_double_append_median 9.80 ms 9.80 ms 100 27 | write_rapidjson_array_double_append_median 26.5 ms 26.5 ms 100 28 | write_nlohmann_array_double_append_median 33.0 ms 33.0 ms 100 29 | write_cpp_yyjson_object_int64_median 18.2 ms 18.2 ms 100 30 | write_c_yyjson_object_int64_median 17.9 ms 17.9 ms 100 31 | write_rapidjson_object_int64_median 36.0 ms 36.0 ms 100 32 | write_nlohmann_object_int64_median 198 ms 198 ms 100 33 | write_cpp_yyjson_object_double_median 34.5 ms 34.4 ms 100 34 | write_c_yyjson_object_double_median 34.6 ms 34.6 ms 100 35 | write_rapidjson_object_double_median 68.3 ms 68.3 ms 100 36 | write_nlohmann_object_double_median 238 ms 238 ms 100 37 | write_cpp_yyjson_object_string_median 11.7 ms 11.7 ms 100 38 | write_c_yyjson_object_string_median 12.4 ms 12.4 ms 100 39 | write_rapidjson_object_string_median 24.3 ms 24.3 ms 100 40 | write_cpp_yyjson_object_string_copy_median 14.1 ms 14.1 ms 100 41 | write_c_yyjson_object_string_copy_median 14.6 ms 14.6 ms 100 42 | write_rapidjson_object_string_copy_median 31.2 ms 31.2 ms 100 43 | write_nlohmann_object_string_copy_median 236 ms 236 ms 100 44 | --------------------------------------------------------------------------------