diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..86cbf0d --- /dev/null +++ b/.clang-format @@ -0,0 +1,163 @@ +--- +Language: Cpp +# BasedOnStyle: Microsoft +AccessModifierOffset: -2 +AlignAfterOpenBracket: BlockIndent +AlignEscapedNewlines: Right +AlignOperands: Align +AlignTrailingComments: false +AlignConsecutiveAssignments: true +AlignConsecutiveDeclarations: true +AllowAllArgumentsOnNextLine: true +AllowAllConstructorInitializersOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortEnumsOnASingleLine: false +AllowShortBlocksOnASingleLine: Never +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: None +AllowShortLambdasOnASingleLine: All +AllowShortIfStatementsOnASingleLine: Never +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: MultiLine +AttributeMacros: + - __capability +BinPackArguments: false +BinPackParameters: AlwaysOnePerLine +BraceWrapping: + AfterCaseLabel: false + AfterClass: true + AfterControlStatement: Always + AfterEnum: true + AfterFunction: true + AfterNamespace: true + AfterObjCDeclaration: true + AfterStruct: true + AfterUnion: false + AfterExternBlock: true + BeforeCatch: true + BeforeElse: true + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: None +BreakBeforeConceptDeclarations: true +BreakBeforeBraces: Custom +BreakBeforeInheritanceComma: false +BreakInheritanceList: BeforeColon +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: BeforeColon +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: true +ColumnLimit: 120 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DeriveLineEnding: true +DerivePointerAlignment: false +DisableFormat: false +EmptyLineBeforeAccessModifier: LogicalBlock +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +StatementAttributeLikeMacros: + - Q_EMIT +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '^"(llvm|llvm-c|clang|clang-c)/' + Priority: 2 + SortPriority: 0 + CaseSensitive: false + - Regex: '^(<|"(gtest|gmock|isl|json)/)' + Priority: 3 + SortPriority: 0 + CaseSensitive: false + - Regex: '.*' + Priority: 1 + SortPriority: 0 + CaseSensitive: false +IncludeIsMainRegex: '(Test)?$' +IncludeIsMainSourceRegex: '' +IndentCaseLabels: false +IndentCaseBlocks: false +IndentGotoLabels: true +IndentPPDirectives: None +IndentExternBlock: AfterExternBlock +IndentRequires: false +IndentWidth: 4 +IndentWrappedFunctionNames: false +InsertTrailingCommas: None +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: true +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBinPackProtocolList: Auto +ObjCBlockIndentWidth: 2 +ObjCBreakBeforeNestedBlockParam: true +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 1000 +PenaltyIndentedWhitespace: 0 +PointerAlignment: Right +ReflowComments: true +SortIncludes: true +SortJavaStaticImport: Before +SortUsingDeclarations: true +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeCaseColon: false +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceAroundPointerQualifiers: Default +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyBlock: false +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInConditionalStatement: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +SpaceBeforeSquareBrackets: false +BitFieldColonSpacing: Both +Standard: Latest +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION +TabWidth: 4 +UseCRLF: false +UseTab: Never +WhitespaceSensitiveMacros: + - STRINGIZE + - PP_STRINGIZE + - BOOST_PP_STRINGIZE + - NS_SWIFT_NAME + - CF_SWIFT_NAME +... diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 0000000..3ddf761 --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,593 @@ +--- +Checks: '*, + -bugprone-easily-swappable-parameters, + -bugprone-lambda-function-name, + -readability-magic-numbers, + -hicpp-no-array-decay, + -hicpp-signed-bitwise, + -hicpp-vararg, + -misc-non-private-member-variables-in-classes, + -cppcoreguidelines-*, + -fuchsia-*, + -altera-*, + -android-*, + -llvmlibc-*, + -readability-convert-member-functions-to-static, + -boost-use-ranges, + -google-objc-function-naming, + -google-objc-global-variable-declaration, + -performance-enum-size' +WarningsAsErrors: '' +HeaderFilterRegex: '^(?!magic_enum).*$' +FormatStyle: Microsoft +CheckOptions: + - key: readability-identifier-naming.ClassCase + value: CamelCase + - key: readability-identifier-naming.ClassMemberCase + value: lower_case + - key: readability-identifier-naming.ConstexprVariableCase + value: CamelCase + - key: readability-identifier-naming.ConstexprVariablePrefix + value: k + - key: readability-identifier-naming.EnumCase + value: CamelCase + - key: readability-identifier-naming.EnumConstantCase + value: CamelCase + - key: readability-identifier-naming.EnumConstantPrefix + value: k + - key: readability-identifier-naming.FunctionCase + value: camelBack + - key: readability-identifier-naming.FunctionIgnoredRegexp + value: '^BM_.*$' + - key: readability-identifier-naming.GlobalConstantCase + value: CamelCase + - key: readability-identifier-naming.GlobalConstantPrefix + value: k + - key: readability-identifier-naming.StaticConstantCase + value: CamelCase + - key: readability-identifier-naming.StaticConstantPrefix + value: k + - key: readability-identifier-naming.StaticVariableCase + value: lower_case + - key: readability-identifier-naming.MacroDefinitionCase + value: UPPER_CASE + - key: readability-identifier-naming.MacroDefinitionIgnoredRegexp + value: '^[A-Z]+(_[A-Z]+)*_$' + - key: readability-identifier-naming.MemberCase + value: lower_case + - key: readability-identifier-naming.PrivateMemberSuffix + value: _ + - key: readability-identifier-naming.PublicMemberSuffix + value: '' + - key: readability-identifier-naming.NamespaceCase + value: lower_case + - key: readability-identifier-naming.ParameterCase + value: lower_case + - key: readability-identifier-naming.TypeAliasCase + value: CamelCase + - key: readability-identifier-naming.TypedefCase + value: CamelCase + - key: readability-identifier-naming.VariableCase + value: lower_case + - key: readability-identifier-naming.IgnoreMainLikeFunctions + value: 'true' + - key: readability-identifier-naming.AggressiveDependentMemberLookup + value: 'false' + - key: readability-identifier-naming.IgnoreFailedSplit + value: 'false' + - key: abseil-string-find-startswith.AbseilStringsMatchHeader + value: 'absl/strings/match.h' + - key: abseil-string-find-startswith.IncludeStyle + value: llvm + - key: abseil-string-find-startswith.StringLikeClasses + value: '::std::basic_string' + - key: abseil-string-find-str-contains.AbseilStringsMatchHeader + value: 'absl/strings/match.h' + - key: abseil-string-find-str-contains.IncludeStyle + value: llvm + - key: abseil-string-find-str-contains.StringLikeClasses + value: '::std::basic_string;::std::basic_string_view;::absl::string_view' + - key: bugprone-argument-comment.CommentBoolLiterals + value: '0' + - key: bugprone-argument-comment.CommentCharacterLiterals + value: '0' + - key: bugprone-argument-comment.CommentFloatLiterals + value: '0' + - key: bugprone-argument-comment.CommentIntegerLiterals + value: '0' + - key: bugprone-argument-comment.CommentNullPtrs + value: '0' + - key: bugprone-argument-comment.CommentStringLiterals + value: '0' + - key: bugprone-argument-comment.CommentUserDefinedLiterals + value: '0' + - key: bugprone-argument-comment.IgnoreSingleArgument + value: '0' + - key: bugprone-argument-comment.StrictMode + value: '0' + - key: bugprone-assert-side-effect.AssertMacros + value: assert + - key: bugprone-assert-side-effect.CheckFunctionCalls + value: 'false' + - key: bugprone-dangling-handle.HandleClasses + value: 'std::basic_string_view;std::experimental::basic_string_view' + - key: bugprone-dynamic-static-initializers.HeaderFileExtensions + value: ';h;hh;hpp;hxx' + - key: bugprone-exception-escape.FunctionsThatShouldNotThrow + value: '' + - key: bugprone-exception-escape.IgnoredExceptions + value: '' + - key: bugprone-misplaced-widening-cast.CheckImplicitCasts + value: 'false' + - key: bugprone-narrowing-conversions.PedanticMode + value: 'false' + - key: bugprone-narrowing-conversions.WarnOnFloatingPointNarrowingConversion + value: 'true' + - key: bugprone-not-null-terminated-result.WantToUseSafeFunctions + value: 'true' + - key: bugprone-reserved-identifier.AggressiveDependentMemberLookup + value: 'false' + - key: bugprone-reserved-identifier.AllowedIdentifiers + value: '' + - key: bugprone-reserved-identifier.Invert + value: 'false' + - key: bugprone-signed-char-misuse.CharTypdefsToIgnore + value: '' + - key: bugprone-signed-char-misuse.DiagnoseSignedUnsignedCharComparisons + value: 'true' + - key: bugprone-sizeof-expression.WarnOnSizeOfCompareToConstant + value: 'true' + - key: bugprone-sizeof-expression.WarnOnSizeOfConstant + value: 'true' + - key: bugprone-sizeof-expression.WarnOnSizeOfIntegerExpression + value: 'false' + - key: bugprone-sizeof-expression.WarnOnSizeOfThis + value: 'true' + - key: bugprone-string-constructor.LargeLengthThreshold + value: '8388608' + - key: bugprone-string-constructor.WarnOnLargeLength + value: 'true' + - key: bugprone-suspicious-enum-usage.StrictMode + value: 'false' + - key: bugprone-suspicious-include.HeaderFileExtensions + value: ';h;hh;hpp;hxx' + - key: bugprone-suspicious-include.ImplementationFileExtensions + value: 'c;cc;cpp;cxx' + - key: bugprone-suspicious-missing-comma.MaxConcatenatedTokens + value: '5' + - key: bugprone-suspicious-missing-comma.RatioThreshold + value: '0.200000' + - key: bugprone-suspicious-missing-comma.SizeThreshold + value: '5' + - key: bugprone-suspicious-string-compare.StringCompareLikeFunctions + value: '' + - key: bugprone-suspicious-string-compare.WarnOnImplicitComparison + value: 'true' + - key: bugprone-suspicious-string-compare.WarnOnLogicalNotComparison + value: 'false' + - key: bugprone-too-small-loop-variable.MagnitudeBitsUpperLimit + value: '16' + - key: bugprone-unhandled-self-assignment.WarnOnlyIfThisHasSuspiciousField + value: 'true' + - key: bugprone-unused-return-value.CheckedFunctions + value: '::std::async;::std::launder;::std::remove;::std::remove_if;::std::unique;::std::unique_ptr::release;::std::basic_string::empty;::std::vector::empty;::std::back_inserter;::std::distance;::std::find;::std::find_if;::std::inserter;::std::lower_bound;::std::make_pair;::std::map::count;::std::map::find;::std::map::lower_bound;::std::multimap::equal_range;::std::multimap::upper_bound;::std::set::count;::std::set::find;::std::setfill;::std::setprecision;::std::setw;::std::upper_bound;::std::vector::at;::bsearch;::ferror;::feof;::isalnum;::isalpha;::isblank;::iscntrl;::isdigit;::isgraph;::islower;::isprint;::ispunct;::isspace;::isupper;::iswalnum;::iswprint;::iswspace;::isxdigit;::memchr;::memcmp;::strcmp;::strcoll;::strncmp;::strpbrk;::strrchr;::strspn;::strstr;::wcscmp;::access;::bind;::connect;::difftime;::dlsym;::fnmatch;::getaddrinfo;::getopt;::htonl;::htons;::iconv_open;::inet_addr;::isascii;::isatty;::mmap;::newlocale;::openat;::pathconf;::pthread_equal;::pthread_getspecific;::pthread_mutex_trylock;::readdir;::readlink;::recvmsg;::regexec;::scandir;::semget;::setjmp;::shm_open;::shmget;::sigismember;::strcasecmp;::strsignal;::ttyname' + - key: cert-dcl16-c.IgnoreMacros + value: 'true' + - key: cert-dcl16-c.NewSuffixes + value: 'L;LL;LU;LLU' + - key: cert-dcl37-c.AggressiveDependentMemberLookup + value: 'false' + - key: cert-dcl37-c.AllowedIdentifiers + value: '' + - key: cert-dcl37-c.Invert + value: 'false' + - key: cert-dcl51-cpp.AggressiveDependentMemberLookup + value: 'false' + - key: cert-dcl51-cpp.AllowedIdentifiers + value: '' + - key: cert-dcl51-cpp.Invert + value: 'false' + - key: cert-dcl59-cpp.HeaderFileExtensions + value: ';h;hh;hpp;hxx' + - key: cert-err09-cpp.CheckThrowTemporaries + value: 'true' + - key: cert-err09-cpp.MaxSize + value: '-1' + - key: cert-err09-cpp.WarnOnLargeObjects + value: 'false' + - key: cert-err61-cpp.CheckThrowTemporaries + value: 'true' + - key: cert-err61-cpp.MaxSize + value: '-1' + - key: cert-err61-cpp.WarnOnLargeObjects + value: 'false' + - key: cert-msc32-c.DisallowedSeedTypes + value: 'time_t,std::time_t' + - key: cert-msc51-cpp.DisallowedSeedTypes + value: 'time_t,std::time_t' + - key: cert-oop11-cpp.IncludeStyle + value: llvm + - key: cert-oop54-cpp.WarnOnlyIfThisHasSuspiciousField + value: 'false' + - key: cert-oop57-cpp.MemCmpNames + value: '' + - key: cert-oop57-cpp.MemCpyNames + value: '' + - key: cert-oop57-cpp.MemSetNames + value: '' + - key: cert-str34-c.CharTypdefsToIgnore + value: '' + - key: cert-str34-c.DiagnoseSignedUnsignedCharComparisons + value: 'false' + - key: cppcoreguidelines-avoid-magic-numbers.IgnoreAllFloatingPointValues + value: 'false' + - key: cppcoreguidelines-avoid-magic-numbers.IgnoreBitFieldsWidths + value: 'true' + - key: cppcoreguidelines-avoid-magic-numbers.IgnorePowersOf2IntegerValues + value: 'false' + - key: cppcoreguidelines-avoid-magic-numbers.IgnoredFloatingPointValues + value: '1.0;100.0;' + - key: cppcoreguidelines-avoid-magic-numbers.IgnoredIntegerValues + value: '1;2;3;4;' + - key: cppcoreguidelines-explicit-virtual-functions.AllowOverrideAndFinal + value: 'false' + - key: cppcoreguidelines-explicit-virtual-functions.FinalSpelling + value: final + - key: cppcoreguidelines-explicit-virtual-functions.IgnoreDestructors + value: 'true' + - key: cppcoreguidelines-explicit-virtual-functions.OverrideSpelling + value: override + - key: cppcoreguidelines-init-variables.IncludeStyle + value: llvm + - key: cppcoreguidelines-init-variables.MathHeader + value: math.h + - key: cppcoreguidelines-macro-usage.AllowedRegexp + value: '^DEBUG_*' + - key: cppcoreguidelines-macro-usage.CheckCapsOnly + value: 'false' + - key: cppcoreguidelines-macro-usage.IgnoreCommandLineMacros + value: 'true' + - key: cppcoreguidelines-narrowing-conversions.PedanticMode + value: 'false' + - key: cppcoreguidelines-narrowing-conversions.WarnOnFloatingPointNarrowingConversion + value: 'true' + - key: cppcoreguidelines-no-malloc.Allocations + value: '::malloc;::calloc' + - key: cppcoreguidelines-no-malloc.Deallocations + value: '::free' + - key: cppcoreguidelines-no-malloc.Reallocations + value: '::realloc' + - key: cppcoreguidelines-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic + value: 'true' + - key: cppcoreguidelines-non-private-member-variables-in-classes.IgnorePublicMemberVariables + value: 'false' + - key: cppcoreguidelines-owning-memory.LegacyResourceConsumers + value: '::free;::realloc;::freopen;::fclose' + - key: cppcoreguidelines-owning-memory.LegacyResourceProducers + value: '::malloc;::aligned_alloc;::realloc;::calloc;::fopen;::freopen;::tmpfile' + - key: cppcoreguidelines-pro-bounds-constant-array-index.GslHeader + value: '' + - key: cppcoreguidelines-pro-bounds-constant-array-index.IncludeStyle + value: llvm + - key: cppcoreguidelines-pro-type-member-init.IgnoreArrays + value: 'false' + - key: cppcoreguidelines-pro-type-member-init.UseAssignment + value: 'false' + - key: cppcoreguidelines-special-member-functions.AllowMissingMoveFunctions + value: 'false' + - key: cppcoreguidelines-special-member-functions.AllowMissingMoveFunctionsWhenCopyIsDeleted + value: 'false' + - key: cppcoreguidelines-special-member-functions.AllowSoleDefaultDtor + value: 'false' + - key: google-build-namespaces.HeaderFileExtensions + value: ';h;hh;hpp;hxx' + - key: google-global-names-in-headers.HeaderFileExtensions + value: ';h;hh;hpp;hxx' + - key: google-readability-braces-around-statements.ShortStatementLines + value: '1' + - key: google-readability-function-size.BranchThreshold + value: '4294967295' + - key: google-readability-function-size.LineThreshold + value: '4294967295' + - key: google-readability-function-size.NestingThreshold + value: '4294967295' + - key: google-readability-function-size.ParameterThreshold + value: '4294967295' + - key: google-readability-function-size.StatementThreshold + value: '800' + - key: google-readability-function-size.VariableThreshold + value: '4294967295' + - key: google-readability-namespace-comments.ShortNamespaceLines + value: '10' + - key: google-readability-namespace-comments.SpacesBeforeComments + value: '2' + - key: google-runtime-int.SignedTypePrefix + value: int + - key: google-runtime-int.TypeSuffix + value: '' + - key: google-runtime-int.UnsignedTypePrefix + value: uint + - key: google-runtime-references.IncludedTypes + value: '' + - key: hicpp-braces-around-statements.ShortStatementLines + value: '0' + - key: hicpp-function-size.BranchThreshold + value: '4294967295' + - key: hicpp-function-size.LineThreshold + value: '4294967295' + - key: hicpp-function-size.NestingThreshold + value: '4294967295' + - key: hicpp-function-size.ParameterThreshold + value: '4294967295' + - key: hicpp-function-size.StatementThreshold + value: '800' + - key: hicpp-function-size.VariableThreshold + value: '4294967295' + - key: hicpp-member-init.IgnoreArrays + value: 'false' + - key: hicpp-member-init.UseAssignment + value: 'false' + - key: hicpp-move-const-arg.CheckTriviallyCopyableMove + value: 'true' + - key: hicpp-multiway-paths-covered.WarnOnMissingElse + value: 'false' + - key: hicpp-no-malloc.Allocations + value: '::malloc;::calloc' + - key: hicpp-no-malloc.Deallocations + value: '::free' + - key: hicpp-no-malloc.Reallocations + value: '::realloc' + - key: hicpp-signed-bitwise.IgnorePositiveIntegerLiterals + value: 'false' + - key: hicpp-special-member-functions.AllowMissingMoveFunctions + value: 'false' + - key: hicpp-special-member-functions.AllowMissingMoveFunctionsWhenCopyIsDeleted + value: 'false' + - key: hicpp-special-member-functions.AllowSoleDefaultDtor + value: 'false' + - key: hicpp-uppercase-literal-suffix.IgnoreMacros + value: 'true' + - key: hicpp-uppercase-literal-suffix.NewSuffixes + value: '' + - key: hicpp-use-auto.MinTypeNameLength + value: '5' + - key: hicpp-use-auto.RemoveStars + value: 'false' + - key: hicpp-use-emplace.ContainersWithPushBack + value: '::std::vector;::std::list;::std::deque' + - key: hicpp-use-emplace.IgnoreImplicitConstructors + value: 'false' + - key: hicpp-use-emplace.SmartPointers + value: '::std::shared_ptr;::std::unique_ptr;::std::auto_ptr;::std::weak_ptr' + - key: hicpp-use-emplace.TupleMakeFunctions + value: '::std::make_pair;::std::make_tuple' + - key: hicpp-use-emplace.TupleTypes + value: '::std::pair;::std::tuple' + - key: hicpp-use-equals-default.IgnoreMacros + value: 'true' + - key: hicpp-use-equals-delete.IgnoreMacros + value: 'true' + - key: hicpp-use-noexcept.ReplacementString + value: '' + - key: hicpp-use-noexcept.UseNoexceptFalse + value: 'true' + - key: hicpp-use-nullptr.NullMacros + value: '' + - key: hicpp-use-override.AllowOverrideAndFinal + value: 'false' + - key: hicpp-use-override.FinalSpelling + value: final + - key: hicpp-use-override.IgnoreDestructors + value: 'false' + - key: hicpp-use-override.OverrideSpelling + value: override + - key: llvm-else-after-return.WarnOnConditionVariables + value: 'false' + - key: llvm-else-after-return.WarnOnUnfixable + value: 'false' + - key: llvm-header-guard.HeaderFileExtensions + value: ';h;hh;hpp;hxx' + - key: llvm-namespace-comment.ShortNamespaceLines + value: '1' + - key: llvm-namespace-comment.SpacesBeforeComments + value: '1' + - key: llvm-qualified-auto.AddConstToQualified + value: 'false' + - key: misc-definitions-in-headers.HeaderFileExtensions + value: ';h;hh;hpp;hxx' + - key: misc-definitions-in-headers.UseHeaderFileExtension + value: 'true' + - key: misc-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic + value: 'false' + - key: misc-non-private-member-variables-in-classes.IgnorePublicMemberVariables + value: 'false' + - key: misc-throw-by-value-catch-by-reference.CheckThrowTemporaries + value: 'true' + - key: misc-throw-by-value-catch-by-reference.MaxSize + value: '-1' + - key: misc-throw-by-value-catch-by-reference.WarnOnLargeObjects + value: 'false' + - key: misc-unused-parameters.StrictMode + value: 'false' + - key: modernize-avoid-bind.PermissiveParameterList + value: 'false' + - key: modernize-loop-convert.MaxCopySize + value: '16' + - key: modernize-loop-convert.MinConfidence + value: reasonable + - key: modernize-loop-convert.NamingStyle + value: CamelCase + - key: modernize-make-shared.IgnoreMacros + value: 'true' + - key: modernize-make-shared.IncludeStyle + value: llvm + - key: modernize-make-shared.MakeSmartPtrFunction + value: 'std::make_shared' + - key: modernize-make-shared.MakeSmartPtrFunctionHeader + value: memory + - key: modernize-make-unique.IgnoreMacros + value: 'true' + - key: modernize-make-unique.IncludeStyle + value: llvm + - key: modernize-make-unique.MakeSmartPtrFunction + value: 'std::make_unique' + - key: modernize-make-unique.MakeSmartPtrFunctionHeader + value: memory + - key: modernize-pass-by-value.IncludeStyle + value: llvm + - key: modernize-pass-by-value.ValuesOnly + value: 'false' + - key: modernize-raw-string-literal.DelimiterStem + value: lit + - key: modernize-raw-string-literal.ReplaceShorterLiterals + value: 'false' + - key: modernize-replace-auto-ptr.IncludeStyle + value: llvm + - key: modernize-replace-disallow-copy-and-assign-macro.MacroName + value: DISALLOW_COPY_AND_ASSIGN + - key: modernize-replace-random-shuffle.IncludeStyle + value: llvm + - key: modernize-use-auto.MinTypeNameLength + value: '5' + - key: modernize-use-auto.RemoveStars + value: 'false' + - key: modernize-use-bool-literals.IgnoreMacros + value: 'true' + - key: modernize-use-default-member-init.IgnoreMacros + value: 'true' + - key: modernize-use-default-member-init.UseAssignment + value: 'false' + - key: modernize-use-emplace.ContainersWithPushBack + value: '::std::vector;::std::list;::std::deque' + - key: modernize-use-emplace.IgnoreImplicitConstructors + value: 'false' + - key: modernize-use-emplace.SmartPointers + value: '::std::shared_ptr;::std::unique_ptr;::std::auto_ptr;::std::weak_ptr' + - key: modernize-use-emplace.TupleMakeFunctions + value: '::std::make_pair;::std::make_tuple' + - key: modernize-use-emplace.TupleTypes + value: '::std::pair;::std::tuple' + - key: modernize-use-equals-default.IgnoreMacros + value: 'true' + - key: modernize-use-equals-delete.IgnoreMacros + value: 'true' + - key: modernize-use-nodiscard.ReplacementString + value: '[[nodiscard]]' + - key: modernize-use-noexcept.ReplacementString + value: '' + - key: modernize-use-noexcept.UseNoexceptFalse + value: 'true' + - key: modernize-use-nullptr.NullMacros + value: 'NULL' + - key: modernize-use-override.AllowOverrideAndFinal + value: 'false' + - key: modernize-use-override.FinalSpelling + value: final + - key: modernize-use-override.IgnoreDestructors + value: 'false' + - key: modernize-use-override.OverrideSpelling + value: override + - key: modernize-use-transparent-functors.SafeMode + value: 'false' + - key: modernize-use-using.IgnoreMacros + value: 'true' + - key: objc-forbidden-subclassing.ForbiddenSuperClassNames + value: 'ABNewPersonViewController;ABPeoplePickerNavigationController;ABPersonViewController;ABUnknownPersonViewController;NSHashTable;NSMapTable;NSPointerArray;NSPointerFunctions;NSTimer;UIActionSheet;UIAlertView;UIImagePickerController;UITextInputMode;UIWebView' + - key: openmp-exception-escape.IgnoredExceptions + value: '' + - key: performance-faster-string-find.StringLikeClasses + value: '::std::basic_string;::std::basic_string_view' + - key: performance-for-range-copy.AllowedTypes + value: '' + - key: performance-for-range-copy.WarnOnAllAutoCopies + value: 'false' + - key: performance-inefficient-string-concatenation.StrictMode + value: 'false' + - key: performance-inefficient-vector-operation.EnableProto + value: 'false' + - key: performance-inefficient-vector-operation.VectorLikeClasses + value: '::std::vector' + - key: performance-move-const-arg.CheckTriviallyCopyableMove + value: 'true' + - key: performance-move-constructor-init.IncludeStyle + value: llvm + - key: performance-no-automatic-move.AllowedTypes + value: '' + - key: performance-type-promotion-in-math-fn.IncludeStyle + value: llvm + - key: performance-unnecessary-copy-initialization.AllowedTypes + value: '' + - key: performance-unnecessary-value-param.AllowedTypes + value: '' + - key: performance-unnecessary-value-param.IncludeStyle + value: llvm + - key: portability-restrict-system-includes.Includes + value: '*' + - key: portability-simd-intrinsics.Std + value: '' + - key: portability-simd-intrinsics.Suggest + value: '0' + - key: readability-braces-around-statements.ShortStatementLines + value: '0' + - key: readability-else-after-return.WarnOnConditionVariables + value: 'true' + - key: readability-else-after-return.WarnOnUnfixable + value: 'true' + - key: readability-function-size.BranchThreshold + value: '4294967295' + - key: readability-function-size.LineThreshold + value: '4294967295' + - key: readability-function-size.NestingThreshold + value: '4294967295' + - key: readability-function-size.ParameterThreshold + value: '4294967295' + - key: readability-function-size.StatementThreshold + value: '800' + - key: readability-function-size.VariableThreshold + value: '4294967295' + - key: readability-implicit-bool-conversion.AllowIntegerConditions + value: 'false' + - key: readability-implicit-bool-conversion.AllowPointerConditions + value: 'false' + - key: readability-inconsistent-declaration-parameter-name.IgnoreMacros + value: 'true' + - key: readability-inconsistent-declaration-parameter-name.Strict + value: 'false' + - key: readability-magic-numbers.IgnoreAllFloatingPointValues + value: 'false' + - key: readability-magic-numbers.IgnoreBitFieldsWidths + value: 'true' + - key: readability-magic-numbers.IgnorePowersOf2IntegerValues + value: 'false' + - key: readability-magic-numbers.IgnoredFloatingPointValues + value: '1.0;100.0;' + - key: readability-magic-numbers.IgnoredIntegerValues + value: '1;2;3;4;' + - key: readability-qualified-auto.AddConstToQualified + value: 'true' + - key: readability-redundant-declaration.IgnoreMacros + value: 'true' + - key: readability-redundant-member-init.IgnoreBaseInCopyConstructors + value: 'false' + - key: readability-redundant-smartptr-get.IgnoreMacros + value: 'true' + - key: readability-redundant-string-init.StringNames + value: '::std::basic_string' + - key: readability-simplify-boolean-expr.ChainedConditionalAssignment + value: 'false' + - key: readability-simplify-boolean-expr.ChainedConditionalReturn + value: 'false' + - key: readability-simplify-subscript-expr.Types + value: '::std::basic_string;::std::basic_string_view;::std::vector;::std::array' + - key: readability-static-accessed-through-instance.NameSpecifierNestingThreshold + value: '3' + - key: readability-uppercase-literal-suffix.IgnoreMacros + value: 'true' + - key: readability-uppercase-literal-suffix.NewSuffixes + value: '' + - key: zircon-temporary-objects.Names + value: '' +# allow x,y,z single letter names, to be used for coordinates + - key: readability-identifier-length.IgnoredVariableNames + value: '^[xyz]|m0|m1|_$' +... diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8d5694f --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +include/cpp_core/version.h +build/ +.cache/ + diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..6fabd8e --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,64 @@ +cmake_minimum_required(VERSION 3.14) + +project(cpp-core + VERSION 0.1.0 + DESCRIPTION "Cross-platform helper library shared by cpp-linux-bindings and cpp-windows-bindings" + LANGUAGES CXX) + +# --------------------------------------------------------------------------- +# Version information - can be overridden by parent project +# --------------------------------------------------------------------------- +foreach(_part IN ITEMS MAJOR MINOR PATCH) + if(NOT DEFINED CPP_CORE_VERSION_${_part} OR CPP_CORE_VERSION_${_part} STREQUAL "") + set(CPP_CORE_VERSION_${_part} ${PROJECT_VERSION_${_part}}) + endif() +endforeach() + +configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/include/cpp_core/version.h.in + ${CMAKE_CURRENT_SOURCE_DIR}/include/cpp_core/version.h + @ONLY) + +# Header-only library -------------------------------------------------------- +add_library(cpp_core INTERFACE) +add_library(cpp_core::cpp_core ALIAS cpp_core) + +# Public include directories +target_include_directories(cpp_core INTERFACE + $ + $) + +# Require C++23 +target_compile_features(cpp_core INTERFACE cxx_std_23) + +# Install rules -------------------------------------------------------------- +include(GNUInstallDirs) + +install(TARGETS cpp_core + EXPORT cpp_coreTargets) + +install(DIRECTORY include/ + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) + +# CMake package configuration ------------------------------------------------ +include(CMakePackageConfigHelpers) + +write_basic_package_version_file( + ${CMAKE_CURRENT_BINARY_DIR}/cpp_coreConfigVersion.cmake + VERSION ${PROJECT_VERSION} + COMPATIBILITY SameMajorVersion) + +configure_package_config_file( + ${CMAKE_CURRENT_LIST_DIR}/cmake/cpp_core_config.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/cpp_coreConfig.cmake + INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/cpp_core) + +install(EXPORT cpp_coreTargets + FILE cpp_coreTargets.cmake + NAMESPACE cpp_core:: + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/cpp_core) + +install(FILES + ${CMAKE_CURRENT_BINARY_DIR}/cpp_coreConfig.cmake + ${CMAKE_CURRENT_BINARY_DIR}/cpp_coreConfigVersion.cmake + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/cpp_core) diff --git a/README.md b/README.md index ccae452..eb13a08 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,90 @@ -# CPP-Bindings +# C++ Core -C++ bindings for low level communication with the OS. These bindings provide functions to `open`, `close`, `read`, `write`, etc. to or from a serial connection. The functions than can be used through a [dynamic link library](https://de.wikipedia.org/wiki/Dynamic_Link_Library) or [shared object](https://en.wikipedia.org/wiki/Library_(computing)#Shared_libraries). +Header-only C++ helper library that provides small, cross-platform utilities and a centrally maintained **Version** struct shared by the *cpp-bindings-linux*, *cpp-bindings-windows* and *cpp-bindings-macos* repositories. + +> ⚠️ **Note for FFI users**: This repository contains **headers only**. +> To obtain a working native library (SO / DLL / dylib) build one of the platform-specific projects instead: +> • Windows → [cpp-bindings-windows](https://github.com/Serial-IO/cpp-bindings-windows) +> • Linux → [cpp-bindings-linux](https://github.com/Serial-IO/cpp-bindings-linux) +> These repositories compile *cpp-core* for you and provide the ready-to-use shared library. ## Documentation -Check out the [Wiki](https://github.com/Serial-Link/CPP-Bindings/wiki) section on how to use these bindings. -## Credits -- Big thanks goes out to [@Katze719](https://github.com/Katze719) who wrote most of the C++ files and functions! -- Thanks to [@AapoAlas](https://github.com/aapoalas) for the great support and help on the [Deno Discord](https://discord.gg/deno)! -- Thanks to [@Dj](https://github.com/DjDeveloperr) for the inspiration on how to write such a library! +* 📄 **[Overview](docs/overview.md)** – architecture, build & quick start. + +* C++23, zero runtime dependencies +* Delivered as an INTERFACE target `cpp_core::cpp_core` +* Fetchable via [CPM.cmake](https://github.com/cpm-cmake/CPM.cmake) or regular `find_package` + +--- + +## Requirements + +* CMake ≥ 3.14 +* A C++23 compatible compiler (GCC 13+, Clang 16+, MSVC 2022+) + +--- + +## Quick Start + +### 1. Add *cpp-core* with CPM.cmake (recommended way) + +```cmake +# Set the project version once via **cache variables** – +# ensures the values end up in cpp-core regardless of when CPM configures. +set(CPP_CORE_VERSION_MAJOR 1 CACHE STRING "") +set(CPP_CORE_VERSION_MINOR 0 CACHE STRING "") +set(CPP_CORE_VERSION_PATCH 3 CACHE STRING "") + +CPMAddPackage( + NAME cpp_core + GITHUB_REPOSITORY Serial-IO/cpp-core # Fork / Upstream + GIT_TAG main # or e.g. v0.1.0 +) + +add_executable(my_app src/main.cpp) +target_link_libraries(my_app PRIVATE cpp_core::cpp_core) +``` + +> Why cache variables? +> They guarantee the values exist **before** the `CPMAddPackage()` call. If the variables are set later (or via +> `OPTIONS ... "CPP_CORE_VERSION_MAJOR=${FOO}"`) and `FOO` is empty at that moment, *cpp-core* falls back to its default version (0.1.0). + +### 2. Use in code + +```cpp +#include +#include + +int main() { + constexpr auto v = cpp_core::VERSION; // {1,4,0} +} +``` + +--- + +## Alternative: add_subdirectory + +If you include the source code directly as a sub-repository, simply do: + +```cmake +add_subdirectory(externals/cpp-core) +# the same version variables can be set before the call +``` + +--- + +## Using the package with `find_package` + +After running `cmake --install` (or `make install`) you can locate the package system-wide: -## Licence -Apache-2.0. Check [LICENSE](https://github.com/Serial-Link/CPP-Bindings/blob/main/LICENSE) for more details. +```cmake +find_package(cpp_core REQUIRED) +add_executable(my_app src/main.cpp) +target_link_libraries(my_app PRIVATE cpp_core::cpp_core) +``` -Feel free to contribute to this project. +--- -Copyright 2024 © Paul & Max +## License +Apache-2.0 – see [LICENSE](LICENSE). diff --git a/cmake/cpp_core_config.cmake.in b/cmake/cpp_core_config.cmake.in new file mode 100644 index 0000000..65434e4 --- /dev/null +++ b/cmake/cpp_core_config.cmake.in @@ -0,0 +1,5 @@ +@PACKAGE_INIT@ + +include("${CMAKE_CURRENT_LIST_DIR}/cpp_coreTargets.cmake") + +check_required_components(cpp_core) diff --git a/docs/overview.md b/docs/overview.md new file mode 100644 index 0000000..d69985c --- /dev/null +++ b/docs/overview.md @@ -0,0 +1,117 @@ +# cpp-core – Library Overview + +Welcome to **cpp-core**, a header-only, cross-platform C++23 helper library that bundles utilities frequently needed in systems programming and embedded scenarios. Besides multiple compile-time helpers it exposes a fully-featured **C API for serial communication**, making the library consumable from virtually any language (Rust, Python, Deno, …). + +> ⚠️ **Looking for a ready-to-use shared library?** Build one of the platform bindings instead of cpp-core itself: +> • Windows → [cpp-bindings-windows](https://github.com/Serial-IO/cpp-bindings-windows) +> • Linux → [cpp-bindings-linux](https://github.com/Serial-IO/cpp-bindings-linux) + +> Looking for the raw function list? See the [C API reference](api_reference.md). +> +> Want to call the library from TypeScript? Jump straight to the [Deno FFI guide](deno_ffi.md). + +--- + +## What ships with cpp-core? + +| Area | Header | Highlights | +|------|--------|------------| +| Versioning | `cpp_core/version.h` | Compile-time `constexpr` version struct, filled during the build. +| Helpers | `cpp_core/helpers.h` | Collection of lightweight, header-only helper templates. +| Serial I/O | `cpp_core/serial.h` | Cross-platform serial helper built on the POSIX/Win32 APIs (see [C API reference](api_reference.md)). +| Error Codes| `cpp_core/status_codes.h` | Unified negative error codes shared across languages and bindings. + +All headers live in the `include/` tree and are directly usable after installation. + +--- + +## Directory structure + +``` +cpp-core/ +├── cmake/ # CMake helper modules +├── docs/ # You are here 📚 +├── include/ +│ └── cpp_core/ # Public headers (header-only!) +└── test/ # Unit tests (if enabled) +``` + +--- + +## Building the library + +### 1. Fetch & configure + +```bash +# clone +$ git clone https://github.com/Serial-IO/cpp-core.git +$ cd cpp-core + +# create an out-of-tree build directory +$ cmake -B build -DCMAKE_BUILD_TYPE=Release +``` + +### 2. Build & install (header-only) + +```bash +$ cmake --build build --target install +``` + +`install` copies the headers (and *optionally* a shared library, see below) to your default prefix (`/usr/local`, `Program Files/`, …). + +### 3. Building a shared library for FFI consumers + +Deno, Python and other FFI users expect a shared library (`*.so`, `*.dll`, `*.dylib`). Enable it like so: + +```bash +# add the switch – all code remains header-only for C++ callers +$ cmake -B build-shared -DBUILD_SHARED_LIBS=ON -DCMAKE_BUILD_TYPE=Release +$ cmake --build build-shared --config Release + +# resulting artifact (Linux) +$ ls build-shared +libcpp_core.so # rename or copy as needed, e.g. to libserial.so +``` + +> **Tip**: keep the header files close to your FFI project so you can re-generate bindings easily. + +--- + +## Minimal C example + +```c +#include +#include + +int main() { + intptr_t h = serialOpen("/dev/ttyUSB0", 115200, 8, 0, 0); + if (h <= 0) { + fprintf(stderr, "open failed: %ld\n", (long)h); + return 1; + } + + const char msg[] = "hello\n"; + serialWriteLine(h, msg, sizeof msg - 1, 1000); + + char buf[64]; + int n = serialReadLine(h, buf, sizeof buf, 1000); + fwrite(buf, 1, n, stdout); + + serialClose(h); +} +``` + +For a deep dive into every parameter head over to the [C API reference](api_reference.md). + +--- + +## Going further + +* **Deno, Node, Python & Rust**: see the dedicated [Deno FFI guide](deno_ffi.md) which includes a complete TypeScript example and hints for other languages. +* **Questions / issues** – open a ticket on GitHub; contributions are welcome! + +--- + +## License + +cpp-core is licensed under the terms of the Apache-2.0 license. See [LICENSE](../LICENSE) for details. diff --git a/include/cpp_core.h b/include/cpp_core.h new file mode 100644 index 0000000..1f50732 --- /dev/null +++ b/include/cpp_core.h @@ -0,0 +1,18 @@ +#pragma once + +/* + * cpp_core.h — Umbrella header for the cpp_core library + * + * Include this single file to gain access to the complete public C/C++ API + * of the cpp_core runtime. Internally it forwards to the individual header + * units located in the cpp_core/ sub-directory so fine-grained includes continue + * to work as before. Prefer including the specific headers you actually need + * in translation units with strict compile-time requirements; however for + * quick prototyping and high-level application code, this umbrella header + * offers the most convenient entry point. + */ + +#include "cpp_core/error_callback.h" +#include "cpp_core/serial.h" +#include "cpp_core/status_codes.h" +#include "cpp_core/version.h" diff --git a/include/cpp_core/error_callback.h b/include/cpp_core/error_callback.h new file mode 100644 index 0000000..3217320 --- /dev/null +++ b/include/cpp_core/error_callback.h @@ -0,0 +1,15 @@ +#pragma once + +#ifdef __cplusplus +extern "C" +{ +#endif + + using ErrorCallbackT = void (*)( + int error_code, + const char *message + ); + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/include/cpp_core/interface/get_version.h b/include/cpp_core/interface/get_version.h new file mode 100644 index 0000000..1092b1b --- /dev/null +++ b/include/cpp_core/interface/get_version.h @@ -0,0 +1,29 @@ +#pragma once +#include "../module_api.h" +#include "../version.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + /** + * @brief Copy the compile-time version of the cpp_core library. + * + * Writes the version baked into the library at build-time to the structure + * pointed to by @p out. If @p out is `nullptr` the call is a no-op. + * + * @param[out] out Pointer to a `cpp_core::Version` structure that receives the version information. May be + * `nullptr`. + */ + inline MODULE_API void getVersion(cpp_core::Version *out) + { + if (out != nullptr) + { + *out = cpp_core::kVersion; + } + } + +#ifdef __cplusplus +} +#endif diff --git a/include/cpp_core/interface/serial_abort_read.h b/include/cpp_core/interface/serial_abort_read.h new file mode 100644 index 0000000..7925546 --- /dev/null +++ b/include/cpp_core/interface/serial_abort_read.h @@ -0,0 +1,28 @@ +#pragma once +#include "../error_callback.h" +#include "../module_api.h" +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + + /** + * @brief Abort a blocking read operation running in a different thread. + * + * The target read function returns immediately with + * ::cpp_core::StatusCodes::kAbortReadError. + * + * @param handle Port handle. + * @param error_callback [optional] Callback to invoke on error. Defined in error_callback.h. Default is `nullptr`. + * @return 0 on success or a negative error code from ::cpp_core::StatusCodes on error. + */ + MODULE_API auto serialAbortRead( + int64_t handle, + ErrorCallbackT error_callback = nullptr + ) -> int; + +#ifdef __cplusplus +} +#endif diff --git a/include/cpp_core/interface/serial_abort_write.h b/include/cpp_core/interface/serial_abort_write.h new file mode 100644 index 0000000..f5c3d0c --- /dev/null +++ b/include/cpp_core/interface/serial_abort_write.h @@ -0,0 +1,28 @@ +#pragma once +#include "../error_callback.h" +#include "../module_api.h" +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + + /** + * @brief Abort a blocking write operation running in a different thread. + * + * The target write function returns immediately with + * ::cpp_core::StatusCodes::kAbortWriteError. + * + * @param handle Port handle. + * @param error_callback [optional] Callback to invoke on error. Defined in error_callback.h. Default is `nullptr`. + * @return 0 on success or a negative error code from ::cpp_core::StatusCodes on error. + */ + MODULE_API auto serialAbortWrite( + int64_t handle, + ErrorCallbackT error_callback = nullptr + ) -> int; + +#ifdef __cplusplus +} +#endif diff --git a/include/cpp_core/interface/serial_clear_buffer_in.h b/include/cpp_core/interface/serial_clear_buffer_in.h new file mode 100644 index 0000000..8723016 --- /dev/null +++ b/include/cpp_core/interface/serial_clear_buffer_in.h @@ -0,0 +1,28 @@ +#pragma once +#include "../error_callback.h" +#include "../module_api.h" +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + + /** + * @brief Clear (flush) the device's input buffer. + * + * Discards every byte the driver has already received but the application + * has not yet read. + * + * @param handle Port handle. + * @param error_callback [optional] Callback to invoke on error. Defined in error_callback.h. Default is `nullptr`. + * @return 0 on success or a negative error code from ::cpp_core::StatusCodes on error. + */ + MODULE_API auto serialClearBufferIn( + int64_t handle, + ErrorCallbackT error_callback = nullptr + ) -> int; + +#ifdef __cplusplus +} +#endif diff --git a/include/cpp_core/interface/serial_clear_buffer_out.h b/include/cpp_core/interface/serial_clear_buffer_out.h new file mode 100644 index 0000000..3a8fcc5 --- /dev/null +++ b/include/cpp_core/interface/serial_clear_buffer_out.h @@ -0,0 +1,28 @@ +#pragma once +#include "../error_callback.h" +#include "../module_api.h" +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + + /** + * @brief Clear (flush) the device's output buffer. + * + * Blocks until all queued bytes have been transmitted and then discards any + * remaining data. + * + * @param handle Port handle. + * @param error_callback [optional] Callback to invoke on error. Defined in error_callback.h. Default is `nullptr`. + * @return 0 on success or a negative error code from ::cpp_core::StatusCodes on error. + */ + MODULE_API auto serialClearBufferOut( + int64_t handle, + ErrorCallbackT error_callback = nullptr + ) -> int; + +#ifdef __cplusplus +} +#endif diff --git a/include/cpp_core/interface/serial_close.h b/include/cpp_core/interface/serial_close.h new file mode 100644 index 0000000..55b4e94 --- /dev/null +++ b/include/cpp_core/interface/serial_close.h @@ -0,0 +1,28 @@ +#pragma once +#include "../error_callback.h" +#include "../module_api.h" +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + + /** + * @brief Close a previously opened serial port. + * + * The handle becomes invalid after the call. Passing an already invalid + * (≤ 0) handle is a no-op. + * + * @param handle Handle obtained from serialOpen(). + * @param error_callback [optional] Callback to invoke on error. Defined in error_callback.h. Default is `nullptr`. + * @return 0 on success or a negative error code from ::cpp_core::StatusCodes on error. + */ + MODULE_API auto serialClose( + int64_t handle, + ErrorCallbackT error_callback = nullptr + ) -> int; + +#ifdef __cplusplus +} +#endif diff --git a/include/cpp_core/interface/serial_drain.h b/include/cpp_core/interface/serial_drain.h new file mode 100644 index 0000000..7e1f2bc --- /dev/null +++ b/include/cpp_core/interface/serial_drain.h @@ -0,0 +1,41 @@ +#pragma once +#include "../error_callback.h" +#include "../module_api.h" +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + + /** + * @brief Wait until the operating-system driver has physically sent every queued byte. + * + * The function blocks the *calling thread* until the device driver reports + * that the transmit FIFO is **empty** – i.e. all bytes handed to previous + * `serialWrite*` calls have been shifted out on the wire. It does *not* + * flush higher-level protocol buffers you may have implemented yourself. + * + * Typical use-case: ensure a complete command frame has left the UART + * before toggling RTS/DTR or powering down the device. + * + * @code{.c} + * // Send a frame and make sure it actually hits the line + * serialWrite(h, frame, frame_len, 50, 1); + * if (serialDrain(h) < 0) { + * fprintf(stderr, "drain failed\n"); + * } + * @endcode + * + * @param handle Port handle. + * @param error_callback [optional] Callback to invoke on error. Defined in error_callback.h. Default is `nullptr`. + * @return 0 on success or a negative error code from ::cpp_core::StatusCodes on error. + */ + MODULE_API auto serialDrain( + int64_t handle, + ErrorCallbackT error_callback = nullptr + ) -> int; + +#ifdef __cplusplus +} +#endif diff --git a/include/cpp_core/interface/serial_get_ports_info.h b/include/cpp_core/interface/serial_get_ports_info.h new file mode 100644 index 0000000..665f981 --- /dev/null +++ b/include/cpp_core/interface/serial_get_ports_info.h @@ -0,0 +1,36 @@ +#pragma once +#include "../error_callback.h" +#include "../module_api.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + /** + * @brief Enumerate all available serial ports on the system. + * + * The supplied callback is invoked once for every discovered port. All string + * parameters may be `nullptr` if the information is unknown. + * + * @param callback_fn Callback receiving port information. + * @param error_callback [optional] Callback to invoke on error. Defined in error_callback.h. Default is `nullptr`. + * @return Number of ports found or a negative error code from ::cpp_core::StatusCodes on error. + */ + MODULE_API auto serialGetPortsInfo( + void (*callback_fn)( + const char *port, + const char *path, + const char *manufacturer, + const char *serial_number, + const char *pnp_id, + const char *location_id, + const char *product_id, + const char *vendor_id + ), + ErrorCallbackT error_callback = nullptr + ) -> int; + +#ifdef __cplusplus +} +#endif diff --git a/include/cpp_core/interface/serial_in_bytes_total.h b/include/cpp_core/interface/serial_in_bytes_total.h new file mode 100644 index 0000000..330a530 --- /dev/null +++ b/include/cpp_core/interface/serial_in_bytes_total.h @@ -0,0 +1,25 @@ +#pragma once +#include "../error_callback.h" +#include "../module_api.h" +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + + /** + * @brief Total number of bytes received since the port was opened. + * + * @param handle Port handle. + * @param error_callback [optional] Callback to invoke on error. Defined in error_callback.h. Default is `nullptr`. + * @return Total number of bytes read or a negative error code from ::cpp_core::StatusCodes on error. + */ + MODULE_API auto serialInBytesTotal( + int64_t handle, + ErrorCallbackT error_callback = nullptr + ) -> int64_t; + +#ifdef __cplusplus +} +#endif diff --git a/include/cpp_core/interface/serial_in_bytes_waiting.h b/include/cpp_core/interface/serial_in_bytes_waiting.h new file mode 100644 index 0000000..cf3adae --- /dev/null +++ b/include/cpp_core/interface/serial_in_bytes_waiting.h @@ -0,0 +1,36 @@ +#pragma once +#include "../error_callback.h" +#include "../module_api.h" +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + + /** + * @brief Query how many bytes can be read *immediately* without blocking. + * + * The number reflects the size of the driver's RX FIFO **after** accounting + * for data already consumed by the application. A value of `0` therefore + * means a read call would have to wait for the next byte to arrive. + * + * @code{.c} + * int pending = serialInBytesWaiting(h); + * if (pending > 0) { + * serialRead(h, buf, pending, 0, 1); // non-blocking read + * } + * @endcode + * + * @param handle Port handle. + * @param error_callback [optional] Callback to invoke on error. Defined in error_callback.h. Default is `nullptr`. + * @return Bytes available for instant reading or a negative error code from ::cpp_core::StatusCodes on error. + */ + MODULE_API auto serialInBytesWaiting( + int64_t handle, + ErrorCallbackT error_callback = nullptr + ) -> int; + +#ifdef __cplusplus +} +#endif diff --git a/include/cpp_core/interface/serial_open.h b/include/cpp_core/interface/serial_open.h new file mode 100644 index 0000000..0388f2a --- /dev/null +++ b/include/cpp_core/interface/serial_open.h @@ -0,0 +1,39 @@ +#pragma once +#include "../error_callback.h" +#include "../module_api.h" +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + + /** + * @brief Open and configure a serial port. + * + * The function attempts to open the device referenced by @p port and applies + * the given line settings. The pointer is interpreted as + * - `const char*` on POSIX and + * - `const wchar_t*` on Windows. + * + * @param port Null-terminated device identifier (e.g. "COM3", "/dev/ttyUSB0"). Passing `nullptr` results in + * a failure. + * @param baudrate Desired baud rate in bit/s (≥ 300). + * @param data_bits Number of data bits (5–8). + * @param parity 0 = none, 1 = even, 2 = odd. + * @param stop_bits 0 = 1 stop bit, 2 = 2 stop bits. + * @param error_callback [optional] Callback to invoke on error. Defined in error_callback.h. Default is `nullptr`. + * @return A positive opaque handle on success or a negative value from ::cpp_core::StatusCodes on failure. + */ + MODULE_API auto serialOpen( + void *port, + int baudrate, + int data_bits, + int parity = 0, + int stop_bits = 0, + ErrorCallbackT error_callback = nullptr + ) -> intptr_t; + +#ifdef __cplusplus +} +#endif diff --git a/include/cpp_core/interface/serial_out_bytes_total.h b/include/cpp_core/interface/serial_out_bytes_total.h new file mode 100644 index 0000000..a29336e --- /dev/null +++ b/include/cpp_core/interface/serial_out_bytes_total.h @@ -0,0 +1,25 @@ +#pragma once +#include "../error_callback.h" +#include "../module_api.h" +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + + /** + * @brief Total number of bytes transmitted since the port was opened. + * + * @param handle Port handle. + * @param error_callback [optional] Callback to invoke on error. Defined in error_callback.h. Default is `nullptr`. + * @return Total number of bytes written or a negative error code from ::cpp_core::StatusCodes on error. + */ + MODULE_API auto serialOutBytesTotal( + int64_t handle, + ErrorCallbackT error_callback = nullptr + ) -> int64_t; + +#ifdef __cplusplus +} +#endif diff --git a/include/cpp_core/interface/serial_out_bytes_waiting.h b/include/cpp_core/interface/serial_out_bytes_waiting.h new file mode 100644 index 0000000..14fc6ee --- /dev/null +++ b/include/cpp_core/interface/serial_out_bytes_waiting.h @@ -0,0 +1,34 @@ +#pragma once +#include "../error_callback.h" +#include "../module_api.h" +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + + /** + * @brief Return the number of bytes that have been accepted by the driver but not yet sent. + * + * Useful for gauging transmission progress in the background or for pacing + * further writes to avoid unbounded buffering. + * + * @code{.c} + * while (serialOutBytesWaiting(h) > 0) { + * usleep(1000); // wait 1 ms and poll again + * } + * @endcode + * + * @param handle Port handle. + * @param error_callback [optional] Callback to invoke on error. Defined in error_callback.h. Default is `nullptr`. + * @return Bytes still waiting in the TX FIFO or a negative error code from ::cpp_core::StatusCodes on error. + */ + MODULE_API auto serialOutBytesWaiting( + int64_t handle, + ErrorCallbackT error_callback = nullptr + ) -> int; + +#ifdef __cplusplus +} +#endif diff --git a/include/cpp_core/interface/serial_read.h b/include/cpp_core/interface/serial_read.h new file mode 100644 index 0000000..1d1a1fb --- /dev/null +++ b/include/cpp_core/interface/serial_read.h @@ -0,0 +1,39 @@ +#pragma once +#include "../error_callback.h" +#include "../module_api.h" +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + + /** + * @brief Read raw bytes from the serial port. + * + * The call blocks for at most @p timeout_ms milliseconds while waiting for + * the FIRST byte. For every subsequent byte the individual timeout is + * calculated as `timeout_ms * multiplier`. + * + * @param handle Port handle. + * @param buffer Destination buffer (must not be `nullptr`). + * @param buffer_size Size of @p buffer in bytes (> 0). + * @param timeout_ms Base timeout per byte in milliseconds (applied to the first byte as-is; subsequent bytes use + * `timeout_ms * multiplier`). + * @param multiplier Factor applied to @p timeout_ms for every byte after the first. 0 -> return immediately after + * the first byte. + * @param error_callback [optional] Callback to invoke on error. Defined in error_callback.h. Default is `nullptr`. + * @return Bytes read (0 on timeout) or a negative error code from ::cpp_core::StatusCodes on error. + */ + MODULE_API auto serialRead( + int64_t handle, + void *buffer, + int buffer_size, + int timeout_ms, + int multiplier, + ErrorCallbackT error_callback = nullptr + ) -> int; + +#ifdef __cplusplus +} +#endif diff --git a/include/cpp_core/interface/serial_read_line.h b/include/cpp_core/interface/serial_read_line.h new file mode 100644 index 0000000..62db720 --- /dev/null +++ b/include/cpp_core/interface/serial_read_line.h @@ -0,0 +1,37 @@ +#pragma once +#include "../error_callback.h" +#include "../module_api.h" +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + + /** + * @brief Read a single line terminated by '\n'. + * + * Timeout handling is identical to serialRead(); the newline character is + * included in the returned data. + * + * @param handle Port handle. + * @param buffer Destination buffer. + * @param buffer_size Capacity of @p buffer in bytes. + * @param timeout_ms Base timeout per byte in milliseconds (applied to the first byte as-is; subsequent bytes use + * `timeout_ms * multiplier`). + * @param multiplier Factor applied to the timeout for subsequent bytes. + * @param error_callback [optional] Callback to invoke on error. Defined in error_callback.h. Default is `nullptr`. + * @return Bytes read (0 on timeout) or a negative error code from ::cpp_core::StatusCodes on error. + */ + MODULE_API auto serialReadLine( + int64_t handle, + void *buffer, + int buffer_size, + int timeout_ms, + int multiplier, + ErrorCallbackT error_callback = nullptr + ) -> int; + +#ifdef __cplusplus +} +#endif diff --git a/include/cpp_core/interface/serial_read_until.h b/include/cpp_core/interface/serial_read_until.h new file mode 100644 index 0000000..ea276ac --- /dev/null +++ b/include/cpp_core/interface/serial_read_until.h @@ -0,0 +1,41 @@ +#pragma once +#include "../error_callback.h" +#include "../module_api.h" +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + + /** + * @brief Read bytes until a terminator character appears. + * + * Semantics are identical to serialRead() but reading stops as soon as the + * byte pointed to by @p until_char has been received. The terminator is part + * of the returned data. + * + * @param handle Port handle. + * @param buffer Destination buffer. + * @param buffer_size Capacity of @p buffer in bytes. + * @param timeout_ms Base timeout per byte in milliseconds (applied to the first byte as-is; each additional byte + * uses `timeout_ms * multiplier`). + * @param multiplier Factor applied to the timeout for every additional byte. + * @param until_char Pointer to the terminator character (must not be `nullptr`). + * @param error_callback [optional] Callback to invoke on error. Defined in error_callback.h. Default is `nullptr`. + * @return Bytes read (including the terminator), 0 on timeout or a negative error code from ::cpp_core::StatusCodes + * on error. + */ + MODULE_API auto serialReadUntil( + int64_t handle, + void *buffer, + int buffer_size, + int timeout_ms, + int multiplier, + void *until_char, + ErrorCallbackT error_callback = nullptr + ) -> int; + +#ifdef __cplusplus +} +#endif diff --git a/include/cpp_core/interface/serial_read_until_sequence.h b/include/cpp_core/interface/serial_read_until_sequence.h new file mode 100644 index 0000000..ff346c1 --- /dev/null +++ b/include/cpp_core/interface/serial_read_until_sequence.h @@ -0,0 +1,39 @@ +#pragma once +#include "../error_callback.h" +#include "../module_api.h" +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + + /** + * @brief Read until a specific byte sequence appears. + * + * Works like serialReadUntil() but supports an arbitrary terminator string. + * The terminator is included in the returned data. + * + * @param handle Port handle. + * @param buffer Destination buffer. + * @param buffer_size Capacity of @p buffer in bytes. + * @param timeout_ms Base timeout per byte in milliseconds (first byte uses this value; each additional byte uses + * `timeout_ms * multiplier`). + * @param multiplier Factor applied to the timeout for subsequent bytes. + * @param sequence Pointer to the terminating byte sequence (must not be `nullptr`). + * @param error_callback [optional] Callback to invoke on error. Defined in error_callback.h. Default is `nullptr`. + * @return Bytes read (including the terminator) or a negative error code from ::cpp_core::StatusCodes on error. + */ + MODULE_API auto serialReadUntilSequence( + int64_t handle, + void *buffer, + int buffer_size, + int timeout_ms, + int multiplier, + void *sequence, + ErrorCallbackT error_callback = nullptr + ) -> int; + +#ifdef __cplusplus +} +#endif diff --git a/include/cpp_core/interface/serial_set_error_callback.h b/include/cpp_core/interface/serial_set_error_callback.h new file mode 100644 index 0000000..46e28a2 --- /dev/null +++ b/include/cpp_core/interface/serial_set_error_callback.h @@ -0,0 +1,22 @@ +#pragma once +#include "../error_callback.h" +#include "../module_api.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + /** + * @brief Register a callback that is invoked whenever an error occurs. + * + * Pass `nullptr` to disable the callback. + * + * @param error_callback Callback to invoke on error. Defined in error_callback.h. Default is `nullptr`. Gets + * invoked on any error. + */ + MODULE_API void serialSetErrorCallback(ErrorCallbackT error_callback); + +#ifdef __cplusplus +} +#endif diff --git a/include/cpp_core/interface/serial_set_read_callback.h b/include/cpp_core/interface/serial_set_read_callback.h new file mode 100644 index 0000000..2b45ae0 --- /dev/null +++ b/include/cpp_core/interface/serial_set_read_callback.h @@ -0,0 +1,20 @@ +#pragma once +#include "../module_api.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + /** + * @brief Register a callback that is invoked whenever bytes are read. + * + * Pass `nullptr` to disable the callback. + * + * @param callback Function receiving the number of bytes that have just been read. + */ + MODULE_API void serialSetReadCallback(void (*callback_fn)(int bytes_read)); + +#ifdef __cplusplus +} +#endif diff --git a/include/cpp_core/interface/serial_set_write_callback.h b/include/cpp_core/interface/serial_set_write_callback.h new file mode 100644 index 0000000..a521e40 --- /dev/null +++ b/include/cpp_core/interface/serial_set_write_callback.h @@ -0,0 +1,20 @@ +#pragma once +#include "../module_api.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + /** + * @brief Register a callback that is invoked whenever bytes are written. + * + * Pass `nullptr` to disable the callback. + * + * @param callback Function receiving the number of bytes that have just been written. + */ + MODULE_API void serialSetWriteCallback(void (*callback_fn)(int bytes_written)); + +#ifdef __cplusplus +} +#endif diff --git a/include/cpp_core/interface/serial_write.h b/include/cpp_core/interface/serial_write.h new file mode 100644 index 0000000..3945dcb --- /dev/null +++ b/include/cpp_core/interface/serial_write.h @@ -0,0 +1,37 @@ +#pragma once +#include "../error_callback.h" +#include "../module_api.h" +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + + /** + * @brief Write raw bytes to the serial port. + * + * Timeout handling mirrors serialRead(): @p timeout_ms applies to the first + * byte, `timeout_ms * multiplier` to every subsequent one. + * + * @param handle Port handle. + * @param buffer Data to transmit (must not be `nullptr`). + * @param buffer_size Number of bytes in @p buffer (> 0). + * @param timeout_ms Base timeout per byte in milliseconds (applied to the first byte as-is; subsequent bytes use + * `timeout_ms * multiplier`). + * @param multiplier Factor applied to the timeout for subsequent bytes. + * @param error_callback [optional] Callback to invoke on error. Defined in error_callback.h. Default is `nullptr`. + * @return Bytes written (may be 0 on timeout) or a negative error code from ::cpp_core::StatusCodes on error. + */ + MODULE_API auto serialWrite( + int64_t handle, + const void *buffer, + int buffer_size, + int timeout_ms, + int multiplier, + ErrorCallbackT error_callback = nullptr + ) -> int; + +#ifdef __cplusplus +} +#endif diff --git a/include/cpp_core/module_api.h b/include/cpp_core/module_api.h new file mode 100644 index 0000000..11d7116 --- /dev/null +++ b/include/cpp_core/module_api.h @@ -0,0 +1,11 @@ +#pragma once + +#if defined(_WIN32) || defined(__CYGWIN__) +#ifdef cpp_windows_bindings_EXPORTS +#define MODULE_API __declspec(dllexport) +#else +#define MODULE_API __declspec(dllimport) +#endif +#else +#define MODULE_API __attribute__((visibility("default"))) +#endif diff --git a/include/cpp_core/serial.h b/include/cpp_core/serial.h new file mode 100644 index 0000000..e7e142a --- /dev/null +++ b/include/cpp_core/serial.h @@ -0,0 +1,27 @@ +#pragma once + +#include "module_api.h" +#include "version.h" + +// Aggregated interface headers +#include "interface/get_version.h" +#include "interface/serial_abort_read.h" +#include "interface/serial_abort_write.h" +#include "interface/serial_clear_buffer_in.h" +#include "interface/serial_clear_buffer_out.h" +#include "interface/serial_close.h" +#include "interface/serial_drain.h" +#include "interface/serial_get_ports_info.h" +#include "interface/serial_in_bytes_total.h" +#include "interface/serial_in_bytes_waiting.h" +#include "interface/serial_open.h" +#include "interface/serial_out_bytes_total.h" +#include "interface/serial_out_bytes_waiting.h" +#include "interface/serial_read.h" +#include "interface/serial_read_line.h" +#include "interface/serial_read_until.h" +#include "interface/serial_read_until_sequence.h" +#include "interface/serial_set_error_callback.h" +#include "interface/serial_set_read_callback.h" +#include "interface/serial_set_write_callback.h" +#include "interface/serial_write.h" diff --git a/include/cpp_core/status_codes.h b/include/cpp_core/status_codes.h new file mode 100644 index 0000000..11b45c9 --- /dev/null +++ b/include/cpp_core/status_codes.h @@ -0,0 +1,22 @@ +#pragma once + +namespace cpp_core +{ +enum class StatusCodes +{ + kSuccess = 0, + kCloseHandleError = -1, + kInvalidHandleError = -2, + kReadError = -3, + kWriteError = -4, + kGetStateError = -5, + kSetStateError = -6, + kSetTimeoutError = -7, + kBufferError = -8, + kNotFoundError = -9, + kClearBufferInError = -10, + kClearBufferOutError = -11, + kAbortReadError = -12, + kAbortWriteError = -13, +}; +} // namespace cpp_core diff --git a/include/cpp_core/version.h.in b/include/cpp_core/version.h.in new file mode 100644 index 0000000..4b398fc --- /dev/null +++ b/include/cpp_core/version.h.in @@ -0,0 +1,17 @@ +#pragma once + +namespace cpp_core +{ + +struct Version +{ + unsigned int major; + unsigned int minor; + unsigned int patch; +}; + +// Generated at configure time. Parent project can override the numbers via +// -DCPP_CORE_VERSION_XXX=... or CPM OPTIONS +inline constexpr Version kVersion{@CPP_CORE_VERSION_MAJOR@U, @CPP_CORE_VERSION_MINOR@U, @CPP_CORE_VERSION_PATCH@U}; + +} // namespace cpp_core