Compare commits
40 Commits
885ef7fea6
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| e722cd0353 | |||
| dd8e0d0552 | |||
| b1299ebd31 | |||
| 2d98bd7719 | |||
| 04e38ddf79 | |||
| c30a23669b | |||
| 3329837974 | |||
| c4e102b14c | |||
| f2847a819d | |||
| 235889604e | |||
| da504dfcf5 | |||
| 0e370b31ba | |||
| 9bc2a8587b | |||
| dd5788f72a | |||
| 95a9fcfd5e | |||
| 918588e0e4 | |||
| 6ba06dcc0c | |||
| b430846a0e | |||
| 7ba15b208f | |||
| 791ffe8633 | |||
| 0756b51950 | |||
| fd30713d29 | |||
| 930b35575c | |||
| 59b3772d5a | |||
| 9d2f5ddc2a | |||
| 336bde5fb0 | |||
| 550175fa92 | |||
| 1b93c0ca22 | |||
| 6135f3030f | |||
| c9969a1d96 | |||
| 53cf9875e6 | |||
| ccac9536e8 | |||
| f64a8368ac | |||
| 3d15cb35af | |||
| 85d6ba2216 | |||
| 288c73104c | |||
|
|
2efcf08ebe | ||
| c2b3e3997d | |||
| a55b2245bd | |||
| abfbc7eaa2 |
8
.gitignore
vendored
8
.gitignore
vendored
@@ -4,12 +4,12 @@ obj/
|
|||||||
|
|
||||||
# user files
|
# user files
|
||||||
.old*/
|
.old*/
|
||||||
[Tt]mp/
|
|
||||||
[Tt]emp/
|
|
||||||
.[Tt]mp/
|
|
||||||
.[Tt]emp/
|
|
||||||
.vs/
|
.vs/
|
||||||
.vshistory/
|
.vshistory/
|
||||||
|
tmp/
|
||||||
|
temp/
|
||||||
|
*.tmp
|
||||||
|
*.temp
|
||||||
.editorconfig
|
.editorconfig
|
||||||
*.user
|
*.user
|
||||||
*.vcxproj.filters
|
*.vcxproj.filters
|
||||||
|
|||||||
4
.gitmodules
vendored
4
.gitmodules
vendored
@@ -1,4 +0,0 @@
|
|||||||
[submodule "cbuild"]
|
|
||||||
path = cbuild
|
|
||||||
url = https://github.com/Timerix22/cbuild.git
|
|
||||||
branch = main
|
|
||||||
5
.idea/codeStyles/codeStyleConfig.xml
generated
5
.idea/codeStyles/codeStyleConfig.xml
generated
@@ -1,5 +0,0 @@
|
|||||||
<component name="ProjectCodeStyleConfiguration">
|
|
||||||
<state>
|
|
||||||
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
|
|
||||||
</state>
|
|
||||||
</component>
|
|
||||||
7
.idea/discord.xml
generated
Normal file
7
.idea/discord.xml
generated
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="DiscordProjectSettings">
|
||||||
|
<option name="show" value="PROJECT_FILES" />
|
||||||
|
<option name="description" value="" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
102
.idea/editor.xml
generated
Normal file
102
.idea/editor.xml
generated
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="BackendCodeEditorSettings">
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppClangFormat/EnableClangFormatSupport/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/EditorConfig/EnableClangFormatSupport/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_BINARY_EXPRESSIONS_CHAIN/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_CALLS_CHAIN/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_EXPRESSION/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_FOR_STMT/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTIPLE_DECLARATION/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_TERNARY/@EntryValue" value="ALIGN_ALL" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_CLASS_DEFINITION/@EntryValue" value="1" type="int" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/KEEP_BLANK_LINES_IN_DECLARATIONS/@EntryValue" value="2" type="int" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/KEEP_BLANK_LINES_IN_CODE/@EntryValue" value="2" type="int" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/KEEP_USER_LINEBREAKS/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_CASE_FROM_SWITCH/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_COMMENT/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INT_ALIGN_EQ/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SIMPLE_BLOCK_STYLE/@EntryValue" value="DO_NOT_CHANGE" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_COMMA_IN_TEMPLATE_ARGS/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_COMMA_IN_TEMPLATE_PARAMS/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_FOR_SEMICOLON/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_FOR_SEMICOLON/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_UNARY_OPERATOR/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_ARRAY_ACCESS_BRACKETS/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_CAST_EXPRESSION_PARENTHESES/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_INITIALIZER_BRACES/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_METHOD_PARENTHESES/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_INITIALIZER_BRACES/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPECIAL_ELSE_IF_TREATMENT/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_CAST_EXPRESSION_PARENTHESES/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_AFTER_BINARY_OPSIGN/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_TERNARY_OPSIGNS/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/TYPE_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/OTHER_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/CASE_BLOCK_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_FUNCTION_DECLARATION/@EntryValue" value="1" type="int" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_FUNCTION_DEFINITION/@EntryValue" value="1" type="int" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_WHILE_ON_NEW_LINE/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_ELSE_ON_NEW_LINE/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_CATCH_ON_NEW_LINE/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/NAMESPACE_INDENTATION/@EntryValue" value="All" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_ARGUMENT/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_EXTENDS_LIST/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_PARAMETER/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_TYPE_ARGUMENT/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_TYPE_PARAMETER/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_DECLARATIONS/@EntryValue" value="0" type="int" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_ACCESS_SPECIFIERS_FROM_CLASS/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_CLASS_MEMBERS_FROM_ACCESS_SPECIFIERS/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/LINE_BREAK_AFTER_COLON_IN_MEMBER_INITIALIZER_LISTS/@EntryValue" value="ON_SINGLE_LINE" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/MEMBER_INITIALIZER_LIST_STYLE/@EntryValue" value="DO_NOT_CHANGE" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_NAMESPACE_DEFINITIONS_ON_SAME_LINE/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_COLON_IN_BITFIELD_DECLARATOR/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_COLON_IN_BITFIELD_DECLARATOR/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_EXTENDS_COLON/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_EXTENDS_COLON/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_FOR_COLON/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_FOR_COLON/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_DATA_MEMBER/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_DATA_MEMBERS/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_METHOD/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_NESTED_DECLARATOR/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_REF_IN_DATA_MEMBER/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_REF_IN_DATA_MEMBERS/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_REF_IN_METHOD/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_ABSTRACT_DECL/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_DATA_MEMBER/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_DATA_MEMBERS/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_METHOD/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_ABSTRACT_DECL/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_DATA_MEMBER/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_DATA_MEMBERS/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_METHOD/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_TEMPLATE_ARGS/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_TEMPLATE_PARAMS/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BETWEEN_CLOSING_ANGLE_BRACKETS_IN_TEMPLATE_ARGS/@EntryValue" value="true" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_TEMPLATE_PARAMS/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_TEMPLATE_ARGS/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_TEMPLATE_PARAMS/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_DECLARATION_PARENTHESES/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_BLOCKS/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_INVOCATION_LPAR/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_AFTER_INVOCATION_LPAR/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_INVOCATION_RPAR/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_DECLARATION_LPAR/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_AFTER_DECLARATION_LPAR/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_DECLARATION_RPAR/@EntryValue" value="false" type="bool" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_ARGUMENTS_STYLE/@EntryValue" value="WRAP_IF_LONG" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_PARAMETERS_STYLE/@EntryValue" value="WRAP_IF_LONG" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BREAK_TEMPLATE_DECLARATION/@EntryValue" value="LINE_BREAK" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/NAMESPACE_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/FREE_BLOCK_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INVOCABLE_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ANONYMOUS_METHOD_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INITIALIZER_BRACES/@EntryValue" value="END_OF_LINE_NO_SPACE" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_STYLE/@EntryValue" value="Space" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_SIZE/@EntryValue" value="4" type="int" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/CONTINUOUS_LINE_INDENT/@EntryValue" value="Double" type="string" />
|
||||||
|
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/TAB_WIDTH/@EntryValue" value="4" type="int" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
25
.idea/inspectionProfiles/Project_Default.xml
generated
25
.idea/inspectionProfiles/Project_Default.xml
generated
@@ -1,29 +1,6 @@
|
|||||||
<component name="InspectionProjectProfileManager">
|
<component name="InspectionProjectProfileManager">
|
||||||
<profile version="1.0">
|
<profile version="1.0">
|
||||||
<option name="myName" value="Project Default" />
|
<option name="myName" value="Project Default" />
|
||||||
<inspection_tool class="ClangTidy" enabled="true" level="WARNING" enabled_by_default="true">
|
<inspection_tool class="CodeBlock2Expr" enabled="true" level="TEXT ATTRIBUTES" enabled_by_default="true" editorAttributes="CONSIDERATION_ATTRIBUTES" />
|
||||||
<option name="clangTidyCheckOptions">
|
|
||||||
<list>
|
|
||||||
<ClangTidyCheckOption />
|
|
||||||
</list>
|
|
||||||
</option>
|
|
||||||
<option name="clangTidyChecks" value="-*,bugprone-argument-comment,bugprone-assert-side-effect,bugprone-bad-signal-to-kill-thread,bugprone-branch-clone,bugprone-copy-constructor-init,bugprone-dangling-handle,bugprone-dynamic-static-initializers,bugprone-fold-init-type,bugprone-forward-declaration-namespace,bugprone-forwarding-reference-overload,bugprone-inaccurate-erase,bugprone-incorrect-roundings,bugprone-integer-division,bugprone-lambda-function-name,bugprone-macro-repeated-side-effects,bugprone-misplaced-operator-in-strlen-in-alloc,bugprone-misplaced-pointer-arithmetic-in-alloc,bugprone-misplaced-widening-cast,bugprone-move-forwarding-reference,bugprone-multiple-statement-macro,bugprone-no-escape,bugprone-not-null-terminated-result,bugprone-parent-virtual-call,bugprone-posix-return,bugprone-sizeof-container,bugprone-sizeof-expression,bugprone-spuriously-wake-up-functions,bugprone-string-constructor,bugprone-string-integer-assignment,bugprone-string-literal-with-embedded-nul,bugprone-suspicious-enum-usage,bugprone-suspicious-include,bugprone-suspicious-memory-comparison,bugprone-suspicious-memset-usage,bugprone-suspicious-missing-comma,bugprone-suspicious-semicolon,bugprone-suspicious-string-compare,bugprone-swapped-arguments,bugprone-terminating-continue,bugprone-throw-keyword-missing,bugprone-too-small-loop-variable,bugprone-undefined-memory-manipulation,bugprone-undelegated-constructor,bugprone-unhandled-self-assignment,bugprone-unused-raii,bugprone-unused-return-value,bugprone-use-after-move,bugprone-virtual-near-miss,cert-dcl21-cpp,cert-dcl58-cpp,cert-err34-c,cert-err52-cpp,cert-err58-cpp,cert-err60-cpp,cert-flp30-c,cert-msc50-cpp,cert-msc51-cpp,cert-str34-c,cppcoreguidelines-interfaces-global-init,cppcoreguidelines-narrowing-conversions,cppcoreguidelines-pro-type-member-init,cppcoreguidelines-pro-type-static-cast-downcast,cppcoreguidelines-slicing,google-default-arguments,google-explicit-constructor,google-runtime-operator,hicpp-exception-baseclass,hicpp-multiway-paths-covered,misc-misplaced-const,misc-new-delete-overloads,misc-no-recursion,misc-non-copyable-objects,misc-throw-by-value-catch-by-reference,misc-unconventional-assign-operator,misc-uniqueptr-reset-release,modernize-avoid-bind,modernize-concat-nested-namespaces,modernize-deprecated-headers,modernize-deprecated-ios-base-aliases,modernize-loop-convert,modernize-make-shared,modernize-make-unique,modernize-pass-by-value,modernize-raw-string-literal,modernize-redundant-void-arg,modernize-replace-auto-ptr,modernize-replace-disallow-copy-and-assign-macro,modernize-replace-random-shuffle,modernize-return-braced-init-list,modernize-shrink-to-fit,modernize-unary-static-assert,modernize-use-auto,modernize-use-bool-literals,modernize-use-emplace,modernize-use-equals-default,modernize-use-equals-delete,modernize-use-nodiscard,modernize-use-noexcept,modernize-use-nullptr,modernize-use-override,modernize-use-transparent-functors,modernize-use-uncaught-exceptions,mpi-buffer-deref,mpi-type-mismatch,openmp-use-default-none,performance-faster-string-find,performance-for-range-copy,performance-implicit-conversion-in-loop,performance-inefficient-algorithm,performance-inefficient-string-concatenation,performance-inefficient-vector-operation,performance-move-const-arg,performance-move-constructor-init,performance-no-automatic-move,performance-noexcept-move-constructor,performance-trivially-destructible,performance-type-promotion-in-math-fn,performance-unnecessary-copy-initialization,performance-unnecessary-value-param,portability-simd-intrinsics,readability-avoid-const-params-in-decls,readability-const-return-type,readability-container-size-empty,readability-convert-member-functions-to-static,readability-delete-null-pointer,readability-deleted-default,readability-inconsistent-declaration-parameter-name,readability-make-member-function-const,readability-misleading-indentation,readability-misplaced-array-index,readability-non-const-parameter,readability-redundant-control-flow,readability-redundant-declaration,readability-redundant-function-ptr-dereference,readability-redundant-smartptr-get,readability-redundant-string-cstr,readability-redundant-string-init,readability-simplify-subscript-expr,readability-static-accessed-through-instance,readability-static-definition-in-anonymous-namespace,readability-string-compare,readability-uniqueptr-delete-release,readability-use-anyofallof" />
|
|
||||||
</inspection_tool>
|
|
||||||
<inspection_tool class="ClangdErrorsAndWarnings" enabled="false" level="WARNING" enabled_by_default="false" />
|
|
||||||
<inspection_tool class="EmptyDeclOrStmt" enabled="false" level="WARNING" enabled_by_default="false" />
|
|
||||||
<inspection_tool class="GrazieInspection" enabled="false" level="TYPO" enabled_by_default="false" />
|
|
||||||
<inspection_tool class="LanguageDetectionInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
|
||||||
<inspection_tool class="Misra" enabled="false" level="WARNING" enabled_by_default="false">
|
|
||||||
<option name="myMisraCPPChecks" value="clion-misra-cpp2008-*,-clion-misra-cpp2008-11-0-1" />
|
|
||||||
</inspection_tool>
|
|
||||||
<inspection_tool class="OCUnusedGlobalDeclaration" enabled="false" level="WARNING" enabled_by_default="false" />
|
|
||||||
<inspection_tool class="ShellCheck" enabled="false" level="ERROR" enabled_by_default="false">
|
|
||||||
<shellcheck_settings value="SC2034,SC2035,SC2059,SC2061,SC2091,SC2155" />
|
|
||||||
</inspection_tool>
|
|
||||||
<inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false">
|
|
||||||
<option name="processCode" value="true" />
|
|
||||||
<option name="processLiterals" value="true" />
|
|
||||||
<option name="processComments" value="true" />
|
|
||||||
</inspection_tool>
|
|
||||||
</profile>
|
</profile>
|
||||||
</component>
|
</component>
|
||||||
1
.idea/vcs.xml
generated
1
.idea/vcs.xml
generated
@@ -2,5 +2,6 @@
|
|||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="VcsDirectoryMappings">
|
<component name="VcsDirectoryMappings">
|
||||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||||
|
<mapping directory="$PROJECT_DIR$/cbuild" vcs="Git" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
24
.vscode/launch.json
vendored
24
.vscode/launch.json
vendored
@@ -11,19 +11,7 @@
|
|||||||
"stopAtEntry": false,
|
"stopAtEntry": false,
|
||||||
"externalConsole": false,
|
"externalConsole": false,
|
||||||
"MIMode": "gdb",
|
"MIMode": "gdb",
|
||||||
"miDebuggerPath": "gdb",
|
"miDebuggerPath": "gdb"
|
||||||
"setupCommands": [
|
|
||||||
{
|
|
||||||
"description": "Enable pretty-printing for gdb",
|
|
||||||
"text": "-enable-pretty-printing",
|
|
||||||
"ignoreFailures": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"description": "Set Disassembly Flavor to Intel",
|
|
||||||
"text": "-gdb-set disassembly-flavor intel",
|
|
||||||
"ignoreFailures": true
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "(gdb-pipe) Debug",
|
"name": "(gdb-pipe) Debug",
|
||||||
@@ -42,6 +30,16 @@
|
|||||||
"pipeArgs": ["-c"],
|
"pipeArgs": ["-c"],
|
||||||
"pipeCwd": "${workspaceFolder}"
|
"pipeCwd": "${workspaceFolder}"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "(msvc) Debug",
|
||||||
|
"type": "cppvsdbg",
|
||||||
|
"request": "launch",
|
||||||
|
"preLaunchTask": "build_dbg",
|
||||||
|
"program": "${workspaceFolder}\\bin\\kerep",
|
||||||
|
"cwd": "${workspaceFolder}\\bin",
|
||||||
|
"stopAtEntry": false,
|
||||||
|
"console": "integratedTerminal"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
3
.vscode/tasks.json
vendored
3
.vscode/tasks.json
vendored
@@ -23,7 +23,8 @@
|
|||||||
"reveal": "always",
|
"reveal": "always",
|
||||||
"focus": true,
|
"focus": true,
|
||||||
"panel": "shared",
|
"panel": "shared",
|
||||||
"showReuseMessage": false
|
"showReuseMessage": false,
|
||||||
|
"clean": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
85
Makefile
85
Makefile
@@ -1,85 +0,0 @@
|
|||||||
######################################
|
|
||||||
###### Build tasks #######
|
|
||||||
######################################
|
|
||||||
|
|
||||||
all: build_exec_dbg
|
|
||||||
|
|
||||||
# creates executable using profiling info generated by profile
|
|
||||||
build_exec: profile
|
|
||||||
@cbuild/call_task.sh build_exec 2>&1 | tee -a make_raw.log
|
|
||||||
|
|
||||||
# creates executable with debug info and no optimizations
|
|
||||||
build_exec_dbg:
|
|
||||||
@cbuild/call_task.sh build_exec_dbg 2>&1 | tee make_raw.log
|
|
||||||
|
|
||||||
# creates shared library
|
|
||||||
build_shared_lib:
|
|
||||||
@cbuild/call_task.sh build_shared_lib 2>&1 | tee make_raw.log
|
|
||||||
|
|
||||||
# creates shared library with debug symbols and no optimizations
|
|
||||||
build_shared_lib_dbg:
|
|
||||||
@cbuild/call_task.sh build_shared_lib_dbg 2>&1 | tee make_raw.log
|
|
||||||
|
|
||||||
# creates static library
|
|
||||||
build_static_lib:
|
|
||||||
@cbuild/call_task.sh build_static_lib 2>&1 | tee make_raw.log
|
|
||||||
|
|
||||||
# creates static library with debug symbols and no optimizations
|
|
||||||
build_static_lib_dbg:
|
|
||||||
@cbuild/call_task.sh build_static_lib_dbg 2>&1 | tee make_raw.log
|
|
||||||
|
|
||||||
######################################
|
|
||||||
###### Launch tasks #######
|
|
||||||
######################################
|
|
||||||
|
|
||||||
# executes $EXEC_FILE
|
|
||||||
exec: build_exec
|
|
||||||
@cbuild/call_task.sh exec 2>&1 | tee -a make_raw.log
|
|
||||||
|
|
||||||
# executes $EXEC_FILE
|
|
||||||
exec_dbg: build_exec_dbg
|
|
||||||
@cbuild/call_task.sh exec 2>&1 | tee -a make_raw.log
|
|
||||||
|
|
||||||
# executes $EXEC_FILE with valgrind memory checker
|
|
||||||
valgrind: build_exec_dbg
|
|
||||||
@cbuild/call_task.sh valgrind 2>&1 | tee -a make_raw.log
|
|
||||||
|
|
||||||
# generates profiling info
|
|
||||||
profile:
|
|
||||||
@cbuild/call_task.sh profile 2>&1 | tee make_raw.log
|
|
||||||
|
|
||||||
# compiles program with -pg and runs it with gprof
|
|
||||||
# uses gprof2dot python script to generate function call tree (pip install gprof2dot)
|
|
||||||
# requires graphviz (https://www.graphviz.org/download/source/)
|
|
||||||
gprof:
|
|
||||||
@cbuild/call_task.sh gprof 2>&1 | tee make_raw.log
|
|
||||||
|
|
||||||
# compiles program and runs it with callgrind (part of valgrind)
|
|
||||||
# uses gprof2dot python script to generate function call tree (pip install gprof2dot)
|
|
||||||
# requires graphviz (https://www.graphviz.org/download/source/)
|
|
||||||
# P.S. detailed rezults can be viewed in KCacheGrind
|
|
||||||
callgrind:
|
|
||||||
@cbuild/call_task.sh callgrind 2>&1 | tee make_raw.log
|
|
||||||
|
|
||||||
# compiles executable with sanitizers and executes it to find errors and warnings
|
|
||||||
sanitize:
|
|
||||||
@cbuild/call_task.sh sanitize 2>&1 | tee make_raw.log
|
|
||||||
|
|
||||||
######################################
|
|
||||||
###### Other tasks #######
|
|
||||||
######################################
|
|
||||||
|
|
||||||
# deletes generated files
|
|
||||||
clean:
|
|
||||||
@cbuild/call_task.sh clean 2>&1 | tee make_raw.log
|
|
||||||
|
|
||||||
# removes all unreadable characters copied from stdio
|
|
||||||
fix_log:
|
|
||||||
sed 's/[^[:blank:][:print:]]//g' make_raw.log \
|
|
||||||
| sed 's/\[0;[0-9][0-9]m//g' \
|
|
||||||
| sed 's/\[0;[0-9]m//g' \
|
|
||||||
| sed 's/\[[0-9][0-9]m//g' \
|
|
||||||
| sed 's/\[[0-9]m//g' \
|
|
||||||
| sed 's/ H //g' \
|
|
||||||
| sed 's/\[3gH //g' \
|
|
||||||
> make_fixed.log
|
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
# kerep
|
# kerep
|
||||||
|
My library written in C.
|
||||||
My library written in C
|
Requires [cbuild](https://timerix.ddns.net:3322/Timerix/cbuild).
|
||||||
|
|||||||
29
TODO.md
29
TODO.md
@@ -1,29 +0,0 @@
|
|||||||
## Allocators
|
|
||||||
- replace all malloc() and free() with allocator_alloc() and allocator_free()
|
|
||||||
- replace allocating constructors with Type_construct(var_ptr, ...)
|
|
||||||
- replace Struct_free functions with Struct_destruct which will not call free() on the struct ptr
|
|
||||||
- store in resizable structs their buffer allocators and free them with Struct_destruct()
|
|
||||||
- check allocator_free call order
|
|
||||||
- deal with StackingAllocator_free not freing memory sometimes
|
|
||||||
- replace LinearAllocator with StackingAllocator when possible (in DtsodV24_deserialize)
|
|
||||||
- use LinkedList instead of complicated LinearAllocator logic
|
|
||||||
- configurable LinearAllocator chunk size (static/growing)
|
|
||||||
|
|
||||||
## Autoarr
|
|
||||||
- store length and max_length inside the struct instead of calculating them by macro
|
|
||||||
- keep Autoarr_length() and Autoarr_maxLength() to old code compatibility
|
|
||||||
- toString()
|
|
||||||
|
|
||||||
## Hashtable
|
|
||||||
- store hash in KVPair
|
|
||||||
- don't use Autoarr in Hashtable
|
|
||||||
- make Hashtable generic struct
|
|
||||||
|
|
||||||
## Unitype
|
|
||||||
- replace UniPtrHeap with UniPtrStack
|
|
||||||
- do something with VoidPtr ownership
|
|
||||||
|
|
||||||
## String
|
|
||||||
- add `bool zero_terminated`
|
|
||||||
- rewrite all code to use `string` instead of `char*`
|
|
||||||
- rewrite `StringBuilder`
|
|
||||||
1
cbuild
1
cbuild
Submodule cbuild deleted from 60fa8c11c2
@@ -1,6 +1,6 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
CBUILD_VERSION=7
|
CBUILD_VERSION=2.1.1
|
||||||
CONFIG_VERSION=7
|
CONFIG_VERSION=9
|
||||||
|
|
||||||
PROJECT="kerep"
|
PROJECT="kerep"
|
||||||
CMP_C="gcc"
|
CMP_C="gcc"
|
||||||
@@ -37,10 +37,12 @@ case "$OS" in
|
|||||||
WINDOWS)
|
WINDOWS)
|
||||||
EXEC_FILE="$PROJECT.exe"
|
EXEC_FILE="$PROJECT.exe"
|
||||||
SHARED_LIB_FILE="$PROJECT.dll"
|
SHARED_LIB_FILE="$PROJECT.dll"
|
||||||
|
LINKER_LIBS="-lpthread -lws2_32"
|
||||||
;;
|
;;
|
||||||
LINUX)
|
LINUX)
|
||||||
EXEC_FILE="$PROJECT"
|
EXEC_FILE="$PROJECT"
|
||||||
SHARED_LIB_FILE="$PROJECT.so"
|
SHARED_LIB_FILE="$PROJECT.so"
|
||||||
|
LINKER_LIBS=""
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
error "operating system $OS has no configuration variants"
|
error "operating system $OS has no configuration variants"
|
||||||
@@ -59,25 +61,29 @@ case "$TASK" in
|
|||||||
# -fdata-sections -ffunction-sections -Wl,--gc-sections removes unused code
|
# -fdata-sections -ffunction-sections -Wl,--gc-sections removes unused code
|
||||||
C_ARGS="-O2 -flto=auto -fuse-linker-plugin -fprofile-use -fprofile-prefix-path=$(realpath $OBJDIR)/objects -fdata-sections -ffunction-sections -Wl,--gc-sections"
|
C_ARGS="-O2 -flto=auto -fuse-linker-plugin -fprofile-use -fprofile-prefix-path=$(realpath $OBJDIR)/objects -fdata-sections -ffunction-sections -Wl,--gc-sections"
|
||||||
CPP_ARGS="$C_ARGS"
|
CPP_ARGS="$C_ARGS"
|
||||||
LINKER_ARGS="$CPP_ARGS"
|
LINKER_ARGS="$CPP_ARGS $LINKER_LIBS"
|
||||||
PRE_TASK_SCRIPT=
|
PRE_TASK_SCRIPT=
|
||||||
TASK_SCRIPT=cbuild/default_tasks/build_exec.sh
|
TASK_SCRIPT=cbuild/default_tasks/build_exec.sh
|
||||||
POST_TASK_SCRIPT=
|
POST_TASK_SCRIPT=
|
||||||
|
SRC_C+=" $TESTS_C"
|
||||||
|
SRC_CPP+=" $TESTS_CPP"
|
||||||
;;
|
;;
|
||||||
# creates executable with debug info and no optimizations
|
# creates executable with debug info and no optimizations
|
||||||
build_exec_dbg)
|
build_exec_dbg)
|
||||||
C_ARGS="-O0 -g3"
|
C_ARGS="-O0 -g3"
|
||||||
CPP_ARGS="$C_ARGS"
|
CPP_ARGS="$C_ARGS"
|
||||||
LINKER_ARGS="$CPP_ARGS"
|
LINKER_ARGS="$CPP_ARGS $LINKER_LIBS"
|
||||||
PRE_TASK_SCRIPT=
|
PRE_TASK_SCRIPT=
|
||||||
TASK_SCRIPT=cbuild/default_tasks/build_exec.sh
|
TASK_SCRIPT=cbuild/default_tasks/build_exec.sh
|
||||||
POST_TASK_SCRIPT=
|
POST_TASK_SCRIPT=
|
||||||
|
SRC_C+=" $TESTS_C"
|
||||||
|
SRC_CPP+=" $TESTS_CPP"
|
||||||
;;
|
;;
|
||||||
# creates shared library
|
# creates shared library
|
||||||
build_shared_lib)
|
build_shared_lib)
|
||||||
C_ARGS="-O2 -fpic -flto -shared"
|
C_ARGS="-O2 -fpic -flto -shared"
|
||||||
CPP_ARGS="$C_ARGS"
|
CPP_ARGS="$C_ARGS"
|
||||||
LINKER_ARGS="$CPP_ARGS -Wl,-soname,$SHARED_LIB_FILE"
|
LINKER_ARGS="$CPP_ARGS -Wl,-soname,$SHARED_LIB_FILE $LINKER_LIBS"
|
||||||
PRE_TASK_SCRIPT=
|
PRE_TASK_SCRIPT=
|
||||||
TASK_SCRIPT=cbuild/default_tasks/build_shared_lib.sh
|
TASK_SCRIPT=cbuild/default_tasks/build_shared_lib.sh
|
||||||
POST_TASK_SCRIPT=
|
POST_TASK_SCRIPT=
|
||||||
@@ -86,7 +92,7 @@ case "$TASK" in
|
|||||||
build_shared_lib_dbg)
|
build_shared_lib_dbg)
|
||||||
C_ARGS="-O0 -g3 -fpic -shared"
|
C_ARGS="-O0 -g3 -fpic -shared"
|
||||||
CPP_ARGS="$C_ARGS"
|
CPP_ARGS="$C_ARGS"
|
||||||
LINKER_ARGS="$CPP_ARGS -Wl,-soname,$SHARED_LIB_FILE"
|
LINKER_ARGS="$CPP_ARGS -Wl,-soname,$SHARED_LIB_FILE $LINKER_LIBS"
|
||||||
PRE_TASK_SCRIPT=
|
PRE_TASK_SCRIPT=
|
||||||
TASK_SCRIPT=cbuild/default_tasks/build_shared_lib.sh
|
TASK_SCRIPT=cbuild/default_tasks/build_shared_lib.sh
|
||||||
POST_TASK_SCRIPT=
|
POST_TASK_SCRIPT=
|
||||||
@@ -113,7 +119,7 @@ case "$TASK" in
|
|||||||
;;
|
;;
|
||||||
# executes $EXEC_FILE with valgrind memory checker
|
# executes $EXEC_FILE with valgrind memory checker
|
||||||
valgrind)
|
valgrind)
|
||||||
VALGRIND_ARGS="-s --read-var-info=yes --track-origins=yes --fullpath-after=$PROJECT/ --leak-check=full --show-leak-kinds=all"
|
VALGRIND_ARGS="-s --read-var-info=yes --track-origins=yes --fullpath-after=$(pwd) --leak-check=full --show-leak-kinds=all"
|
||||||
TASK_SCRIPT=cbuild/default_tasks/valgrind.sh
|
TASK_SCRIPT=cbuild/default_tasks/valgrind.sh
|
||||||
;;
|
;;
|
||||||
# generates profiling info
|
# generates profiling info
|
||||||
@@ -127,10 +133,12 @@ case "$TASK" in
|
|||||||
# -fprofile-prefix-path sets path where profiling info about objects will be saved
|
# -fprofile-prefix-path sets path where profiling info about objects will be saved
|
||||||
C_ARGS="-O2 -flto=auto -fuse-linker-plugin -fprofile-generate -fprofile-prefix-path=$(realpath $OBJDIR)/objects"
|
C_ARGS="-O2 -flto=auto -fuse-linker-plugin -fprofile-generate -fprofile-prefix-path=$(realpath $OBJDIR)/objects"
|
||||||
CPP_ARGS="$C_ARGS"
|
CPP_ARGS="$C_ARGS"
|
||||||
LINKER_ARGS="$CPP_ARGS"
|
LINKER_ARGS="$CPP_ARGS $LINKER_LIBS"
|
||||||
PRE_TASK_SCRIPT=cbuild/default_tasks/build_exec.sh
|
PRE_TASK_SCRIPT=cbuild/default_tasks/build_exec.sh
|
||||||
TASK_SCRIPT=cbuild/default_tasks/profile.sh
|
TASK_SCRIPT=cbuild/default_tasks/profile.sh
|
||||||
POST_TASK_SCRIPT=
|
POST_TASK_SCRIPT=
|
||||||
|
SRC_C+=" $TESTS_C"
|
||||||
|
SRC_CPP+=" $TESTS_CPP"
|
||||||
;;
|
;;
|
||||||
# compiles program with -pg and runs it with gprof
|
# compiles program with -pg and runs it with gprof
|
||||||
# uses gprof2dot python script to generate function call tree (pip install gprof2dot)
|
# uses gprof2dot python script to generate function call tree (pip install gprof2dot)
|
||||||
@@ -140,41 +148,47 @@ case "$TASK" in
|
|||||||
# -pg adds code to executable, that generates file containing function call info (gmon.out)
|
# -pg adds code to executable, that generates file containing function call info (gmon.out)
|
||||||
C_ARGS="-O2 -flto=auto -fuse-linker-plugin -pg"
|
C_ARGS="-O2 -flto=auto -fuse-linker-plugin -pg"
|
||||||
CPP_ARGS="$C_ARGS"
|
CPP_ARGS="$C_ARGS"
|
||||||
LINKER_ARGS="$CPP_ARGS"
|
LINKER_ARGS="$CPP_ARGS $LINKER_LIBS"
|
||||||
PRE_TASK_SCRIPT=cbuild/default_tasks/build_exec.sh
|
PRE_TASK_SCRIPT=cbuild/default_tasks/build_exec.sh
|
||||||
TASK_SCRIPT=cbuild/default_tasks/gprof.sh
|
TASK_SCRIPT=cbuild/default_tasks/gprof.sh
|
||||||
POST_TASK_SCRIPT=
|
POST_TASK_SCRIPT=
|
||||||
|
SRC_C+=" $TESTS_C"
|
||||||
|
SRC_CPP+=" $TESTS_CPP"
|
||||||
;;
|
;;
|
||||||
# compiles program and runs it with callgrind (part of valgrind)
|
# compiles program and runs it with callgrind (part of valgrind)
|
||||||
# uses gprof2dot python script to generate function call tree (pip install gprof2dot)
|
# uses gprof2dot python script to generate function call tree (pip install gprof2dot)
|
||||||
# requires graphviz (https://www.graphviz.org/download/source/)
|
# requires graphviz (https://www.graphviz.org/download/source/)
|
||||||
# P.S. detailed rezults can be viewed in KCacheGrind
|
# P.S. detailed results can be viewed in KCacheGrind
|
||||||
callgrind)
|
callgrind)
|
||||||
OUTDIR="$OUTDIR/callgrind"
|
OUTDIR="$OUTDIR/callgrind"
|
||||||
# -pg adds code to executable, that generates file containing function call info (gmon.out)
|
# -pg adds code to executable, that generates file containing function call info (gmon.out)
|
||||||
C_ARGS="-O2 -flto=auto -fuse-linker-plugin"
|
C_ARGS="-O2 -flto=auto -fuse-linker-plugin"
|
||||||
CPP_ARGS="$C_ARGS"
|
CPP_ARGS="$C_ARGS"
|
||||||
LINKER_ARGS="$CPP_ARGS"
|
LINKER_ARGS="$CPP_ARGS $LINKER_LIBS"
|
||||||
PRE_TASK_SCRIPT=tasks/pre_build.sh
|
PRE_TASK_SCRIPT=tasks/pre_build.sh
|
||||||
TASK_SCRIPT=cbuild/default_tasks/build_exec.sh
|
TASK_SCRIPT=cbuild/default_tasks/build_exec.sh
|
||||||
POST_TASK_SCRIPT=cbuild/default_tasks/callgrind.sh
|
POST_TASK_SCRIPT=cbuild/default_tasks/callgrind.sh
|
||||||
|
SRC_C+=" $TESTS_C"
|
||||||
|
SRC_CPP+=" $TESTS_CPP"
|
||||||
;;
|
;;
|
||||||
# compiles executable with sanitizers and executes it to find errors and warnings
|
# compiles executable with sanitizers and executes it to find errors and warnings
|
||||||
sanitize)
|
sanitize)
|
||||||
OUTDIR="$OUTDIR/sanitize"
|
OUTDIR="$OUTDIR/sanitize"
|
||||||
C_ARGS="-O0 -g3 -fsanitize=undefined,address"
|
C_ARGS="-O0 -g3 -fsanitize=undefined,address"
|
||||||
CPP_ARGS="$C_ARGS"
|
CPP_ARGS="$C_ARGS"
|
||||||
LINKER_ARGS="$CPP_ARGS"
|
LINKER_ARGS="$CPP_ARGS $LINKER_LIBS"
|
||||||
PRE_TASK_SCRIPT=cbuild/default_tasks/build_exec.sh
|
PRE_TASK_SCRIPT=cbuild/default_tasks/build_exec.sh
|
||||||
TASK_SCRIPT=cbuild/default_tasks/exec.sh
|
TASK_SCRIPT=cbuild/default_tasks/exec.sh
|
||||||
POST_TASK_SCRIPT=
|
POST_TASK_SCRIPT=
|
||||||
|
SRC_C+=" $TESTS_C"
|
||||||
|
SRC_CPP+=" $TESTS_CPP"
|
||||||
;;
|
;;
|
||||||
# deletes generated files
|
# deletes generated files
|
||||||
clean)
|
clean)
|
||||||
TASK_SCRIPT=cbuild/default_tasks/clean.sh
|
TASK_SCRIPT=cbuild/default_tasks/clean.sh
|
||||||
;;
|
;;
|
||||||
# nothing to do
|
# nothing to do
|
||||||
no_task)
|
"" | no_task)
|
||||||
;;
|
;;
|
||||||
# unknown task
|
# unknown task
|
||||||
*)
|
*)
|
||||||
27
src/Array/Array.c
Normal file
27
src/Array/Array.c
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
#include "Array.h"
|
||||||
|
|
||||||
|
Array_define(char)
|
||||||
|
Array_define(bool)
|
||||||
|
Array_define(f32)
|
||||||
|
Array_define(f64)
|
||||||
|
Array_define(i8)
|
||||||
|
Array_define(u8)
|
||||||
|
Array_define(i16)
|
||||||
|
Array_define(u16)
|
||||||
|
Array_define(i32)
|
||||||
|
Array_define(u32)
|
||||||
|
Array_define(i64)
|
||||||
|
Array_define(u64)
|
||||||
|
Array_define(Pointer)
|
||||||
|
|
||||||
|
Array_define(Unitype)
|
||||||
|
|
||||||
|
void Array_Unitype_free_(Array_Unitype* array, bool freeMembers){
|
||||||
|
if(freeMembers) for (u32 i=0; i<array->length; i++)
|
||||||
|
Unitype_free(array->values[i]);
|
||||||
|
if(array->allocatedOnHeap)
|
||||||
|
free(array->values);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __Array_Unitype_free_(void* ar)
|
||||||
|
{ Array_Unitype_free_(ar, true); }
|
||||||
32
src/Array/Array.h
Normal file
32
src/Array/Array.h
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "Array_declare.h"
|
||||||
|
#include "Array_define.h"
|
||||||
|
|
||||||
|
Array_declare(char)
|
||||||
|
Array_declare(bool)
|
||||||
|
Array_declare(f32)
|
||||||
|
Array_declare(f64)
|
||||||
|
Array_declare(i8)
|
||||||
|
Array_declare(u8)
|
||||||
|
Array_declare(i16)
|
||||||
|
Array_declare(u16)
|
||||||
|
Array_declare(i32)
|
||||||
|
Array_declare(u32)
|
||||||
|
Array_declare(i64)
|
||||||
|
Array_declare(u64)
|
||||||
|
Array_declare(Pointer)
|
||||||
|
|
||||||
|
Array_declare(Unitype)
|
||||||
|
|
||||||
|
/// use this function instead of auto generated
|
||||||
|
void Array_Unitype_free_(Array_Unitype* array, bool freeMembers);
|
||||||
|
void __Array_Unitype_free_(void* ar);
|
||||||
|
|
||||||
|
#if __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
39
src/Array/Array_declare.h
Normal file
39
src/Array/Array_declare.h
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "../base/base.h"
|
||||||
|
|
||||||
|
#define Array_declare(type) \
|
||||||
|
STRUCT(Array_##type, \
|
||||||
|
type* values; \
|
||||||
|
u32 length; \
|
||||||
|
bool allocatedOnHeap; \
|
||||||
|
) \
|
||||||
|
\
|
||||||
|
static inline Array_##type Array_##type##_allocValues(u32 length){ \
|
||||||
|
return (Array_##type) { \
|
||||||
|
.values=(type*)malloc(sizeof(type)*length), \
|
||||||
|
.length=length, \
|
||||||
|
.allocatedOnHeap=true \
|
||||||
|
}; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
static inline Array_##type Array_##type##_fromBuffer(type* buffer, u32 bufferLength, bool allocatedOnHeap){ \
|
||||||
|
return (Array_##type) { \
|
||||||
|
.values=buffer, \
|
||||||
|
.length=bufferLength, \
|
||||||
|
.allocatedOnHeap=allocatedOnHeap \
|
||||||
|
}; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
static inline void Array_##type##_free(Array_##type* array){ \
|
||||||
|
if(array->allocatedOnHeap) \
|
||||||
|
free(array->values); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#if __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
14
src/Array/Array_define.h
Normal file
14
src/Array/Array_define.h
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "../base/base.h"
|
||||||
|
|
||||||
|
#define Array_define(type) \
|
||||||
|
kt_define(Array_##type, (freeMembers_t)Array_##type##_free, NULL);
|
||||||
|
|
||||||
|
#if __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
2
src/Array/README.md
Normal file
2
src/Array/README.md
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
# Array struct
|
||||||
|
This struct stores array pointer and length. If you want to use `Array` of some type, it should be declared in header file by macro `Array_declare` and defined in source file by `Array_define`.
|
||||||
@@ -1,17 +1,17 @@
|
|||||||
#include "Autoarr.h"
|
#include "Autoarr.h"
|
||||||
|
|
||||||
Autoarr_define(Pointer)
|
Autoarr_define(Pointer, true)
|
||||||
Autoarr_define(char)
|
Autoarr_define(char, false)
|
||||||
Autoarr_define(bool)
|
Autoarr_define(bool, false)
|
||||||
Autoarr_define(f32)
|
Autoarr_define(f32, false)
|
||||||
Autoarr_define(f64)
|
Autoarr_define(f64, false)
|
||||||
Autoarr_define(u8)
|
Autoarr_define(u8, false)
|
||||||
Autoarr_define(i8)
|
Autoarr_define(i8, false)
|
||||||
Autoarr_define(u16)
|
Autoarr_define(u16, false)
|
||||||
Autoarr_define(i16)
|
Autoarr_define(i16, false)
|
||||||
Autoarr_define(u32)
|
Autoarr_define(u32, false)
|
||||||
Autoarr_define(i32)
|
Autoarr_define(i32, false)
|
||||||
Autoarr_define(u64)
|
Autoarr_define(u64, false)
|
||||||
Autoarr_define(i64)
|
Autoarr_define(i64, false)
|
||||||
|
|
||||||
Autoarr_define(Unitype)
|
Autoarr_define(Unitype, false)
|
||||||
|
|||||||
@@ -23,6 +23,21 @@ Autoarr_declare(u64)
|
|||||||
|
|
||||||
Autoarr_declare(Unitype)
|
Autoarr_declare(Unitype)
|
||||||
|
|
||||||
|
#define Autoarr_foreach(ar, elem, codeblock...) { \
|
||||||
|
if(ar->blocks_count>0) { \
|
||||||
|
typeof(**ar->values) elem; \
|
||||||
|
for(u16 blockI=0;blockI<ar->blocks_count-1;blockI++) \
|
||||||
|
for(u32 elemI=0;elemI<ar->max_block_length;elemI++){ \
|
||||||
|
elem=ar->values[blockI][elemI]; \
|
||||||
|
{ codeblock; } \
|
||||||
|
} \
|
||||||
|
for(u16 elemI=0;elemI<ar->block_length;elemI++){ \
|
||||||
|
elem=ar->values[ar->blocks_count-1][elemI]; \
|
||||||
|
{ codeblock; } \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
#if __cplusplus
|
#if __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
38
src/Autoarr/Autoarr_KVPair_exported.c
Normal file
38
src/Autoarr/Autoarr_KVPair_exported.c
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
#if __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "Autoarr.h"
|
||||||
|
#include "../Hashtable/KeyValuePair.h"
|
||||||
|
|
||||||
|
EXPORT void CALL kerep_Autoarr_KVPair_create(u16 max_blocks_count, u16 max_block_length, Autoarr_KVPair** output){
|
||||||
|
*output=Autoarr_create(KVPair, max_blocks_count, max_block_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORT void CALL kerep_Autoarr_KVPair_free(Autoarr_KVPair* ar){
|
||||||
|
Autoarr_free(ar, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORT void CALL kerep_Autoarr_KVPair_get(Autoarr_KVPair* ar, u32 index, KVPair* output){
|
||||||
|
*output=Autoarr_get(ar, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORT void CALL kerep_Autoarr_KVPair_add(Autoarr_KVPair* ar, KVPair element){
|
||||||
|
Autoarr_add(ar, element);
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORT void CALL kerep_Autoarr_KVPair_set(Autoarr_KVPair* ar, u32 index, KVPair element){
|
||||||
|
Autoarr_set(ar, index, element);
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORT void CALL kerep_Autoarr_KVPair_length(Autoarr_KVPair* ar, u32* output){
|
||||||
|
*output=Autoarr_length(ar);
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORT void CALL kerep_Autoarr_KVPair_max_length(Autoarr_KVPair* ar, u32* output){
|
||||||
|
*output=Autoarr_max_length(ar);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -4,12 +4,12 @@ extern "C" {
|
|||||||
|
|
||||||
#include "Autoarr.h"
|
#include "Autoarr.h"
|
||||||
|
|
||||||
EXPORT void CALL kerep_Autoarr_Unitype_create(u16 max_chunks_count, u16 max_chunk_length, Autoarr_Unitype** output){
|
EXPORT void CALL kerep_Autoarr_Unitype_create(u16 max_blocks_count, u16 max_block_length, Autoarr_Unitype** output){
|
||||||
*output=Autoarr_construct(Unitype, max_chunks_count, max_chunk_length);
|
*output=Autoarr_create(Unitype, max_blocks_count, max_block_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT void CALL kerep_Autoarr_Unitype_destruct(Autoarr_Unitype* ar){
|
EXPORT void CALL kerep_Autoarr_Unitype_free(Autoarr_Unitype* ar){
|
||||||
Autoarr_destruct(ar, true);
|
Autoarr_free(ar, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT void CALL kerep_Autoarr_Unitype_get(Autoarr_Unitype* ar, u32 index, Unitype* output){
|
EXPORT void CALL kerep_Autoarr_Unitype_get(Autoarr_Unitype* ar, u32 index, Unitype* output){
|
||||||
@@ -6,60 +6,67 @@ extern "C" {
|
|||||||
|
|
||||||
#include "../base/base.h"
|
#include "../base/base.h"
|
||||||
|
|
||||||
#define Autoarr_declare(TYPE) \
|
#define Autoarr_declare(type) \
|
||||||
\
|
\
|
||||||
typedef struct Autoarr_##TYPE Autoarr_##TYPE; \
|
struct Autoarr_##type; \
|
||||||
\
|
\
|
||||||
typedef struct __Autoarr_##TYPE##_functions_list_t { \
|
typedef struct __Autoarr_##type##_functions_list_t { \
|
||||||
void (*add)(Autoarr_##TYPE* ar, TYPE element); \
|
void (*add)(struct Autoarr_##type* ar, type element); \
|
||||||
TYPE (*get)(Autoarr_##TYPE* ar, u32 index); \
|
type (*get)(struct Autoarr_##type* ar, u32 index); \
|
||||||
TYPE* (*getPtr)(Autoarr_##TYPE* ar, u32 index); \
|
type* (*getPtr)(struct Autoarr_##type* ar, u32 index); \
|
||||||
void (*set)(Autoarr_##TYPE* ar, u32 index, TYPE element); \
|
void (*set)(struct Autoarr_##type* ar, u32 index, type element); \
|
||||||
TYPE* (*toArray)(Autoarr_##TYPE* ar, allocator_ptr array_holder); \
|
void (*freeWithMembers)(struct Autoarr_##type* ar, bool freePtr); \
|
||||||
} __Autoarr_##TYPE##_functions_list_t; \
|
void (*freeWithoutMembers)(struct Autoarr_##type* ar, bool freePtr); \
|
||||||
|
type* (*toArray)(struct Autoarr_##type* ar); \
|
||||||
|
} __Autoarr_##type##_functions_list_t; \
|
||||||
\
|
\
|
||||||
STRUCT(Autoarr_##TYPE, \
|
extern __Autoarr_##type##_functions_list_t __Autoarr_##type##_functions_list; \
|
||||||
InternalAllocator_declare(LinearAllocator); \
|
\
|
||||||
__Autoarr_##TYPE##_functions_list_t* functions; \
|
STRUCT(Autoarr_##type, \
|
||||||
ktDescriptor* type; \
|
u16 blocks_count; \
|
||||||
u32 length; \
|
u16 max_blocks_count; \
|
||||||
TYPE* _typeof_target; \
|
u16 block_length; \
|
||||||
|
u16 max_block_length; \
|
||||||
|
type** values; \
|
||||||
|
__Autoarr_##type##_functions_list_t* functions; \
|
||||||
) \
|
) \
|
||||||
\
|
\
|
||||||
void __Autoarr_##TYPE##_construct(Autoarr_##TYPE* ar, alloc_size_t starting_size, allocator_ptr external_al); \
|
Autoarr_##type* __Autoarr_##type##_create(u16 max_blocks_count, u16 max_block_length); \
|
||||||
void __Autoarr_##TYPE##_destruct(Autoarr_##TYPE* ar); \
|
void __Autoarr_##type##_freeWithMembers(Autoarr_##type* ar, bool freePtr); \
|
||||||
|
void ____Autoarr_##type##_freeWithMembers(void* ar);
|
||||||
|
|
||||||
#define Autoarr(TYPE) Autoarr_##TYPE
|
#define Autoarr(type) Autoarr_##type
|
||||||
|
|
||||||
#define Autoarr_construct(ptr, TYPE, starting_size, data_allocator) \
|
#define Autoarr_create(type, max_blocks_count, max_block_length) \
|
||||||
__Autoarr_##TYPE##_construct(ptr, starting_size, data_allocator)
|
__Autoarr_##type##_create(max_blocks_count, max_block_length)
|
||||||
#define Autoarr_destruct(autoarr) (autoarr)->type->destruct(autoarr)
|
#define Autoarr_add(autoarr, element) \
|
||||||
#define Autoarr_add(autoarr, element) (autoarr)->functions->add(autoarr, element)
|
autoarr->functions->add(autoarr, element)
|
||||||
#define Autoarr_get(autoarr, index) (autoarr)->functions->get(autoarr,index)
|
#define Autoarr_get(autoarr, index) \
|
||||||
#define Autoarr_getPtr(autoarr, index) (autoarr)->functions->getPtr(autoarr,index)
|
autoarr->functions->get(autoarr,index)
|
||||||
#define Autoarr_set(autoarr, index, element) (autoarr)->functions->set(autoarr, index, element)
|
#define Autoarr_getPtr(autoarr, index) \
|
||||||
#define Autoarr_toArray(autoarr, array_alloctr) (autoarr)->functions->toArray(autoarr, array_alloctr)
|
autoarr->functions->getPtr(autoarr,index)
|
||||||
#define Autoarr_length(autoarr) (autoarr)->length
|
#define Autoarr_set(autoarr, index, element) \
|
||||||
#define Autoarr_pop(autoarr) { \
|
autoarr->functions->set(autoarr, index, element)
|
||||||
u32 new_len=(autoarr)->length-1; \
|
#define Autoarr_free(autoarr, freePtr) \
|
||||||
allocator_free(InternalAllocator_getPtr((autoarr)), Autoarr_getPtr((autoarr), new_len)); \
|
autoarr->functions->freeWithMembers(autoarr, freePtr)
|
||||||
(autoarr)->length=new_len; \
|
#define Autoarr_freeWithoutMembers(autoarr, freePtr) \
|
||||||
}
|
autoarr->functions->freeWithoutMembers(autoarr, freePtr)
|
||||||
|
#define Autoarr_toArray(autoarr) \
|
||||||
|
autoarr->functions->toArray(autoarr)
|
||||||
|
|
||||||
#define Autoarr_foreach(ar, elem, codeblock...) { \
|
#define Autoarr_length(autoarr) \
|
||||||
if((ar)->length > 0) { \
|
(u32)(!autoarr->blocks_count ? 0 : \
|
||||||
typeof(*((ar)->_typeof_target)) elem; \
|
autoarr->max_block_length*(autoarr->blocks_count-1)+autoarr->block_length)
|
||||||
LinearAllocator* al=(LinearAllocator*)InternalAllocator_getPtr(ar); \
|
#define Autoarr_max_length(autoarr) \
|
||||||
for(u16 chunk_i=0; chunk_i <= al->curr_chunk_i; chunk_i++) { \
|
(u32)(autoarr->max_block_length*autoarr->max_blocks_count)
|
||||||
MemoryChunk chunk = al->chunks[chunk_i]; \
|
|
||||||
alloc_size_t chunk_elem_count = chunk.occupied_size/sizeof(elem); \
|
#define Autoarr_pop(AR){ \
|
||||||
typeof((ar)->_typeof_target) chunk_data = (void*)chunk.data; \
|
if(AR->block_length==1){ \
|
||||||
for(u32 elem##_i=0; elem##_i < chunk_elem_count; elem##_i++) { \
|
AR->blocks_count--; \
|
||||||
elem = chunk_data[elem##_i]; \
|
AR->block_length=AR->max_block_length; \
|
||||||
{ codeblock; } \
|
free(AR->values[AR->blocks_count]); \
|
||||||
} \
|
|
||||||
} \
|
|
||||||
} \
|
} \
|
||||||
|
else AR->block_length--; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#if __cplusplus
|
#if __cplusplus
|
||||||
|
|||||||
@@ -6,72 +6,94 @@ extern "C" {
|
|||||||
|
|
||||||
#include "../base/base.h"
|
#include "../base/base.h"
|
||||||
|
|
||||||
#define Autoarr_define(TYPE) \
|
#define Autoarr_define(type, TYPE_IS_PTR) \
|
||||||
\
|
\
|
||||||
void __Autoarr_##TYPE##_add(Autoarr_##TYPE* ar, TYPE element){ \
|
kt_define(Autoarr_##type, ____Autoarr_##type##_freeWithMembers, NULL); \
|
||||||
TYPE* ptr = allocator_alloc(InternalAllocator_getPtr(ar), sizeof(element)); \
|
|
||||||
*ptr=element; \
|
|
||||||
ar->length++; \
|
|
||||||
} \
|
|
||||||
\
|
\
|
||||||
TYPE* __Autoarr_##TYPE##_getPtr(Autoarr_##TYPE* ar, u32 index){ \
|
void __Autoarr_##type##_add(Autoarr_##type* ar, type element){ \
|
||||||
if(index >= Autoarr_length(ar)) \
|
if(!ar->values){ \
|
||||||
throw(ERR_WRONGINDEX); \
|
ar->values=malloc(ar->max_blocks_count*sizeof(type*)); \
|
||||||
u32 elem_count_sum=0; \
|
goto create_block; \
|
||||||
LinearAllocator* al=(LinearAllocator*)InternalAllocator_getPtr(ar); \
|
|
||||||
for(u16 chunk_i=0; chunk_i <= al->curr_chunk_i; chunk_i++) { \
|
|
||||||
MemoryChunk chunk = al->chunks[chunk_i]; \
|
|
||||||
alloc_size_t chunk_elem_count = chunk.occupied_size/sizeof(TYPE); \
|
|
||||||
alloc_size_t chunk_elem_i = index - elem_count_sum; \
|
|
||||||
if(chunk_elem_i < chunk_elem_count){ \
|
|
||||||
return chunk.data + chunk_elem_i*sizeof(TYPE); \
|
|
||||||
} \
|
} \
|
||||||
elem_count_sum += chunk_elem_count; \
|
if(ar->block_length==ar->max_block_length){ \
|
||||||
|
if (ar->blocks_count>=ar->max_blocks_count) throw(ERR_MAXLENGTH); \
|
||||||
|
ar->block_length=0; \
|
||||||
|
create_block: \
|
||||||
|
ar->values[ar->blocks_count]=malloc(ar->max_block_length*sizeof(type)); \
|
||||||
|
ar->blocks_count++; \
|
||||||
} \
|
} \
|
||||||
return NULL; \
|
ar->values[ar->blocks_count-1][ar->block_length]=element; \
|
||||||
|
ar->block_length++; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
TYPE __Autoarr_##TYPE##_get(Autoarr_##TYPE* ar, u32 index){ \
|
type __Autoarr_##type##_get(Autoarr_##type* ar, u32 index){ \
|
||||||
TYPE* ptr=__Autoarr_##TYPE##_getPtr(ar, index); \
|
if(index>=Autoarr_length(ar)) throw(ERR_WRONGINDEX); \
|
||||||
return *ptr; \
|
return ar->values[index/ar->max_block_length][index%ar->max_block_length]; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
void __Autoarr_##TYPE##_set(Autoarr_##TYPE* ar, u32 index, TYPE value){ \
|
type* __Autoarr_##type##_getPtr(Autoarr_##type* ar, u32 index){ \
|
||||||
TYPE* ptr=__Autoarr_##TYPE##_getPtr(ar, index); \
|
if(index>=Autoarr_length(ar)) throw(ERR_WRONGINDEX); \
|
||||||
*ptr=value; \
|
return ar->values[index/ar->max_block_length]+(index%ar->max_block_length); \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
void __Autoarr_##TYPE##_destruct(Autoarr_##TYPE* ar){ \
|
void __Autoarr_##type##_set(Autoarr_##type* ar, u32 index, type element){ \
|
||||||
InternalAllocator_destructIfInternal(LinearAllocator, ar); \
|
if(index>=Autoarr_length(ar)) throw(ERR_WRONGINDEX); \
|
||||||
|
ar->values[index/ar->max_block_length][index%ar->max_block_length]=element; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
TYPE* __Autoarr_##TYPE##_toArray(Autoarr_##TYPE* ar, allocator_ptr array_alloctr){ \
|
void __Autoarr_##type##_freeWithoutMembers(Autoarr_##type* ar, bool freePtr){ \
|
||||||
|
for(u16 i=0; i<ar->blocks_count;i++) \
|
||||||
|
free(ar->values[i]); \
|
||||||
|
free(ar->values); \
|
||||||
|
if(freePtr) free(ar); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
void __Autoarr_##type##_freeWithMembers(Autoarr_##type* ar, bool freePtr){ \
|
||||||
|
if(ktDescriptor_##type.freeMembers!=NULL) { \
|
||||||
|
Autoarr_foreach(ar, el, \
|
||||||
|
void* members_ptr=⪙ \
|
||||||
|
if(TYPE_IS_PTR) members_ptr=*(type**)members_ptr; \
|
||||||
|
ktDescriptor_##type.freeMembers(members_ptr); \
|
||||||
|
); \
|
||||||
|
} \
|
||||||
|
__Autoarr_##type##_freeWithoutMembers(ar, freePtr);\
|
||||||
|
} \
|
||||||
|
void ____Autoarr_##type##_freeWithMembers(void* ar){ \
|
||||||
|
__Autoarr_##type##_freeWithMembers((Autoarr_##type*)ar, false); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
type* __Autoarr_##type##_toArray(Autoarr_##type* ar){ \
|
||||||
u32 length=Autoarr_length(ar); \
|
u32 length=Autoarr_length(ar); \
|
||||||
if(length==0) \
|
if(length==0) \
|
||||||
return NULL; \
|
return NULL; \
|
||||||
TYPE* array=allocator_alloc(array_alloctr, length); \
|
type* array=malloc(length * sizeof(type)); \
|
||||||
Autoarr_foreach(ar, el, { \
|
for(u32 i=0; i<length; i++) \
|
||||||
array[el_i]=el; \
|
array[i]=__Autoarr_##type##_get(ar, i); \
|
||||||
}); \
|
|
||||||
return array; \
|
return array; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
__Autoarr_##TYPE##_functions_list_t __Autoarr_##TYPE##_functions_list={ \
|
__Autoarr_##type##_functions_list_t __Autoarr_##type##_functions_list={ \
|
||||||
&__Autoarr_##TYPE##_add, \
|
&__Autoarr_##type##_add, \
|
||||||
&__Autoarr_##TYPE##_get, \
|
&__Autoarr_##type##_get, \
|
||||||
&__Autoarr_##TYPE##_getPtr, \
|
&__Autoarr_##type##_getPtr, \
|
||||||
&__Autoarr_##TYPE##_set, \
|
&__Autoarr_##type##_set, \
|
||||||
&__Autoarr_##TYPE##_toArray \
|
&__Autoarr_##type##_freeWithMembers, \
|
||||||
|
&__Autoarr_##type##_freeWithoutMembers, \
|
||||||
|
&__Autoarr_##type##_toArray \
|
||||||
}; \
|
}; \
|
||||||
\
|
\
|
||||||
void __Autoarr_##TYPE##_construct(Autoarr_##TYPE* ar, alloc_size_t starting_size, allocator_ptr data_allocator){ \
|
Autoarr_##type* __Autoarr_##type##_create(u16 max_blocks_count, u16 max_block_length){ \
|
||||||
InternalAllocator_setExternalOrConstruct(ar, data_allocator, LinearAllocator, starting_size); \
|
Autoarr_##type* ar=malloc(sizeof(Autoarr_##type)); \
|
||||||
ar->functions=&__Autoarr_##TYPE##_functions_list; \
|
*ar=(Autoarr_##type){ \
|
||||||
ar->type = &ktDescriptor_name(TYPE); \
|
.max_blocks_count=max_blocks_count, \
|
||||||
ar->length=0; \
|
.blocks_count=0, \
|
||||||
} \
|
.max_block_length=max_block_length, \
|
||||||
\
|
.block_length=0, \
|
||||||
kt_define(Autoarr_##TYPE, (destruct_t)__Autoarr_##TYPE##_destruct, NULL);
|
.values=NULL, \
|
||||||
|
.functions=&__Autoarr_##type##_functions_list \
|
||||||
|
}; \
|
||||||
|
return ar; \
|
||||||
|
}
|
||||||
|
|
||||||
#if __cplusplus
|
#if __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,6 @@ bool DtsodV24_remove(Hashtable* dtsod, char* key){
|
|||||||
}
|
}
|
||||||
|
|
||||||
// frees memory including memory of elements (hashtables, autoarrs, etc.)
|
// frees memory including memory of elements (hashtables, autoarrs, etc.)
|
||||||
void DtsodV24_destruct(Hashtable* dtsod){
|
void DtsodV24_free(Hashtable* dtsod){
|
||||||
Hashtable_destruct(dtsod);
|
Hashtable_free(dtsod);
|
||||||
}
|
}
|
||||||
@@ -25,7 +25,7 @@ bool DtsodV24_contains(Hashtable* dtsod, char* key);
|
|||||||
bool DtsodV24_remove(Hashtable* dtsod, char* key);
|
bool DtsodV24_remove(Hashtable* dtsod, char* key);
|
||||||
|
|
||||||
// frees memory including memory of elements (hashtables, autoarrs, etc.)
|
// frees memory including memory of elements (hashtables, autoarrs, etc.)
|
||||||
void DtsodV24_destruct(Hashtable* dtsod);
|
void DtsodV24_free(Hashtable* dtsod);
|
||||||
|
|
||||||
#if __cplusplus
|
#if __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
#include "DtsodV24.h"
|
#include "DtsodV24.h"
|
||||||
#include "../String/StringBuilder.h"
|
#include "../String/StringBuilder.h"
|
||||||
|
|
||||||
#define ARR_SZ_START 64
|
#define ARR_BC 64
|
||||||
|
#define ARR_BL 1024
|
||||||
|
|
||||||
|
|
||||||
typedef struct DeserializeSharedData{
|
typedef struct DeserializeSharedData{
|
||||||
@@ -9,13 +10,11 @@ typedef struct DeserializeSharedData{
|
|||||||
char* sh_text;
|
char* sh_text;
|
||||||
bool sh_partOfDollarList;
|
bool sh_partOfDollarList;
|
||||||
bool sh_calledRecursively;
|
bool sh_calledRecursively;
|
||||||
allocator_ptr sh_tmp_al;
|
|
||||||
} DeserializeSharedData;
|
} DeserializeSharedData;
|
||||||
|
|
||||||
#define text shared->sh_text
|
#define text shared->sh_text
|
||||||
#define partOfDollarList shared->sh_partOfDollarList
|
#define partOfDollarList shared->sh_partOfDollarList
|
||||||
#define calledRecursively shared->sh_calledRecursively
|
#define calledRecursively shared->sh_calledRecursively
|
||||||
#define tmp_al shared->sh_tmp_al
|
|
||||||
|
|
||||||
|
|
||||||
// special func for throwing error messages about wrong characters in deserializing text
|
// special func for throwing error messages about wrong characters in deserializing text
|
||||||
@@ -45,7 +44,7 @@ Maybe ERROR_WRONGCHAR(const char c, char* _text, char* text_first, const char* s
|
|||||||
if(!_c) break;
|
if(!_c) break;
|
||||||
}
|
}
|
||||||
char errmsg[1024];
|
char errmsg[1024];
|
||||||
sprintf_s(errmsg, sizeof(errmsg), "unexpected <%c> at:\n"
|
ksprintf(errmsg,1024, "unexpected <%c> at:\n"
|
||||||
" \"%s\"\n"
|
" \"%s\"\n"
|
||||||
"\\___[%s:%d] %s()",
|
"\\___[%s:%d] %s()",
|
||||||
c,errBuf, srcfile,line,funcname);
|
c,errBuf, srcfile,line,funcname);
|
||||||
@@ -95,7 +94,7 @@ Maybe __ReadName(DeserializeSharedData* shared){
|
|||||||
safethrow_wrongchar(c,;);
|
safethrow_wrongchar(c,;);
|
||||||
return SUCCESS(UniHeapPtr(char,NULL));
|
return SUCCESS(UniHeapPtr(char,NULL));
|
||||||
case ':':
|
case ':':
|
||||||
return SUCCESS(UniHeapPtr(char,string_extract(tmp_al, nameStr)));
|
return SUCCESS(UniHeapPtr(char,string_extract(nameStr)));
|
||||||
case '$':
|
case '$':
|
||||||
if(nameStr.length!=0)
|
if(nameStr.length!=0)
|
||||||
safethrow_wrongchar(c,;);
|
safethrow_wrongchar(c,;);
|
||||||
@@ -112,7 +111,7 @@ Maybe __ReadName(DeserializeSharedData* shared){
|
|||||||
}
|
}
|
||||||
#define ReadName() __ReadName(shared)
|
#define ReadName() __ReadName(shared)
|
||||||
|
|
||||||
Maybe __deserialize(char** _text, bool _calledRecursively, allocator_ptr _tmp_al);
|
Maybe __deserialize(char** _text, bool _calledRecursively);
|
||||||
Maybe __ReadValue(DeserializeSharedData* shared, bool* readingList);
|
Maybe __ReadValue(DeserializeSharedData* shared, bool* readingList);
|
||||||
#define ReadValue(rL) __ReadValue(shared, rL)
|
#define ReadValue(rL) __ReadValue(shared, rL)
|
||||||
|
|
||||||
@@ -120,9 +119,7 @@ Maybe __ReadValue(DeserializeSharedData* shared, bool* readingList);
|
|||||||
Maybe __ReadString(DeserializeSharedData* shared){
|
Maybe __ReadString(DeserializeSharedData* shared){
|
||||||
char c;
|
char c;
|
||||||
bool prevIsBackslash=false;
|
bool prevIsBackslash=false;
|
||||||
StringBuilder _sb;
|
StringBuilder* b=StringBuilder_create();
|
||||||
StringBuilder* b=&_sb;
|
|
||||||
StringBuilder_construct(b, tmp_al);
|
|
||||||
|
|
||||||
while ((c=*++text)){
|
while ((c=*++text)){
|
||||||
if(c=='"') {
|
if(c=='"') {
|
||||||
@@ -143,25 +140,24 @@ Maybe __ReadString(DeserializeSharedData* shared){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
safethrow(ERR_ENDOFSTR, StringBuilder_destruct(b));
|
safethrow(ERR_ENDOFSTR, StringBuilder_free(b));
|
||||||
}
|
}
|
||||||
#define ReadString() __ReadString(shared)
|
#define ReadString() __ReadString(shared)
|
||||||
|
|
||||||
Maybe __ReadList(DeserializeSharedData* shared){
|
Maybe __ReadList(DeserializeSharedData* shared){
|
||||||
Autoarr(Unitype) list;
|
Autoarr(Unitype)* list=Autoarr_create(Unitype,ARR_BC,ARR_BL);
|
||||||
Autoarr_construct(&list, Unitype, ARR_SZ_START, NULL);
|
|
||||||
bool readingList=true;
|
bool readingList=true;
|
||||||
while (true){
|
while (true){
|
||||||
try(ReadValue((&readingList)), m_val, Autoarr_destruct(&list))
|
try(ReadValue((&readingList)), m_val, Autoarr_free(list, true))
|
||||||
Autoarr_add(&list, m_val.value);
|
Autoarr_add(list,m_val.value);
|
||||||
if (!readingList){
|
if (!readingList){
|
||||||
if(Unitype_isUniNull(m_val.value))
|
if(Unitype_isUniNull(m_val.value))
|
||||||
Autoarr_pop(&list);
|
Autoarr_pop(list);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return SUCCESS(UniHeapPtr(Autoarr_Unitype, &list));
|
return SUCCESS(UniHeapPtr(Autoarr_Unitype,list));
|
||||||
};
|
};
|
||||||
#define ReadList() __ReadList(shared)
|
#define ReadList() __ReadList(shared)
|
||||||
|
|
||||||
@@ -179,34 +175,34 @@ Maybe __ParseValue(DeserializeSharedData* shared, string str){
|
|||||||
else safethrow_wrongchar(*str.ptr,;);
|
else safethrow_wrongchar(*str.ptr,;);
|
||||||
// Float64
|
// Float64
|
||||||
case 'f': {
|
case 'f': {
|
||||||
char* _c=string_extract(tmp_al, str);
|
char* _c=string_extract(str);
|
||||||
Unitype rez=UniFloat64(strtod(_c,NULL));
|
Unitype rez=UniFloat64(strtod(_c,NULL));
|
||||||
// allocator_free(tmp_al,_c);
|
free(_c);
|
||||||
return SUCCESS(rez);
|
return SUCCESS(rez);
|
||||||
}
|
}
|
||||||
// UInt64
|
// UInt64
|
||||||
case 'u': {
|
case 'u': {
|
||||||
u64 lu=0;
|
u64 lu=0;
|
||||||
char* _c=string_extract(tmp_al, str);
|
char* _c=string_extract(str);
|
||||||
if(sscanf(_c, IFWIN("%llu", "%lu"), &lu)!=1){
|
if(sscanf(_c, IFWIN("%llu", "%lu"), &lu)!=1){
|
||||||
char err[64];
|
char err[64];
|
||||||
sprintf_s(err, sizeof(err), "can't parse to int: <%s>", _c);
|
ksprintf(err,64,"can't parse to int: <%s>",_c);
|
||||||
safethrow(err, /*allocator_free(tmp_al, _c)*/);
|
safethrow(err,free(_c));
|
||||||
}
|
}
|
||||||
// allocator_free(tmp_al, _c);
|
free(_c);
|
||||||
return SUCCESS(UniUInt64(lu));
|
return SUCCESS(UniUInt64(lu));
|
||||||
}
|
}
|
||||||
// Int64
|
// Int64
|
||||||
case '0': case '1': case '2': case '3': case '4':
|
case '0': case '1': case '2': case '3': case '4':
|
||||||
case '5': case '6': case '7': case '8': case '9': {
|
case '5': case '6': case '7': case '8': case '9': {
|
||||||
i64 li=0;
|
i64 li=0;
|
||||||
char* _c=string_extract(tmp_al, str);
|
char* _c=string_extract(str);
|
||||||
if(sscanf(_c, IFWIN("%lli", "%li"), &li)!=1){
|
if(sscanf(_c, IFWIN("%lli", "%li"), &li)!=1){
|
||||||
char err[64];
|
char err[64];
|
||||||
sprintf_s(err, sizeof(err),"can't parse to int: <%s>",_c);
|
ksprintf(err,64,"can't parse to int: <%s>",_c);
|
||||||
// safethrow(err,allocator_free(tmp_al, _c));
|
safethrow(err,free(_c));
|
||||||
}
|
}
|
||||||
// allocator_free(tmp_al, _c);
|
free(_c);
|
||||||
return SUCCESS(UniInt64(li));
|
return SUCCESS(UniInt64(li));
|
||||||
}
|
}
|
||||||
// wrong type
|
// wrong type
|
||||||
@@ -234,35 +230,35 @@ Maybe __ReadValue(DeserializeSharedData* shared, bool* readingList){
|
|||||||
case '=': case ':':
|
case '=': case ':':
|
||||||
case '}': case '$':
|
case '}': case '$':
|
||||||
case '\'':
|
case '\'':
|
||||||
safethrow_wrongchar(c,Unitype_destruct(&value));
|
safethrow_wrongchar(c,Unitype_free(value));
|
||||||
case '#':;
|
case '#':;
|
||||||
char _c=c;
|
char _c=c;
|
||||||
char* _text=text;
|
char* _text=text;
|
||||||
try(SkipComment(),_,;);
|
try(SkipComment(),_,;);
|
||||||
if(valueStr.length!=0){
|
if(valueStr.length!=0){
|
||||||
text=_text;
|
text=_text;
|
||||||
safethrow_wrongchar(_c,Unitype_destruct(&value));
|
safethrow_wrongchar(_c,Unitype_free(value));
|
||||||
}
|
}
|
||||||
valueStr.ptr=text+1; // skips '\n'
|
valueStr.ptr=text+1; // skips '\n'
|
||||||
break;
|
break;
|
||||||
case '"':
|
case '"':
|
||||||
if(valueStr.length!=0) safethrow_wrongchar(c,Unitype_destruct(&value));
|
if(valueStr.length!=0) safethrow_wrongchar(c,Unitype_free(value));
|
||||||
try(ReadString(),maybeString,;)
|
try(ReadString(),maybeString,;)
|
||||||
value=maybeString.value;
|
value=maybeString.value;
|
||||||
break;
|
break;
|
||||||
case '{':
|
case '{':
|
||||||
if(valueStr.length!=0) safethrow_wrongchar(c,Unitype_destruct(&value));
|
if(valueStr.length!=0) safethrow_wrongchar(c,Unitype_free(value));
|
||||||
++text; // skips '{'
|
++text; // skips '{'
|
||||||
try(__deserialize(&text,true,tmp_al), val, Unitype_destruct(&value))
|
try(__deserialize(&text,true), val,Unitype_free(value))
|
||||||
value=val.value;
|
value=val.value;
|
||||||
break;
|
break;
|
||||||
case '[':
|
case '[':
|
||||||
if(valueStr.length!=0) safethrow_wrongchar(c,Unitype_destruct(&value));
|
if(valueStr.length!=0) safethrow_wrongchar(c,Unitype_free(value));
|
||||||
try(ReadList(),maybeList,Unitype_destruct(&value))
|
try(ReadList(),maybeList,Unitype_free(value))
|
||||||
value=maybeList.value;
|
value=maybeList.value;
|
||||||
break;
|
break;
|
||||||
case ']':
|
case ']':
|
||||||
if(!readingList) safethrow_wrongchar(c,Unitype_destruct(&value));
|
if(!readingList) safethrow_wrongchar(c,Unitype_free(value));
|
||||||
*readingList=false;
|
*readingList=false;
|
||||||
goto return_value;
|
goto return_value;
|
||||||
case ';':
|
case ';':
|
||||||
@@ -270,14 +266,14 @@ Maybe __ReadValue(DeserializeSharedData* shared, bool* readingList){
|
|||||||
return_value:
|
return_value:
|
||||||
if(valueStr.length!=0){
|
if(valueStr.length!=0){
|
||||||
if(!Unitype_isUniNull(value))
|
if(!Unitype_isUniNull(value))
|
||||||
safethrow_wrongchar(c,Unitype_destruct(&value));
|
safethrow_wrongchar(c,Unitype_free(value));
|
||||||
try(ParseValue(valueStr),maybeParsed,;)
|
try(ParseValue(valueStr),maybeParsed,;)
|
||||||
value=maybeParsed.value;
|
value=maybeParsed.value;
|
||||||
}
|
}
|
||||||
return SUCCESS(value);
|
return SUCCESS(value);
|
||||||
default:
|
default:
|
||||||
if(spaceAfterVal)
|
if(spaceAfterVal)
|
||||||
safethrow_wrongchar(c,Unitype_destruct(&value));
|
safethrow_wrongchar(c,Unitype_free(value));
|
||||||
valueStr.length++;
|
valueStr.length++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -286,29 +282,25 @@ Maybe __ReadValue(DeserializeSharedData* shared, bool* readingList){
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Maybe __deserialize(char** _text, bool _calledRecursively, allocator_ptr _tmp_al) {
|
Maybe __deserialize(char** _text, bool _calledRecursively) {
|
||||||
DeserializeSharedData _shared={
|
DeserializeSharedData _shared={
|
||||||
.sh_text_first=*_text,
|
.sh_text_first=*_text,
|
||||||
.sh_text=*_text,
|
.sh_text=*_text,
|
||||||
.sh_partOfDollarList=false,
|
.sh_partOfDollarList=false,
|
||||||
.sh_calledRecursively=_calledRecursively,
|
.sh_calledRecursively=_calledRecursively
|
||||||
.sh_tmp_al=_tmp_al
|
|
||||||
};
|
};
|
||||||
DeserializeSharedData* shared=&_shared;
|
DeserializeSharedData* shared=&_shared;
|
||||||
Hashtable _dict;
|
Hashtable* dict=Hashtable_create();
|
||||||
Hashtable* dict = &_dict;
|
|
||||||
Hashtable_construct(dict, _tmp_al);
|
|
||||||
|
|
||||||
text--;
|
text--;
|
||||||
while(true){
|
while(true){
|
||||||
try(ReadName(), maybeName, Hashtable_destruct(dict))
|
try(ReadName(), maybeName, Hashtable_free(dict))
|
||||||
if(!maybeName.value.VoidPtr) // end of file or '}' in recursive call
|
if(!maybeName.value.VoidPtr) // end of file or '}' in recursive call
|
||||||
goto END;
|
goto END;
|
||||||
char* nameCPtr=maybeName.value.VoidPtr;
|
char* nameCPtr=maybeName.value.VoidPtr;
|
||||||
try(ReadValue(NULL), val, {
|
try(ReadValue(NULL), val, {
|
||||||
Hashtable_destruct(dict);
|
Hashtable_free(dict);
|
||||||
// do not use, free call order is incorrect
|
free(nameCPtr);
|
||||||
// allocator_free(tmp_al, nameCPtr);
|
|
||||||
}) {
|
}) {
|
||||||
if(partOfDollarList){
|
if(partOfDollarList){
|
||||||
partOfDollarList=false;
|
partOfDollarList=false;
|
||||||
@@ -318,12 +310,10 @@ Maybe __deserialize(char** _text, bool _calledRecursively, allocator_ptr _tmp_al
|
|||||||
list=(Autoarr(Unitype)*)lu.VoidPtr;
|
list=(Autoarr(Unitype)*)lu.VoidPtr;
|
||||||
// Key is not used in that case, because it is already added
|
// Key is not used in that case, because it is already added
|
||||||
// to the table with the first dollar list item.
|
// to the table with the first dollar list item.
|
||||||
// do not use, free call order is incorrect
|
free(nameCPtr);
|
||||||
// allocator_free(tmp_al, nameCPtr);
|
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
list=allocator_alloc(tmp_al, sizeof(*list));
|
list=Autoarr_create(Unitype,ARR_BC,ARR_BL);
|
||||||
Autoarr_construct(list, Unitype, ARR_SZ_START, NULL);
|
|
||||||
Hashtable_add(dict,nameCPtr,UniHeapPtr(Autoarr_Unitype,list));
|
Hashtable_add(dict,nameCPtr,UniHeapPtr(Autoarr_Unitype,list));
|
||||||
}
|
}
|
||||||
Autoarr_add(list,val.value);
|
Autoarr_add(list,val.value);
|
||||||
@@ -338,9 +328,5 @@ Maybe __deserialize(char** _text, bool _calledRecursively, allocator_ptr _tmp_al
|
|||||||
}
|
}
|
||||||
|
|
||||||
Maybe DtsodV24_deserialize(char* _text) {
|
Maybe DtsodV24_deserialize(char* _text) {
|
||||||
LinearAllocator _tmp_al;
|
return __deserialize(&_text, false);
|
||||||
LinearAllocator_construct(&_tmp_al, 1024);
|
|
||||||
Maybe m=__deserialize(&_text, false, (allocator_ptr)&_tmp_al);
|
|
||||||
LinearAllocator_destruct(&_tmp_al);
|
|
||||||
return m;
|
|
||||||
}
|
}
|
||||||
|
|||||||
62
src/DtsodParser/DtsodV24_exported.c
Normal file
62
src/DtsodParser/DtsodV24_exported.c
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
//
|
||||||
|
// I planned to export functions from DtsodV24.h,
|
||||||
|
// but C# P/Invoke can't get returned values for some reason.
|
||||||
|
// Following functions return values by pointer, which looks in C# like out parameter
|
||||||
|
//
|
||||||
|
|
||||||
|
#if __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "DtsodV24.h"
|
||||||
|
|
||||||
|
// parses text to binary values
|
||||||
|
EXPORT void CALL kerep_DtsodV24_deserialize(char* text, Hashtable** output, char** errmsg){
|
||||||
|
Maybe r=DtsodV24_deserialize(text);
|
||||||
|
*errmsg=r.errmsg;
|
||||||
|
*output=r.value.VoidPtr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// creates text representation of dtsod
|
||||||
|
EXPORT void CALL kerep_DtsodV24_serialize(Hashtable* dtsod, char** output, char** errmsg){
|
||||||
|
Maybe r=DtsodV24_serialize(dtsod);
|
||||||
|
*errmsg=r.errmsg;
|
||||||
|
*output=r.value.VoidPtr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns value or UniNull if key not found
|
||||||
|
EXPORT void CALL kerep_DtsodV24_get(Hashtable* dtsod, char* key, Unitype* output){
|
||||||
|
*output=DtsodV24_get(dtsod, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
// adds or sets the value
|
||||||
|
EXPORT void CALL kerep_DtsodV24_addOrSet(Hashtable* dtsod, char* key, Unitype value){
|
||||||
|
DtsodV24_addOrSet(dtsod, key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// checks for dtsod contains value or dont
|
||||||
|
EXPORT void CALL kerep_DtsodV24_contains(Hashtable* dtsod, char* key, bool* output){
|
||||||
|
*output=DtsodV24_contains(dtsod, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
// replaces value with UniNull if key exists in dtsod
|
||||||
|
EXPORT void CALL kerep_DtsodV24_remove(Hashtable* dtsod, char* key, bool* output){
|
||||||
|
*output=DtsodV24_remove(dtsod, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
// replaces value with UniNull if key exists in dtsod
|
||||||
|
EXPORT void CALL kerep_DtsodV24_free(Hashtable* dtsod){
|
||||||
|
DtsodV24_free(dtsod);
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORT void CALL kerep_DtsodV24_height(Hashtable* dtsod, u16* heigth){
|
||||||
|
*heigth=Hashtable_height(dtsod);
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORT void CALL kerep_DtsodV24_getrow(Hashtable* dtsod, u16 h, Autoarr_KVPair** row){
|
||||||
|
*row=dtsod->rows[h];
|
||||||
|
}
|
||||||
|
|
||||||
|
#if __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -123,13 +123,8 @@ Maybe __serialize(StringBuilder* _b, u8 _tabs, Hashtable* dtsod){
|
|||||||
}
|
}
|
||||||
|
|
||||||
Maybe DtsodV24_serialize(Hashtable* dtsod){
|
Maybe DtsodV24_serialize(Hashtable* dtsod){
|
||||||
LinearAllocator _al; allocator_ptr al=(allocator_ptr)&_al;
|
StringBuilder* sb=StringBuilder_create();
|
||||||
LinearAllocator_construct(&_al, 512);
|
try(__serialize(sb,0,dtsod),__, StringBuilder_free(sb));
|
||||||
StringBuilder _sb;
|
|
||||||
StringBuilder* sb=&_sb;
|
|
||||||
StringBuilder_construct(sb, al);
|
|
||||||
try(__serialize(sb,0,dtsod),__, StringBuilder_destruct(sb); LinearAllocator_destruct(&_al););
|
|
||||||
char* str=StringBuilder_build(sb).ptr;
|
char* str=StringBuilder_build(sb).ptr;
|
||||||
LinearAllocator_destruct(&_al);
|
|
||||||
return SUCCESS(UniHeapPtr(char, str));
|
return SUCCESS(UniHeapPtr(char, str));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,10 +26,9 @@ bool dir_exists(const char* path){
|
|||||||
Maybe dir_create(const char* path){
|
Maybe dir_create(const char* path){
|
||||||
if (dir_exists(path))
|
if (dir_exists(path))
|
||||||
return MaybeNull;
|
return MaybeNull;
|
||||||
LinearAllocator _al; LinearAllocator_construct(&_al, 128);
|
char* parentDir=path_parentDir(path);
|
||||||
allocator_ptr al=&_al.base;
|
|
||||||
char* parentDir=path_parentDir(al, path);
|
|
||||||
dir_create(parentDir);
|
dir_create(parentDir);
|
||||||
|
free(parentDir);
|
||||||
#if KFS_USE_WINDOWS_H
|
#if KFS_USE_WINDOWS_H
|
||||||
if(!CreateDirectory(path, NULL))
|
if(!CreateDirectory(path, NULL))
|
||||||
#else
|
#else
|
||||||
@@ -37,10 +36,10 @@ Maybe dir_create(const char* path){
|
|||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
char err[512];
|
char err[512];
|
||||||
sprintf_s(err, sizeof(err), "can't create dicectory <%s>", path);
|
ksprintf(err, 512, "can't create dicectory <%s>", path);
|
||||||
safethrow(err, LinearAllocator_destruct(&_al));
|
safethrow(err,;);
|
||||||
}
|
}
|
||||||
LinearAllocator_destruct(&_al);
|
|
||||||
return MaybeNull;
|
return MaybeNull;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,9 +2,9 @@
|
|||||||
#include "../String/StringBuilder.h"
|
#include "../String/StringBuilder.h"
|
||||||
#include "io_includes.h"
|
#include "io_includes.h"
|
||||||
|
|
||||||
void __file_destructMembers(void* _f){ fclose((FileHandle)_f); }
|
void __file_freeMembers(void* _f){ fclose((FileHandle)_f); }
|
||||||
|
|
||||||
kt_define(FileHandle, __file_destructMembers, NULL)
|
kt_define(FileHandle, __file_freeMembers, NULL)
|
||||||
|
|
||||||
bool file_exists(const char* path){
|
bool file_exists(const char* path){
|
||||||
if(path[0]=='.'){
|
if(path[0]=='.'){
|
||||||
@@ -50,11 +50,8 @@ char* FileOpenMode_toStr(FileOpenMode m){
|
|||||||
|
|
||||||
Maybe file_open(const char* path, FileOpenMode mode){
|
Maybe file_open(const char* path, FileOpenMode mode){
|
||||||
FileHandle file=fopen(path, FileOpenMode_toStr(mode));
|
FileHandle file=fopen(path, FileOpenMode_toStr(mode));
|
||||||
LinearAllocator _al; LinearAllocator_construct(&_al, 128);
|
|
||||||
allocator_ptr al=&_al.base;
|
|
||||||
if(!file)
|
if(!file)
|
||||||
safethrow(cptr_concat(al, "can't open file ", (char*)path), LinearAllocator_destruct(&_al));
|
safethrow(cptr_concat("can't open file ", (char*)path),;);
|
||||||
LinearAllocator_destruct(&_al);
|
|
||||||
return SUCCESS(UniHeapPtr(FileHandle,file));
|
return SUCCESS(UniHeapPtr(FileHandle,file));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,66 +64,64 @@ Maybe file_close(FileHandle file){
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define ioWriteCheck() \
|
#define ioWriteCheck() \
|
||||||
if(rezult==EOF) \
|
if(result==EOF) \
|
||||||
safethrow(ERR_IO_EOF,;); \
|
safethrow(ERR_IO_EOF,;); \
|
||||||
if(rezult!=0) \
|
if(result!=0) \
|
||||||
safethrow(ERR_IO,;);
|
safethrow(ERR_IO,;);
|
||||||
|
|
||||||
Maybe file_writeChar(FileHandle file, char byte){
|
Maybe file_writeChar(FileHandle file, char byte){
|
||||||
i32 rezult=fputc(byte, file);
|
i32 result=fputc(byte, file);
|
||||||
ioWriteCheck();
|
ioWriteCheck();
|
||||||
return MaybeNull;
|
return MaybeNull;
|
||||||
}
|
}
|
||||||
|
|
||||||
Maybe file_writeBuffer(FileHandle file, char* buffer, u64 length){
|
Maybe file_writeBuffer(FileHandle file, char* buffer, u64 length){
|
||||||
i32 rezult=0;
|
i32 result=0;
|
||||||
for(u64 i=0; i<length && !rezult; i++)
|
for(u64 i=0; i<length && !result; i++)
|
||||||
rezult=fputc(buffer[i], file);
|
result=fputc(buffer[i], file);
|
||||||
ioWriteCheck();
|
ioWriteCheck();
|
||||||
return MaybeNull;
|
return MaybeNull;
|
||||||
}
|
}
|
||||||
|
|
||||||
Maybe file_writeCptr(FileHandle file, char* cptr){
|
Maybe file_writeCptr(FileHandle file, char* cptr){
|
||||||
i32 rezult=fputs(cptr, file);
|
i32 result=fputs(cptr, file);
|
||||||
ioWriteCheck();
|
ioWriteCheck();
|
||||||
return MaybeNull;
|
return MaybeNull;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Maybe file_readChar(FileHandle file){
|
Maybe file_readChar(FileHandle file){
|
||||||
i32 rezult=fgetc(file);
|
i32 result=fgetc(file);
|
||||||
if(feof(file)) safethrow(ERR_IO_EOF,;);
|
if(feof(file)) safethrow(ERR_IO_EOF,;);
|
||||||
if(ferror(file)) safethrow(ERR_IO,;);
|
if(ferror(file)) safethrow(ERR_IO,;);
|
||||||
return SUCCESS(UniUInt64(rezult));
|
return SUCCESS(UniUInt64(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
Maybe file_readBuffer(FileHandle file, char* buffer, u64 length){
|
Maybe file_readBuffer(FileHandle file, char* buffer, u64 length){
|
||||||
i32 rezult=0;
|
i32 result=0;
|
||||||
u64 i=0;
|
u64 i=0;
|
||||||
for(; i<length && rezult!=EOF; i++){
|
for(; i<length && result!=EOF; i++){
|
||||||
rezult=fgetc(file);
|
result=fgetc(file);
|
||||||
buffer[i]=(char)rezult;
|
buffer[i]=(char)result;
|
||||||
}
|
}
|
||||||
if(ferror(file)) safethrow(ERR_IO,;);
|
if(ferror(file)) safethrow(ERR_IO,;);
|
||||||
return SUCCESS(UniUInt64(i));
|
return SUCCESS(UniUInt64(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
Maybe file_readAll(FileHandle file, char** allBytes){
|
Maybe file_readAll(FileHandle file, char** allBytes){
|
||||||
i32 rezult=0;
|
i32 result=0;
|
||||||
char buffer[256];
|
char buffer[256];
|
||||||
string bufStr={.ptr=buffer, .length=sizeof(buffer)};
|
string bufStr={.ptr=buffer, .length=sizeof(buffer)};
|
||||||
StringBuilder _sb;
|
StringBuilder* sb=StringBuilder_create();
|
||||||
StringBuilder* sb=&_sb;
|
|
||||||
StringBuilder_construct(sb, NULL);
|
|
||||||
u64 i=0;
|
u64 i=0;
|
||||||
while(true){
|
while(true){
|
||||||
rezult=fgetc(file);
|
result=fgetc(file);
|
||||||
if(rezult==EOF){
|
if(result==EOF){
|
||||||
if(ferror(file))
|
if(ferror(file))
|
||||||
safethrow(ERR_IO, StringBuilder_destruct(sb));
|
safethrow(ERR_IO, StringBuilder_free(sb));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
buffer[i%sizeof(buffer)]=(char)rezult;
|
buffer[i%sizeof(buffer)]=(char)result;
|
||||||
i++;
|
i++;
|
||||||
if(!(i%sizeof(buffer)))
|
if(!(i%sizeof(buffer)))
|
||||||
StringBuilder_append_string(sb,bufStr);
|
StringBuilder_append_string(sb,bufStr);
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "../base/base.h"
|
#include "../base/base.h"
|
||||||
|
#include "../Array/Array.h"
|
||||||
#include "../String/string.h"
|
#include "../String/string.h"
|
||||||
|
|
||||||
typedef FILE* FileHandle;
|
typedef FILE* FileHandle;
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
#include "filesystem.h"
|
#include "filesystem.h"
|
||||||
|
|
||||||
char* __path_concat(allocator_ptr al, u32 n, ...){
|
char* __path_concat(u32 n, ...){
|
||||||
char** parts=(char**)allocator_alloc(al, n*sizeof(char*));
|
char** parts=(char**)malloc(n*sizeof(char*));
|
||||||
u32* lengths=allocator_alloc(al, n*sizeof(u32));
|
u32* lengths=malloc(n*sizeof(u32));
|
||||||
u32 totalLength=0;
|
u32 totalLength=0;
|
||||||
|
|
||||||
// reading args from va_list
|
// reading args from va_list
|
||||||
@@ -18,11 +18,11 @@ char* __path_concat(allocator_ptr al, u32 n, ...){
|
|||||||
va_end(vl);
|
va_end(vl);
|
||||||
|
|
||||||
// allocating memory for output value
|
// allocating memory for output value
|
||||||
char* totality=allocator_alloc(al, totalLength+1);
|
char* totality=malloc(totalLength+1);
|
||||||
const char* output=totality;
|
const char* output=totality;
|
||||||
totality[totalLength]=0;
|
totality[totalLength]=0;
|
||||||
|
|
||||||
// copying content of all strings to rezult
|
// copying content of all strings to result
|
||||||
u16 k=0;
|
u16 k=0;
|
||||||
for(; k<n-1; k++){
|
for(; k<n-1; k++){
|
||||||
memcpy(totality, parts[k], lengths[k]);
|
memcpy(totality, parts[k], lengths[k]);
|
||||||
@@ -32,13 +32,13 @@ char* __path_concat(allocator_ptr al, u32 n, ...){
|
|||||||
}
|
}
|
||||||
memcpy(totality, parts[k], lengths[k]);
|
memcpy(totality, parts[k], lengths[k]);
|
||||||
|
|
||||||
allocator_free(al, lengths);
|
free(parts);
|
||||||
allocator_free(al, parts);
|
free(lengths);
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* path_fixSeparators(allocator_ptr al, const char* path){
|
char* path_fixSeparators(const char* path){
|
||||||
char* pathCopy=cptr_copy(al, path);
|
char* pathCopy=cptr_copy(path);
|
||||||
char c;
|
char c;
|
||||||
while((c=*pathCopy)){
|
while((c=*pathCopy)){
|
||||||
if(c==path_notSep)
|
if(c==path_notSep)
|
||||||
@@ -49,17 +49,13 @@ char* path_fixSeparators(allocator_ptr al, const char* path){
|
|||||||
}
|
}
|
||||||
|
|
||||||
Maybe path_throwIfEscapes(const char* path){
|
Maybe path_throwIfEscapes(const char* path){
|
||||||
LinearAllocator _al; LinearAllocator_construct(&_al, 128);
|
|
||||||
allocator_ptr al=&_al.base;
|
|
||||||
if(cptr_contains(path,".."))
|
if(cptr_contains(path,".."))
|
||||||
safethrow(cptr_concat(al, "path <",path,"> uses <..>, that's not allowed"),
|
safethrow(cptr_concat("path <",path,"> uses <..>, that's not allowed"),);
|
||||||
LinearAllocator_destruct(&_al));
|
|
||||||
LinearAllocator_destruct(&_al);
|
|
||||||
return MaybeNull;
|
return MaybeNull;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* path_parentDir(allocator_ptr al, char* dir){
|
char* path_parentDir(char* dir){
|
||||||
char* copy=cptr_copy(al, dir);
|
char* copy=cptr_copy(dir);
|
||||||
i32 length=cptr_length(copy);
|
i32 length=cptr_length(copy);
|
||||||
i32 i=cptr_lastIndexOfChar(copy,path_sep);
|
i32 i=cptr_lastIndexOfChar(copy,path_sep);
|
||||||
if(i!=-1 && i==length-1){
|
if(i!=-1 && i==length-1){
|
||||||
@@ -67,8 +63,8 @@ char* path_parentDir(allocator_ptr al, char* dir){
|
|||||||
i=cptr_lastIndexOfChar(copy,path_sep);
|
i=cptr_lastIndexOfChar(copy,path_sep);
|
||||||
}
|
}
|
||||||
if(i==-1){
|
if(i==-1){
|
||||||
allocator_free(al, copy);
|
free(copy);
|
||||||
copy=allocator_alloc(al, 2);
|
copy=malloc(2);
|
||||||
copy[0]='.';
|
copy[0]='.';
|
||||||
copy[1]=0;
|
copy[1]=0;
|
||||||
}
|
}
|
||||||
@@ -76,13 +72,13 @@ char* path_parentDir(allocator_ptr al, char* dir){
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
char* path_basename(allocator_ptr al, char* path, bool with_extension){
|
char* path_basename(char* path, bool with_extension){
|
||||||
i32 nameIndex=cptr_lastIndexOfChar(path, path_sep)+1;
|
i32 nameIndex=cptr_lastIndexOfChar(path, path_sep)+1;
|
||||||
string rezult=string_fromCptr(path+nameIndex);
|
string result=string_fromCptr(path+nameIndex);
|
||||||
if(!with_extension){
|
if(!with_extension){
|
||||||
i32 extIndex=cptr_lastIndexOfChar(rezult.ptr, '.');
|
i32 extIndex=cptr_lastIndexOfChar(result.ptr, '.');
|
||||||
if(extIndex!=0 && extIndex!=-1)
|
if(extIndex!=0 && extIndex!=-1)
|
||||||
rezult.length=extIndex;
|
result.length=extIndex;
|
||||||
}
|
}
|
||||||
return string_extract(al, rezult);
|
return string_extract(result);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,17 +14,17 @@ static const char path_sep='/';
|
|||||||
static const char path_notSep='\\';
|
static const char path_notSep='\\';
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
char* __path_concat(allocator_ptr al, u32 n, ...);
|
char* __path_concat(u32 n, ...);
|
||||||
/// @brief merges path parts together and puts <path_sep> between them
|
/// @brief merges path parts together and puts <path_sep> between them
|
||||||
/// @return new cstr
|
/// @return new cstr
|
||||||
#define path_concat(ALLOCATOR, PATH_PARTS...) __path_concat(ALLOCATOR, count_args(PATH_PARTS), PATH_PARTS)
|
#define path_concat(PATH_PARTS...) __path_concat(count_args(PATH_PARTS), PATH_PARTS)
|
||||||
|
|
||||||
/// @brief fixes path separators
|
/// @brief fixes path separators
|
||||||
/// @param cstr where can be <path_notSep>
|
/// @param cstr where can be <path_notSep>
|
||||||
/// @return new cstr with correct separators
|
/// @return new cstr with correct separators
|
||||||
char* path_fixSeparators(allocator_ptr al, const char* path);
|
char* path_fixSeparators(const char* path);
|
||||||
|
|
||||||
#define path_resolve(ALLOCATOR, PATH_PARTS...) path_fixSeparators(ALLOCATOR, path_concat(ALLOCATOR, PATH_PARTS))
|
#define path_resolve(PATH_PARTS...) path_fixSeparators(path_concat(PATH_PARTS))
|
||||||
|
|
||||||
/// @brief calls safethrow() if finds escape sequense in path
|
/// @brief calls safethrow() if finds escape sequense in path
|
||||||
/// @param path cstr where can be <..>
|
/// @param path cstr where can be <..>
|
||||||
@@ -32,10 +32,10 @@ char* path_fixSeparators(allocator_ptr al, const char* path);
|
|||||||
Maybe path_throwIfEscapes(const char* path);
|
Maybe path_throwIfEscapes(const char* path);
|
||||||
|
|
||||||
///@return path of parent dir
|
///@return path of parent dir
|
||||||
char* path_parentDir(allocator_ptr al, char* path);
|
char* path_parentDir(char* path);
|
||||||
|
|
||||||
///@return file name
|
///@return file name
|
||||||
char* path_basename(allocator_ptr al, char* path, bool with_extension);
|
char* path_basename(char* path, bool with_extension);
|
||||||
|
|
||||||
#if __cplusplus
|
#if __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,70 +1,74 @@
|
|||||||
#include "Hashtable.h"
|
#include "Hashtable.h"
|
||||||
|
|
||||||
kt_define(Hashtable, __Hashtable_destruct, NULL);
|
kt_define(Hashtable, __Hashtable_free, NULL);
|
||||||
|
|
||||||
// amount of rows
|
// amount of rows
|
||||||
static const u16 HT_HEIGHTS[]={17,61,257,1021,4099,16381,65521};
|
static const u16 HT_HEIGHTS[]={17,61,257,1021,4099,16381,65521};
|
||||||
#define HT_HEIN_MIN 0
|
#define HT_HEIN_MIN 0
|
||||||
#define HT_HEIN_MAX 6
|
#define HT_HEIN_MAX 6
|
||||||
|
|
||||||
#define ARR_SIZE_MAX 16
|
#define ARR_BC 2
|
||||||
|
#define ARR_BL 8
|
||||||
|
|
||||||
void Hashtable_construct(Hashtable* ht, allocator_ptr external_al){
|
Hashtable* Hashtable_create(){
|
||||||
InternalAllocator_setExternalOrConstruct(ht, external_al, LinearAllocator, 1024);
|
Hashtable* ht=malloc(sizeof(Hashtable));
|
||||||
ht->hein=HT_HEIN_MIN;
|
ht->hein=HT_HEIN_MIN;
|
||||||
ht->rows=malloc(HT_HEIGHTS[HT_HEIN_MIN]*sizeof(Autoarr(KVPair)*));
|
ht->rows=malloc(HT_HEIGHTS[HT_HEIN_MIN]*sizeof(Autoarr(KVPair)*));
|
||||||
allocator_ptr internal_al = InternalAllocator_getPtr(ht);
|
for(u16 i=0;i<HT_HEIGHTS[HT_HEIN_MIN];i++)
|
||||||
for(u16 i=0; i<HT_HEIGHTS[HT_HEIN_MIN]; i++)
|
ht->rows[i]=Autoarr_create(KVPair,ARR_BC,ARR_BL);
|
||||||
Autoarr_construct(&ht->rows[i], KVPair, 16, internal_al);
|
return ht;
|
||||||
}
|
}
|
||||||
|
|
||||||
u16 __Hashtable_height(Hashtable* ht) { return HT_HEIGHTS[ht->hein]; }
|
void __Hashtable_free(void* _ht){
|
||||||
|
|
||||||
void __Hashtable_destruct(void* _ht){
|
|
||||||
Hashtable* ht=_ht;
|
Hashtable* ht=_ht;
|
||||||
for(u16 i=0;i<HT_HEIGHTS[ht->hein];i++)
|
for(u16 i=0;i<HT_HEIGHTS[ht->hein];i++)
|
||||||
Autoarr_destruct(&ht->rows[i]);
|
Autoarr_free(ht->rows[i], true);
|
||||||
allocator_free(InternalAllocator_getPtr(ht), ht->rows);
|
free(ht->rows);
|
||||||
InternalAllocator_destructIfInternal(LinearAllocator, ht);
|
|
||||||
}
|
}
|
||||||
void Hashtable_destruct(Hashtable* ht){
|
void Hashtable_free(Hashtable* ht){
|
||||||
__Hashtable_destruct(ht);
|
__Hashtable_free(ht);
|
||||||
|
free(ht);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u16 Hashtable_height(Hashtable* ht) { return HT_HEIGHTS[ht->hein]; }
|
||||||
|
|
||||||
|
|
||||||
void Hashtable_expand(Hashtable* ht){
|
void Hashtable_expand(Hashtable* ht){
|
||||||
if(ht->hein>=HT_HEIN_MAX) throw(ERR_MAXLENGTH);
|
if(ht->hein>=HT_HEIN_MAX) throw(ERR_MAXLENGTH);
|
||||||
|
|
||||||
Autoarr(KVPair)* newrows=malloc(HT_HEIGHTS[++ht->hein]*sizeof(Autoarr(KVPair)*));
|
Autoarr(KVPair)** newrows=malloc(HT_HEIGHTS[++ht->hein]*sizeof(Autoarr(KVPair)*));
|
||||||
for(u16 i=0;i<HT_HEIGHTS[ht->hein];i++)
|
for(u16 i=0;i<HT_HEIGHTS[ht->hein];i++)
|
||||||
Autoarr_construct(&newrows[i], KVPair, ARR_SIZE_MAX, InternalAllocator_getPtr(ht));
|
newrows[i]=Autoarr_create(KVPair,ARR_BC,ARR_BL);
|
||||||
|
|
||||||
for(u16 i=0;i<HT_HEIGHTS[ht->hein-1];i++){
|
for(u16 i=0;i<HT_HEIGHTS[ht->hein-1];i++){
|
||||||
Autoarr(KVPair)* ar=&ht->rows[i];
|
Autoarr(KVPair)* ar=ht->rows[i];
|
||||||
u32 arlen=Autoarr_length(ar);
|
u32 arlen=Autoarr_length(ar);
|
||||||
for(u32 k=0;k<arlen;k++){
|
for(u32 k=0;k<arlen;k++){
|
||||||
KVPair p=Autoarr_get(ar,k);
|
KVPair p=Autoarr_get(ar,k);
|
||||||
u16 newrown=hashs(hash_sdbm32, p.key)%HT_HEIGHTS[ht->hein];
|
u16 newrown=hashs(hash_sdbm32, p.key)%HT_HEIGHTS[ht->hein];
|
||||||
Autoarr(KVPair)* newar=&newrows[newrown];
|
Autoarr(KVPair)* newar=newrows[newrown];
|
||||||
Autoarr_add(newar,p);
|
Autoarr_add(newar,p);
|
||||||
}
|
}
|
||||||
Autoarr_destruct(ar);
|
// there is no need to free array values, because they are copied into new array
|
||||||
|
// so dont replace this incorrect auto-generated function
|
||||||
|
Autoarr_freeWithoutMembers(ar, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(ht->rows);
|
free(ht->rows);
|
||||||
ht->rows = newrows;
|
ht->rows=newrows;
|
||||||
}
|
}
|
||||||
|
|
||||||
Autoarr(KVPair)* getrow(Hashtable* ht, char* key, bool can_expand){
|
Autoarr(KVPair)* getrow(Hashtable* ht, char* key, bool can_expand){
|
||||||
u32 hash=hashs(hash_sdbm32, key);
|
u32 hash=hashs(hash_sdbm32, key);
|
||||||
Autoarr(KVPair)* ar=&ht->rows[hash%HT_HEIGHTS[ht->hein]];
|
Autoarr(KVPair)* ar=ht->rows[hash%HT_HEIGHTS[ht->hein]];
|
||||||
if(can_expand && Autoarr_length(ar) == ARR_SIZE_MAX)
|
if(can_expand && Autoarr_length(ar)==Autoarr_max_length(ar))
|
||||||
Hashtable_expand(ht);
|
Hashtable_expand(ht);
|
||||||
ar=&ht->rows[hash%HT_HEIGHTS[ht->hein]];
|
ar=ht->rows[hash%HT_HEIGHTS[ht->hein]];
|
||||||
return ar;
|
return ar;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @param key must be heap allocated
|
/// @param key must be heap allocated
|
||||||
/// Hashtable_destruct will free this pointer
|
/// Hashtable_free will free this pointer
|
||||||
void Hashtable_add(Hashtable* ht, char* key, Unitype u){
|
void Hashtable_add(Hashtable* ht, char* key, Unitype u){
|
||||||
KVPair p={ .key=key, .value=u };
|
KVPair p={ .key=key, .value=u };
|
||||||
Autoarr_add(getrow(ht,key,true),p);
|
Autoarr_add(getrow(ht,key,true),p);
|
||||||
@@ -82,8 +86,7 @@ Unitype* Hashtable_getPtr(Hashtable* ht, char* key){
|
|||||||
u32 arlen=Autoarr_length(ar);
|
u32 arlen=Autoarr_length(ar);
|
||||||
for(u32 i=0;i<arlen;i++){
|
for(u32 i=0;i<arlen;i++){
|
||||||
KVPair* p=Autoarr_getPtr(ar,i);
|
KVPair* p=Autoarr_getPtr(ar,i);
|
||||||
if(cptr_equals(key,p->key))
|
if(cptr_equals(key,p->key)) return &p->value;
|
||||||
return &p->value;
|
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -93,8 +96,7 @@ Unitype Hashtable_get(Hashtable* ht, char* key){
|
|||||||
u32 arlen=Autoarr_length(ar);
|
u32 arlen=Autoarr_length(ar);
|
||||||
for(u32 i=0;i<arlen;i++){
|
for(u32 i=0;i<arlen;i++){
|
||||||
KVPair p=Autoarr_get(ar,i);
|
KVPair p=Autoarr_get(ar,i);
|
||||||
if(cptr_equals(key,p.key))
|
if(cptr_equals(key,p.key)) return p.value;
|
||||||
return p.value;
|
|
||||||
}
|
}
|
||||||
return UniNull;
|
return UniNull;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,14 +9,16 @@ extern "C" {
|
|||||||
#include "KeyValuePair.h"
|
#include "KeyValuePair.h"
|
||||||
|
|
||||||
STRUCT(Hashtable,
|
STRUCT(Hashtable,
|
||||||
InternalAllocator_declare(LinearAllocator);
|
|
||||||
u8 hein; // height=HT_HEIGHTS[hein]
|
u8 hein; // height=HT_HEIGHTS[hein]
|
||||||
Autoarr(KVPair)* rows; // Autoarr[height]
|
Autoarr(KVPair)** rows; // Autoarr[height]
|
||||||
)
|
)
|
||||||
|
|
||||||
void Hashtable_construct(Hashtable* ht, allocator_ptr external_al);
|
Hashtable* Hashtable_create();
|
||||||
void Hashtable_destruct(Hashtable* ht);
|
void Hashtable_free(Hashtable* ht);
|
||||||
void __Hashtable_destruct(void* ht);
|
void __Hashtable_free(void* ht);
|
||||||
|
|
||||||
|
// amount of rows
|
||||||
|
u16 Hashtable_height(Hashtable* ht);
|
||||||
|
|
||||||
// don't add pairs with the same keys,
|
// don't add pairs with the same keys,
|
||||||
// or something weird will happen
|
// or something weird will happen
|
||||||
@@ -34,13 +36,11 @@ Unitype* Hashtable_getPtr(Hashtable* ht, char* key);
|
|||||||
Unitype Hashtable_get(Hashtable* ht, char* key);
|
Unitype Hashtable_get(Hashtable* ht, char* key);
|
||||||
bool Hashtable_tryGet(Hashtable* ht, char* key, Unitype* output);
|
bool Hashtable_tryGet(Hashtable* ht, char* key, Unitype* output);
|
||||||
|
|
||||||
u16 __Hashtable_height(Hashtable* ht);
|
|
||||||
|
|
||||||
#define Hashtable_foreach(HT, EL, codeblock...) { \
|
#define Hashtable_foreach(HT, EL, codeblock...) { \
|
||||||
u16 hmax=__Hashtable_height(HT); \
|
u16 hmax=Hashtable_height(HT); \
|
||||||
for(u16 h=0; h<hmax; h++){ \
|
for(u16 h=0; h<hmax; h++){ \
|
||||||
Autoarr(KVPair)* row=&HT->rows[h]; \
|
Autoarr(KVPair)* AR=HT->rows[h]; \
|
||||||
Autoarr_foreach(row, EL, codeblock); \
|
Autoarr_foreach(AR, EL, codeblock); \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,15 @@
|
|||||||
#include "KeyValuePair.h"
|
#include "KeyValuePair.h"
|
||||||
|
|
||||||
kt_define(KVPair, NULL, NULL);
|
kt_define(KVPair, __KVPair_free, NULL);
|
||||||
|
|
||||||
Autoarr_define(KVPair)
|
Autoarr_define(KVPair, false)
|
||||||
|
|
||||||
|
// proper way to clean a KVP
|
||||||
|
void KVPair_free(KVPair p){
|
||||||
|
free(p.key);
|
||||||
|
Unitype_free(p.value);
|
||||||
|
}
|
||||||
|
void __KVPair_free(void* p){ KVPair_free(*(KVPair*)p); }
|
||||||
|
|
||||||
void printkvp(KVPair p){
|
void printkvp(KVPair p){
|
||||||
kprintf("{\"%s\", ",p.key);
|
kprintf("{\"%s\", ",p.key);
|
||||||
|
|||||||
@@ -14,7 +14,9 @@ STRUCT(KVPair,
|
|||||||
|
|
||||||
Autoarr_declare(KVPair)
|
Autoarr_declare(KVPair)
|
||||||
|
|
||||||
void __KVPair_destruct(void* p);
|
// proper way to clean a KVP
|
||||||
|
void KVPair_free(KVPair p);
|
||||||
|
void __KVPair_free(void* p);
|
||||||
|
|
||||||
void printkvp(KVPair p);
|
void printkvp(KVPair p);
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ extern "C" {
|
|||||||
#define LLNode_create(TYPE, VALUE) LLNode_##TYPE##_create(VALUE)
|
#define LLNode_create(TYPE, VALUE) LLNode_##TYPE##_create(VALUE)
|
||||||
|
|
||||||
#define LinkedList_create(TYPE) LinkedList_##TYPE##_create()
|
#define LinkedList_create(TYPE) LinkedList_##TYPE##_create()
|
||||||
#define LinkedList_destruct(LLIST) ({ LLIST->_functions->destruct(LLIST); free(LLIST); })
|
#define LinkedList_free(LLIST) ({ LLIST->_functions->freeMembers(LLIST); free(LLIST); })
|
||||||
|
|
||||||
|
|
||||||
void LinkedList_addToBeginning(void* _llist, void* _new_node);
|
void LinkedList_addToBeginning(void* _llist, void* _new_node);
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ STRUCT(LLNode(TYPE), \
|
|||||||
) \
|
) \
|
||||||
\
|
\
|
||||||
LLNode(TYPE)* LLNode_##TYPE##_create(TYPE value); \
|
LLNode(TYPE)* LLNode_##TYPE##_create(TYPE value); \
|
||||||
void LLNode_##TYPE##_destruct(LLNode(TYPE)* node, bool free_value);
|
void LLNode_##TYPE##_free(LLNode(TYPE)* node, bool free_value);
|
||||||
|
|
||||||
|
|
||||||
#define LinkedList_declare(TYPE)\
|
#define LinkedList_declare(TYPE)\
|
||||||
@@ -27,7 +27,7 @@ STRUCT(LinkedList(TYPE), \
|
|||||||
) \
|
) \
|
||||||
\
|
\
|
||||||
typedef struct LinkedList_##TYPE##_functions_t { \
|
typedef struct LinkedList_##TYPE##_functions_t { \
|
||||||
destruct_t destruct; \
|
freeMembers_t freeMembers; \
|
||||||
void (*removePrev)(LinkedList(TYPE)* llist, LLNode(TYPE)* nextNode, bool freeRemoved); \
|
void (*removePrev)(LinkedList(TYPE)* llist, LLNode(TYPE)* nextNode, bool freeRemoved); \
|
||||||
void (*removeNext)(LinkedList(TYPE)* llist, LLNode(TYPE)* prevNode, bool freeRemoved); \
|
void (*removeNext)(LinkedList(TYPE)* llist, LLNode(TYPE)* prevNode, bool freeRemoved); \
|
||||||
} LinkedList_##TYPE##_functions_t; \
|
} LinkedList_##TYPE##_functions_t; \
|
||||||
|
|||||||
@@ -14,19 +14,19 @@ LLNode(TYPE)* LLNode_##TYPE##_create(TYPE value){ \
|
|||||||
return node; \
|
return node; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
void LLNode_##TYPE##_destructMembers(void* _node){ \
|
void LLNode_##TYPE##_freeMembers(void* _node){ \
|
||||||
LLNode(TYPE)* node=(LLNode(TYPE)*)_node; \
|
LLNode(TYPE)* node=(LLNode(TYPE)*)_node; \
|
||||||
void* value_ptr=&node->value; \
|
void* value_ptr=&node->value; \
|
||||||
if(TYPE_IS_PTR) value_ptr=*(TYPE**)value_ptr; \
|
if(TYPE_IS_PTR) value_ptr=*(TYPE**)value_ptr; \
|
||||||
ktDescriptor_##TYPE.destruct(value_ptr); \
|
ktDescriptor_##TYPE.freeMembers(value_ptr); \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
void LLNode_##TYPE##_destruct(LLNode(TYPE)* node, bool free_value){ \
|
void LLNode_##TYPE##_free(LLNode(TYPE)* node, bool free_value){ \
|
||||||
if(free_value) LLNode_##TYPE##_destructMembers(node); \
|
if(free_value) LLNode_##TYPE##_freeMembers(node); \
|
||||||
free(node); \
|
free(node); \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
kt_define(LLNode_##TYPE, LLNode_##TYPE##_destructMembers, NULL)
|
kt_define(LLNode_##TYPE, LLNode_##TYPE##_freeMembers, NULL)
|
||||||
|
|
||||||
|
|
||||||
#define LinkedList_define(TYPE, VALUE_IS_PTR)\
|
#define LinkedList_define(TYPE, VALUE_IS_PTR)\
|
||||||
@@ -41,10 +41,10 @@ LinkedList(TYPE)* LinkedList_##TYPE##_create(){ \
|
|||||||
return l; \
|
return l; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
void LinkedList_##TYPE##_destructMembers(void* _l){ \
|
void LinkedList_##TYPE##_freeMembers(void* _l){ \
|
||||||
LinkedList(TYPE)* l=(LinkedList(TYPE)*)_l; \
|
LinkedList(TYPE)* l=(LinkedList(TYPE)*)_l; \
|
||||||
if(l->first_node!=NULL) \
|
if(l->first_node!=NULL) \
|
||||||
LinkedList_foreach(l, node, LLNode_##TYPE##_destruct(node, true)); \
|
LinkedList_foreach(l, node, LLNode_##TYPE##_free(node, true)); \
|
||||||
l->first_node=NULL; l->last_node=NULL; l->count=0; \
|
l->first_node=NULL; l->last_node=NULL; l->count=0; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
@@ -55,7 +55,7 @@ void LinkedList_##TYPE##_removePrev(LinkedList(TYPE)* llist, LLNode(TYPE)* nextN
|
|||||||
nextNode->prev=prevNode; \
|
nextNode->prev=prevNode; \
|
||||||
prevNode->next=nextNode; \
|
prevNode->next=nextNode; \
|
||||||
if(freeRemoved) \
|
if(freeRemoved) \
|
||||||
LLNode_##TYPE##_destruct(removedNode, true); \
|
LLNode_##TYPE##_free(removedNode, true); \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
void LinkedList_##TYPE##_removeNext(LinkedList(TYPE)* llist, LLNode(TYPE)* prevNode, bool freeRemoved){ \
|
void LinkedList_##TYPE##_removeNext(LinkedList(TYPE)* llist, LLNode(TYPE)* prevNode, bool freeRemoved){ \
|
||||||
@@ -65,16 +65,16 @@ void LinkedList_##TYPE##_removeNext(LinkedList(TYPE)* llist, LLNode(TYPE)* prevN
|
|||||||
prevNode->next=nextNode; \
|
prevNode->next=nextNode; \
|
||||||
nextNode->prev=prevNode; \
|
nextNode->prev=prevNode; \
|
||||||
if(freeRemoved) \
|
if(freeRemoved) \
|
||||||
LLNode_##TYPE##_destruct(removedNode, true); \
|
LLNode_##TYPE##_free(removedNode, true); \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
LinkedList_##TYPE##_functions_t _LinkedList_##TYPE##_functions={ \
|
LinkedList_##TYPE##_functions_t _LinkedList_##TYPE##_functions={ \
|
||||||
.destruct=LinkedList_##TYPE##_destructMembers, \
|
.freeMembers=LinkedList_##TYPE##_freeMembers, \
|
||||||
.removePrev=LinkedList_##TYPE##_removePrev, \
|
.removePrev=LinkedList_##TYPE##_removePrev, \
|
||||||
.removeNext=LinkedList_##TYPE##_removeNext \
|
.removeNext=LinkedList_##TYPE##_removeNext \
|
||||||
}; \
|
}; \
|
||||||
\
|
\
|
||||||
kt_define(LinkedList_##TYPE, LinkedList_##TYPE##_destructMembers, NULL)
|
kt_define(LinkedList_##TYPE, LinkedList_##TYPE##_freeMembers, NULL)
|
||||||
|
|
||||||
|
|
||||||
#if __cplusplus
|
#if __cplusplus
|
||||||
|
|||||||
4
src/Network/README.md
Normal file
4
src/Network/README.md
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
# kerep network
|
||||||
|
|
||||||
|
Don't forget to call `kn_tryInit()` before doint anything with network.
|
||||||
|
|
||||||
44
src/Network/network.c
Normal file
44
src/Network/network.c
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
#include "network_internal.h"
|
||||||
|
|
||||||
|
Maybe kn_tryInit(){
|
||||||
|
#if _WIN32
|
||||||
|
// Initialize Winsock
|
||||||
|
WSADATA wsaData = {0};
|
||||||
|
int startupResult = WSAStartup(MAKEWORD(2,2), &wsaData);
|
||||||
|
if (startupResult != 0) {
|
||||||
|
char* errcode = toString_hex(&startupResult, sizeof(int), 0 , 1, 1);
|
||||||
|
safethrow(cptr_concat("WSAStartup failed with error: ", errcode), ;);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return SUCCESS(UniNull);
|
||||||
|
}
|
||||||
|
|
||||||
|
Maybe kt_tryDispose(){
|
||||||
|
#if _WIN32
|
||||||
|
// Deinitialize Winsock
|
||||||
|
int cleanupResult = WSACleanup();
|
||||||
|
if (cleanupResult != 0) {
|
||||||
|
char* errcode = toString_hex(&cleanupResult, sizeof(int), 0, 1, 1);
|
||||||
|
safethrow(cptr_concat("WSAStartup failed with error: ", errcode), ;);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return SUCCESS(UniNull);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Maybe __kn_StdSocket_shutdown(i64 socketfd, knShutdownType direction){
|
||||||
|
if(shutdown(socketfd, (int)direction) == -1)
|
||||||
|
safethrow("can't shutdown socket", ;);
|
||||||
|
return MaybeNull;
|
||||||
|
}
|
||||||
|
|
||||||
|
Maybe __kn_StdSocket_close(i64 socketfd){
|
||||||
|
#if KN_USE_WINSOCK
|
||||||
|
if(closesocket(socketfd) == -1)
|
||||||
|
#else
|
||||||
|
if(close(socketfd) == -1)
|
||||||
|
#endif
|
||||||
|
safethrow("can't close socket", ;);
|
||||||
|
|
||||||
|
return MaybeNull;
|
||||||
|
}
|
||||||
19
src/Network/network.h
Normal file
19
src/Network/network.h
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "../base/base.h"
|
||||||
|
|
||||||
|
#include "network_types.h"
|
||||||
|
#include "sockets/knSocketTCP.h"
|
||||||
|
#include "sockets/knSocketUDP.h"
|
||||||
|
#include "sockets/knSocketChanneled.h"
|
||||||
|
|
||||||
|
Maybe kn_tryInit();
|
||||||
|
Maybe kt_tryDispose();
|
||||||
|
|
||||||
|
#if __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
32
src/Network/network_internal.h
Normal file
32
src/Network/network_internal.h
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "network.h"
|
||||||
|
#include "socket_impl_includes.h"
|
||||||
|
|
||||||
|
/// shutdown TCP/UDP/other std socket
|
||||||
|
Maybe __kn_StdSocket_shutdown(i64 socketfd, knShutdownType direction);
|
||||||
|
|
||||||
|
/// close TCP/UDP/other std socket
|
||||||
|
Maybe __kn_StdSocket_close(i64 socketfd);
|
||||||
|
|
||||||
|
static inline struct sockaddr_in knIPV4Endpoint_toSockaddr(knIPV4Endpoint end){
|
||||||
|
struct sockaddr_in saddr = {0};
|
||||||
|
saddr.sin_family = AF_INET;
|
||||||
|
saddr.sin_addr.s_addr = end.address.UintBigEndian;
|
||||||
|
saddr.sin_port = htons(end.port); /* transforms port number to big endian (network order) */
|
||||||
|
return saddr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline knIPV4Endpoint knIPV4Endpoint_fromSockaddr(struct sockaddr_in saddr_ptr){
|
||||||
|
knIPV4Address ipv4 = knIPV4Address_fromU32(saddr_ptr.sin_addr.s_addr);
|
||||||
|
u16 port = ntohs(saddr_ptr.sin_port); /* transforms port number to little endian (normal order) */
|
||||||
|
return knIPV4Endpoint_create(ipv4, port);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
95
src/Network/network_types.c
Normal file
95
src/Network/network_types.c
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
#include "network_types.h"
|
||||||
|
|
||||||
|
char* __knIPV4Address_toString(void* p, u32 f){ return knIPV4Address_toString(*(knIPV4Address*)p); }
|
||||||
|
char* __knIPV4Endpoint_toString(void* p, u32 f){ return knIPV4Endpoint_toString(*(knIPV4Endpoint*)p); }
|
||||||
|
|
||||||
|
kt_define(knIPV4Address, NULL, __knIPV4Address_toString);
|
||||||
|
kt_define(knIPV4Endpoint, NULL, __knIPV4Endpoint_toString);
|
||||||
|
|
||||||
|
|
||||||
|
Maybe knIPV4Address_fromStr(char* addrStr, knIPV4Address* addrVal){
|
||||||
|
char* addrStr_src=addrStr;
|
||||||
|
char* errmsg_extra="wrong char";
|
||||||
|
u8 c;
|
||||||
|
knIPV4Address addr;
|
||||||
|
addr.UintBigEndian=0;
|
||||||
|
u16 n=0;
|
||||||
|
for(u8 i=0; i<4; ){
|
||||||
|
c=*addrStr++;
|
||||||
|
switch (c){
|
||||||
|
case '\0':
|
||||||
|
if(i<3){
|
||||||
|
errmsg_extra="end of string";
|
||||||
|
goto default_case;
|
||||||
|
}
|
||||||
|
|
||||||
|
addr.bytes[i++]=n;
|
||||||
|
n=0;
|
||||||
|
break;
|
||||||
|
case '.':
|
||||||
|
addr.bytes[i++]=n;
|
||||||
|
n=0;
|
||||||
|
break;
|
||||||
|
case '0': case '1': case '2': case '3': case '4':
|
||||||
|
case '5': case '6': case '7': case '8': case '9':
|
||||||
|
n=n*10+c-'0';
|
||||||
|
if(n>255) {
|
||||||
|
errmsg_extra="one part of address > 255";
|
||||||
|
goto default_case;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default_case:
|
||||||
|
default:
|
||||||
|
u32 errmsgL=cptr_length(addrStr) + 80;
|
||||||
|
char* errmsg=malloc(errmsgL);
|
||||||
|
ksprintf(errmsg, errmsgL, "wrong ip address string: %s\n %s", addrStr_src, errmsg_extra);
|
||||||
|
safethrow(errmsg,;);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*addrVal=addr;
|
||||||
|
return MaybeNull;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* knIPV4Address_toString(knIPV4Address address) {
|
||||||
|
char* a = toString_u64(address.bytes[0], 0, 0);
|
||||||
|
char* b = toString_u64(address.bytes[1], 0, 0);
|
||||||
|
char* c = toString_u64(address.bytes[2], 0, 0);
|
||||||
|
char* d = toString_u64(address.bytes[3], 0, 0);
|
||||||
|
char* s = cptr_concat(a,".",b,".",c,".",d);
|
||||||
|
free(a);
|
||||||
|
free(b);
|
||||||
|
free(c);
|
||||||
|
free(d);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Maybe knIPV4Endpoint_fromStr(char* endStr, knIPV4Endpoint* endVal){
|
||||||
|
i32 sep_i = cptr_seekChar(endStr, ':', 0, 48);
|
||||||
|
if(sep_i < 7)
|
||||||
|
safethrow(cptr_concat("can't find ':' in '", endStr, "'"), ;);
|
||||||
|
const char* portBegin = endStr+sep_i+1;
|
||||||
|
u64 port = knPort_INVALID;
|
||||||
|
if(sscanf(portBegin, IFWIN("%llu", "%lu"), &port)!=1)
|
||||||
|
safethrow(cptr_concat("can't recognise port number in '", portBegin, "'"), ;)
|
||||||
|
|
||||||
|
knIPV4Address addr = knIPV4Address_INVALID;
|
||||||
|
char* addrStr = cptr_copy(endStr);
|
||||||
|
addrStr[sep_i] = 0;
|
||||||
|
try(knIPV4Address_fromStr(addrStr, &addr), _m865, ;);
|
||||||
|
free(addrStr);
|
||||||
|
|
||||||
|
*endVal = knIPV4Endpoint_create(addr, port);
|
||||||
|
return MaybeNull;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* knIPV4Endpoint_toString(knIPV4Endpoint end) {
|
||||||
|
char* a = knIPV4Address_toString(end.address);
|
||||||
|
char* p = toString_u64(end.port, 0, 0);
|
||||||
|
char* s = cptr_concat(a,":",p);
|
||||||
|
free(a);
|
||||||
|
free(p);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
58
src/Network/network_types.h
Normal file
58
src/Network/network_types.h
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "../base/base.h"
|
||||||
|
|
||||||
|
typedef u16 knPort;
|
||||||
|
#define knPort_INVALID ((knPort)~0)
|
||||||
|
#define knPort_isINVALID(PORT) (PORT == knPort_INVALID)
|
||||||
|
|
||||||
|
typedef union knIPV4Address {
|
||||||
|
u32 UintBigEndian;
|
||||||
|
u8 bytes[4];
|
||||||
|
} knIPV4Address;
|
||||||
|
kt_declare(knIPV4Address);
|
||||||
|
|
||||||
|
#define knIPV4Address_fromBytes(A, B, C, D) ((knIPV4Address){.bytes={A,B,C,D}})
|
||||||
|
#define knIPV4Address_fromU32(N) ((knIPV4Address){.UintBigEndian=N})
|
||||||
|
|
||||||
|
|
||||||
|
#define knIPV4Address_ANY knIPV4Address_fromBytes(0,0,0,0)
|
||||||
|
#define knIPV4Address_LOOPBACK knIPV4Address_fromBytes(127,0,0,1)
|
||||||
|
#define knIPV4Address_INVALID knIPV4Address_fromBytes(255,255,255,255)
|
||||||
|
#define knIPV4Address_isINVALID(ADDR) (ADDR.UintBigEndian == (u32)~0)
|
||||||
|
|
||||||
|
///@return Maybe<null>
|
||||||
|
Maybe knIPV4Address_fromStr(char* addrStr, knIPV4Address* addrPtr);
|
||||||
|
|
||||||
|
char* knIPV4Address_toString(knIPV4Address address);
|
||||||
|
|
||||||
|
|
||||||
|
STRUCT(knIPV4Endpoint,
|
||||||
|
knIPV4Address address;
|
||||||
|
knPort port;
|
||||||
|
)
|
||||||
|
|
||||||
|
#define knIPV4Endpoint_create(ADDR, PORT) ((knIPV4Endpoint){ADDR, PORT})
|
||||||
|
|
||||||
|
#define knIPV4Endpoint_INVALID knIPV4Endpoint_create(knIPV4Address_INVALID, knPort_INVALID)
|
||||||
|
#define knIPV4Endpoint_isINVALID(ENDP) (knIPV4Address_isINVALID(ENDP.address) || knPort_isINVALID(ENDP.port))
|
||||||
|
|
||||||
|
///@return Maybe<null>
|
||||||
|
Maybe knIPV4Endpoint_fromStr(char* endStr, knIPV4Endpoint* endVal);
|
||||||
|
|
||||||
|
char* knIPV4Endpoint_toString(knIPV4Endpoint end);
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum knShutdownType {
|
||||||
|
knShutdownType_Receive = 0,
|
||||||
|
knShutdownType_Send = 1,
|
||||||
|
knShutdownType_Both = 2,
|
||||||
|
} knShutdownType;
|
||||||
|
|
||||||
|
#if __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
27
src/Network/socket_impl_includes.h
Normal file
27
src/Network/socket_impl_includes.h
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_WIN64) || defined(_WIN32)
|
||||||
|
#define KN_USE_WINSOCK 1
|
||||||
|
#else
|
||||||
|
#define KN_USE_WINSOCK 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if KN_USE_WINSOCK
|
||||||
|
#include <winsock2.h>
|
||||||
|
// #include <ws2tcpip.h>
|
||||||
|
#else
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
52
src/Network/sockets/knSocketChanneled.c
Normal file
52
src/Network/sockets/knSocketChanneled.c
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
#include "../network_internal.h"
|
||||||
|
|
||||||
|
void __knSocketChanneled_close(void* p){ knSocketChanneled_close(p); }
|
||||||
|
|
||||||
|
kt_define(knPackage, NULL, NULL);
|
||||||
|
kt_define(knPackageQueueElem, NULL, NULL);
|
||||||
|
kt_define(knChannel, NULL, NULL);
|
||||||
|
kt_define(knSocketChanneled, __knSocketChanneled_close, NULL);
|
||||||
|
|
||||||
|
Maybe knSocketChanneled_open(){
|
||||||
|
knSocketChanneled* newSocket=malloc(sizeof(knSocketChanneled));
|
||||||
|
newSocket->localEndpoint=knIPV4Endpoint_INVALID;
|
||||||
|
newSocket->remoteEndpoint=knIPV4Endpoint_INVALID;
|
||||||
|
newSocket->channels=NULL;
|
||||||
|
newSocket->channelsAmount=0;
|
||||||
|
return SUCCESS(UniHeapPtr(knSocketChanneled, newSocket));
|
||||||
|
}
|
||||||
|
|
||||||
|
Maybe knSocketChanneled_close(knSocketChanneled* socket){
|
||||||
|
try(__kn_StdSocket_close(socket->socketfd), _m762, ;);
|
||||||
|
free(socket);
|
||||||
|
return MaybeNull;
|
||||||
|
}
|
||||||
|
|
||||||
|
knChannel* __createChannel(){
|
||||||
|
knChannel* ch=malloc(sizeof(knChannel));
|
||||||
|
ch->queueStart=NULL;
|
||||||
|
return ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
Maybe knSocketChanneled_createChannel(knSocketChanneled* socket){
|
||||||
|
if(socket->channelsAmount == 65535)
|
||||||
|
safethrow("max amount of channels",;);
|
||||||
|
u16 channelsAmountPrev=socket->channelsAmount;
|
||||||
|
socket->channelsAmount++;
|
||||||
|
if(channelsAmountPrev==0)
|
||||||
|
socket->channels=malloc(sizeof(knChannel*));
|
||||||
|
else
|
||||||
|
socket->channels=realloc(socket->channels, socket->channelsAmount*sizeof(knChannel*));
|
||||||
|
socket->channels[channelsAmountPrev]=__createChannel();
|
||||||
|
return SUCCESS(UniUInt64(channelsAmountPrev));
|
||||||
|
}
|
||||||
|
|
||||||
|
Maybe knSocketChanneled_listen(knSocketChanneled* socket, knIPV4Endpoint localEndp);
|
||||||
|
|
||||||
|
Maybe knSocketChanneled_connect(knSocketChanneled* socket, knIPV4Endpoint remoteEndp);
|
||||||
|
|
||||||
|
Maybe knSocketChanneled_accept(knSocketChanneled* socket);
|
||||||
|
|
||||||
|
Maybe knSocketChanneled_send(knSocketChanneled* socket, u16 destinationIndex, u8* data, u32 dataLength);
|
||||||
|
|
||||||
|
Maybe knSocketChanneled_receive(knSocketChanneled* socket, u16 destinationIndex, u8* buffer, u32 bufferLength);
|
||||||
77
src/Network/sockets/knSocketChanneled.h
Normal file
77
src/Network/sockets/knSocketChanneled.h
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "../network_types.h"
|
||||||
|
|
||||||
|
#define KNPAC_MAX_DATA_SIZE (65535-sizeof(knPackage)+sizeof(u8*))
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum __attribute__((__packed__)) knPacVersion {
|
||||||
|
knPac_V1=1
|
||||||
|
} knPacVersion;
|
||||||
|
|
||||||
|
static const char knPacHeader[5]={'k','n','p','a','c'};
|
||||||
|
|
||||||
|
STRUCT(knPackage,
|
||||||
|
char header[5]; /* knpac */
|
||||||
|
knPacVersion version; /* protocol version */
|
||||||
|
u16 data_size; /* size of data block in bytes (1-KNPAC_MAX_DATA_SIZE) */
|
||||||
|
u32 channel_id; /* id of knChannel in socket */
|
||||||
|
u32 package_num; /* number in sequence of sent packages */
|
||||||
|
u64 data_hash; /* hash64 of data */
|
||||||
|
u8* data; /* ptr to data */
|
||||||
|
)
|
||||||
|
|
||||||
|
STRUCT(knPackageQueueElem,
|
||||||
|
knPackage package;
|
||||||
|
knPackageQueueElem* previousElem;
|
||||||
|
knPackageQueueElem* nextElem;
|
||||||
|
)
|
||||||
|
|
||||||
|
STRUCT(knChannel,
|
||||||
|
knPackageQueueElem* queueStart;
|
||||||
|
)
|
||||||
|
|
||||||
|
STRUCT(knSocketChanneled,
|
||||||
|
i64 socketfd;
|
||||||
|
knIPV4Endpoint localEndpoint;
|
||||||
|
knIPV4Endpoint remoteEndpoint;
|
||||||
|
u16 channelsAmount;
|
||||||
|
knChannel** channels;
|
||||||
|
)
|
||||||
|
|
||||||
|
///@return Maybe<knSocketChanneled*> new socket
|
||||||
|
Maybe knSocketChanneled_open();
|
||||||
|
|
||||||
|
///@return Maybe<void> error or nothing
|
||||||
|
Maybe knSocketChanneled_close(knSocketChanneled* socket);
|
||||||
|
|
||||||
|
///@return Maybe<u64> channel index
|
||||||
|
Maybe knSocketChanneled_createChannel(knSocketChanneled* socket);
|
||||||
|
|
||||||
|
///start listening at local endpoint
|
||||||
|
///@return Maybe<void> error or nothing
|
||||||
|
Maybe knSocketChanneled_listen(knSocketChanneled* socket, knIPV4Endpoint localEndp);
|
||||||
|
|
||||||
|
///sets socket remote endpoint
|
||||||
|
///@return Maybe<void> error or nothing
|
||||||
|
Maybe knSocketChanneled_connect(knSocketChanneled* socket, knIPV4Endpoint remoteEndp);
|
||||||
|
|
||||||
|
///@return Maybe<knSocketChanneled*> new socket connected to client
|
||||||
|
Maybe knSocketChanneled_accept(knSocketChanneled* socket);
|
||||||
|
|
||||||
|
///@param dataLength 0-4294967295
|
||||||
|
///@return Maybe<void>
|
||||||
|
Maybe knSocketChanneled_send(knSocketChanneled* socket, u16 destinationIndex, u8* data, u32 dataLength);
|
||||||
|
|
||||||
|
///@param buffer buffer for receiving data
|
||||||
|
///@param bufferLength 0-4294967295
|
||||||
|
///@return Maybe<u64> received bytes amount
|
||||||
|
Maybe knSocketChanneled_receive(knSocketChanneled* socket, u16 destinationIndex, u8* buffer, u32 bufferLength);
|
||||||
|
|
||||||
|
#if __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
129
src/Network/sockets/knSocketTCP.c
Normal file
129
src/Network/sockets/knSocketTCP.c
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
#include "../network_internal.h"
|
||||||
|
|
||||||
|
void __knSocketTCP_close(void* p){ knSocketTCP_close(p); }
|
||||||
|
|
||||||
|
kt_define(knSocketTCP, __knSocketTCP_close, NULL);
|
||||||
|
|
||||||
|
Maybe knSocketTCP_open(bool allowReuse){
|
||||||
|
knSocketTCP* newSocket=malloc(sizeof(knSocketTCP));
|
||||||
|
newSocket->localEndpoint=knIPV4Endpoint_INVALID;
|
||||||
|
newSocket->remoteEndpoint=knIPV4Endpoint_INVALID;
|
||||||
|
newSocket->socketfd=socket(AF_INET, SOCK_STREAM, 0);
|
||||||
|
if(newSocket->socketfd==-1 || newSocket->socketfd == ~0)
|
||||||
|
safethrow("can't create socket", free(newSocket));
|
||||||
|
|
||||||
|
// set value of REUSEADDR socket option
|
||||||
|
int opt_val = allowReuse;
|
||||||
|
if(setsockopt(newSocket->socketfd, SOL_SOCKET, SO_REUSEADDR, (void*)&opt_val, sizeof(opt_val)) != 0)
|
||||||
|
safethrow("can't set socket options", knSocketTCP_close(newSocket));
|
||||||
|
|
||||||
|
return SUCCESS(UniHeapPtr(knSocketTCP, newSocket));
|
||||||
|
}
|
||||||
|
|
||||||
|
Maybe knSocketTCP_shutdown(knSocketTCP* socket, knShutdownType direction){
|
||||||
|
try(__kn_StdSocket_shutdown(socket->socketfd, direction), _m875, ;);
|
||||||
|
return MaybeNull;
|
||||||
|
}
|
||||||
|
|
||||||
|
Maybe knSocketTCP_close(knSocketTCP* socket){
|
||||||
|
try(__kn_StdSocket_close(socket->socketfd), _m875, ;);
|
||||||
|
free(socket);
|
||||||
|
return MaybeNull;
|
||||||
|
}
|
||||||
|
|
||||||
|
Maybe knSocketTCP_bind(knSocketTCP* socket, knIPV4Endpoint localEndp){
|
||||||
|
struct sockaddr_in servaddr = knIPV4Endpoint_toSockaddr(localEndp);
|
||||||
|
if(bind(socket->socketfd, (void*)&servaddr, sizeof(servaddr)) != 0)
|
||||||
|
safethrow("socket bind failed", ;);
|
||||||
|
|
||||||
|
socket->localEndpoint = localEndp;
|
||||||
|
return MaybeNull;
|
||||||
|
}
|
||||||
|
|
||||||
|
Maybe knSocketTCP_listen(knSocketTCP* socket){
|
||||||
|
if(listen(socket->socketfd, 1024) != 0)
|
||||||
|
safethrow("socket listen failed", ;);
|
||||||
|
return MaybeNull;
|
||||||
|
}
|
||||||
|
|
||||||
|
Maybe knSocketTCP_connect(knSocketTCP* socket, knIPV4Endpoint remoteEnd){
|
||||||
|
struct sockaddr_in localAddr = {0};
|
||||||
|
struct sockaddr_in remoteAddr = knIPV4Endpoint_toSockaddr(remoteEnd);
|
||||||
|
u64 sockaddr_size = sizeof(localAddr);
|
||||||
|
|
||||||
|
if(connect(socket->socketfd, (struct sockaddr*)&remoteAddr, sizeof(remoteAddr)) != 0)
|
||||||
|
safethrow("socket connect failed", ;);
|
||||||
|
|
||||||
|
if(getsockname(socket->socketfd, (struct sockaddr*)&localAddr, (void*)&sockaddr_size) != 0)
|
||||||
|
safethrow("can't get connected socket local address", ;);
|
||||||
|
|
||||||
|
socket->localEndpoint = knIPV4Endpoint_fromSockaddr(localAddr);
|
||||||
|
socket->remoteEndpoint = remoteEnd;
|
||||||
|
return MaybeNull;
|
||||||
|
}
|
||||||
|
|
||||||
|
Maybe knSocketTCP_accept(knSocketTCP* socket){
|
||||||
|
struct sockaddr_in localAddr = {0};
|
||||||
|
struct sockaddr_in remoteAddr = {0};
|
||||||
|
u64 sockaddr_size = sizeof(localAddr);
|
||||||
|
|
||||||
|
i64 client_fd = accept(socket->socketfd, (struct sockaddr*)&remoteAddr, (void*)&sockaddr_size);
|
||||||
|
if(client_fd == -1 || client_fd == ~0)
|
||||||
|
safethrow("can't accept client connection", ;);
|
||||||
|
|
||||||
|
if(getsockname(client_fd, (struct sockaddr*)&localAddr, (void*)&sockaddr_size) != 0)
|
||||||
|
safethrow("can't get accepted socket local address", __kn_StdSocket_close(client_fd));
|
||||||
|
|
||||||
|
// if accept() didn't set remoteAddr for some reason
|
||||||
|
if(remoteAddr.sin_addr.s_addr == 0 && remoteAddr.sin_port == 0 && remoteAddr.sin_family == 0){
|
||||||
|
if(getpeername(client_fd, (struct sockaddr*)&remoteAddr, (void*)&sockaddr_size) != 0)
|
||||||
|
safethrow("can't get accepted socket remote address", __kn_StdSocket_close(client_fd));
|
||||||
|
}
|
||||||
|
|
||||||
|
knSocketTCP* clientSocket = malloc(sizeof(knSocketTCP));
|
||||||
|
clientSocket->socketfd = client_fd;
|
||||||
|
clientSocket->localEndpoint = knIPV4Endpoint_fromSockaddr(localAddr);
|
||||||
|
clientSocket->remoteEndpoint = knIPV4Endpoint_fromSockaddr(remoteAddr);
|
||||||
|
return SUCCESS(UniHeapPtr(knSocketTCP, clientSocket));
|
||||||
|
}
|
||||||
|
|
||||||
|
Maybe knSocketTCP_send(knSocketTCP* socket, void* _buf, u32 dataLength){
|
||||||
|
char* buf = _buf;
|
||||||
|
u32 sentTotal = 0;
|
||||||
|
while(sentTotal < dataLength){
|
||||||
|
int sentCount = send(socket->socketfd, buf+sentTotal, dataLength-sentTotal, 0);
|
||||||
|
if(sentCount == -1){
|
||||||
|
safethrow(
|
||||||
|
cptr_concat("can't send ", toString_u64(dataLength-sentTotal,0,0),
|
||||||
|
" bytes out of ", toString_u64(dataLength,0,0),
|
||||||
|
" at index ", toString_u64(sentTotal,0,0)
|
||||||
|
),
|
||||||
|
;);
|
||||||
|
}
|
||||||
|
sentTotal += sentCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
return MaybeNull;
|
||||||
|
}
|
||||||
|
|
||||||
|
Maybe knSocketTCP_receive(knSocketTCP* socket, void* _buf, u32 bufferLength){
|
||||||
|
char* buf = _buf;
|
||||||
|
int receivedCount = recv(socket->socketfd, buf, bufferLength, 0);
|
||||||
|
if(receivedCount == -1 || receivedCount == 0)
|
||||||
|
safethrow("can't receive data from socket", ;)
|
||||||
|
|
||||||
|
return SUCCESS(UniUInt64(receivedCount));
|
||||||
|
}
|
||||||
|
|
||||||
|
Maybe knSocketTCP_receiveN(knSocketTCP* socket, void* _buf, u32 bufsize, u32 n){
|
||||||
|
char* buf = _buf;
|
||||||
|
if(bufsize < n)
|
||||||
|
safethrow(ERR_UNEXPECTEDVAL, ;);
|
||||||
|
|
||||||
|
u32 receivedTotal = 0;
|
||||||
|
while(receivedTotal < n) {
|
||||||
|
try(knSocketTCP_receive(socket, buf+receivedTotal, n-receivedTotal), m_receivedCount, ;);
|
||||||
|
receivedTotal += m_receivedCount.value.UInt64;
|
||||||
|
}
|
||||||
|
return MaybeNull;
|
||||||
|
}
|
||||||
64
src/Network/sockets/knSocketTCP.h
Normal file
64
src/Network/sockets/knSocketTCP.h
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "../network_types.h"
|
||||||
|
|
||||||
|
STRUCT(knSocketTCP,
|
||||||
|
i64 socketfd;
|
||||||
|
knIPV4Endpoint localEndpoint;
|
||||||
|
knIPV4Endpoint remoteEndpoint;
|
||||||
|
/* TODO socket status enum */
|
||||||
|
)
|
||||||
|
|
||||||
|
///@note EXAMPLE 1: socket = open(false); bind(socket, localhost:8080); close(socket); - the socket on port 8080 still unavaliable for several minutes
|
||||||
|
///@note EXAMPLE 2: socket = open(true); bind(socket, localhost:8080); close(socket); - the socket on port 8080 can be opened again
|
||||||
|
///@param allowReuse enables binding multiple sockets to single port. Set to TRUE on a listening socket if you want to bind it to the same port after close.
|
||||||
|
///@return Maybe<knSocketTCP*> new socket
|
||||||
|
Maybe knSocketTCP_open(bool allowReuse);
|
||||||
|
|
||||||
|
///@param direction receive/send/both
|
||||||
|
///@return Maybe<void> error or nothing
|
||||||
|
Maybe knSocketTCP_shutdown(knSocketTCP* socket, knShutdownType direction);
|
||||||
|
|
||||||
|
/// closes file descriptor and frees socket pointer
|
||||||
|
///@return Maybe<void> error or nothing
|
||||||
|
Maybe knSocketTCP_close(knSocketTCP* socket);
|
||||||
|
|
||||||
|
/// binds socket to a local endpoint
|
||||||
|
///@return Maybe<void> error or nothing
|
||||||
|
Maybe knSocketTCP_bind(knSocketTCP* socket, knIPV4Endpoint localEndp);
|
||||||
|
|
||||||
|
/// begins listening for incoming TCP connections
|
||||||
|
Maybe knSocketTCP_listen(knSocketTCP* socket);
|
||||||
|
///@return Maybe<void> error or nothing
|
||||||
|
|
||||||
|
/// establishes TCP connection with a remote endpoint
|
||||||
|
///@return Maybe<void> error or nothing
|
||||||
|
Maybe knSocketTCP_connect(knSocketTCP* socket, knIPV4Endpoint remoteEnd);
|
||||||
|
|
||||||
|
///@return Maybe<knSocketTCP*> new socket connected to client
|
||||||
|
Maybe knSocketTCP_accept(knSocketTCP* socket);
|
||||||
|
|
||||||
|
/// sends <dataLength> bytes from buffer
|
||||||
|
///@param buffer buffer for receiving data
|
||||||
|
///@param dataLength 0-4294967295
|
||||||
|
///@return Maybe<void>
|
||||||
|
Maybe knSocketTCP_send(knSocketTCP* socket, void* buffer, u32 dataLength);
|
||||||
|
|
||||||
|
/// receives a package of any size
|
||||||
|
/// (by TCP 32 bytes han be sent as 32x1byte, 4x8byte, 32x1byte or in any other combination)
|
||||||
|
///@param buffer buffer for receiving data
|
||||||
|
///@param bufferLength 0-4294967295
|
||||||
|
///@return Maybe<u64> received bytes amount
|
||||||
|
Maybe knSocketTCP_receive(knSocketTCP* socket, void* buffer, u32 bufferLength);
|
||||||
|
|
||||||
|
/// receives a package of size n
|
||||||
|
///@return Maybe<void>
|
||||||
|
Maybe knSocketTCP_receiveN(knSocketTCP* socket, void* buf, u32 bufsize, u32 n);
|
||||||
|
|
||||||
|
#if __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
94
src/Network/sockets/knSocketUDP.c
Normal file
94
src/Network/sockets/knSocketUDP.c
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
#include "../network_internal.h"
|
||||||
|
|
||||||
|
void __knSocketUDP_close(void* p){ knSocketUDP_close(p); }
|
||||||
|
|
||||||
|
kt_define(knSocketUDP, __knSocketUDP_close, NULL);
|
||||||
|
|
||||||
|
Maybe knSocketUDP_open(bool allowReuse){
|
||||||
|
knSocketUDP* newSocket=malloc(sizeof(knSocketUDP));
|
||||||
|
newSocket->localEndpoint=knIPV4Endpoint_INVALID;
|
||||||
|
newSocket->socketfd=socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
|
if(newSocket->socketfd==-1 || newSocket->socketfd == ~0)
|
||||||
|
safethrow("can't create socket", free(newSocket));
|
||||||
|
|
||||||
|
// set value of REUSEADDR socket option
|
||||||
|
int opt_val = allowReuse;
|
||||||
|
if(setsockopt(newSocket->socketfd, SOL_SOCKET, SO_REUSEADDR, (void*)&opt_val, sizeof(opt_val)) != 0)
|
||||||
|
safethrow("can't set socket options", knSocketUDP_close(newSocket));
|
||||||
|
|
||||||
|
return SUCCESS(UniHeapPtr(knSocketUDP, newSocket));
|
||||||
|
}
|
||||||
|
|
||||||
|
Maybe knSocketUDP_shutdown(knSocketUDP* socket, knShutdownType direction){
|
||||||
|
try(__kn_StdSocket_shutdown(socket->socketfd, direction), _m875, ;);
|
||||||
|
return MaybeNull;
|
||||||
|
}
|
||||||
|
|
||||||
|
Maybe knSocketUDP_close(knSocketUDP* socket){
|
||||||
|
try(__kn_StdSocket_close(socket->socketfd), _m875, ;);
|
||||||
|
free(socket);
|
||||||
|
return MaybeNull;
|
||||||
|
}
|
||||||
|
|
||||||
|
Maybe knSocketUDP_bind(knSocketUDP* socket, knIPV4Endpoint localEndp){
|
||||||
|
struct sockaddr_in servaddr = {
|
||||||
|
.sin_family = AF_INET,
|
||||||
|
.sin_addr.s_addr = localEndp.address.UintBigEndian,
|
||||||
|
.sin_port = htons(localEndp.port) /* transforms port to big endian */
|
||||||
|
};
|
||||||
|
|
||||||
|
if(bind(socket->socketfd, (void*)&servaddr, sizeof(servaddr)) != 0)
|
||||||
|
safethrow("socket bind failed", ;);
|
||||||
|
|
||||||
|
socket->localEndpoint = localEndp;
|
||||||
|
return MaybeNull;
|
||||||
|
}
|
||||||
|
|
||||||
|
Maybe knSocketUDP_sendTo(knSocketUDP* socket, char* buffer, u32 dataLength, knIPV4Endpoint destEnd){
|
||||||
|
struct sockaddr_in dest_saddr = knIPV4Endpoint_toSockaddr(destEnd);
|
||||||
|
u32 sentCount = sendto(
|
||||||
|
socket->socketfd,
|
||||||
|
buffer,
|
||||||
|
dataLength,
|
||||||
|
0,
|
||||||
|
(struct sockaddr*)&dest_saddr,
|
||||||
|
sizeof(struct sockaddr_in)
|
||||||
|
);
|
||||||
|
|
||||||
|
if(sentCount != dataLength) {
|
||||||
|
safethrow(
|
||||||
|
cptr_concat("can't send ", toString_u64(dataLength-sentCount,0,0),
|
||||||
|
" bytes out of ", toString_u64(dataLength,0,0)
|
||||||
|
),
|
||||||
|
;);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sockaddr_in localAddr = {0};
|
||||||
|
u64 sockaddr_size = sizeof(localAddr);
|
||||||
|
|
||||||
|
if(getsockname(socket->socketfd, (struct sockaddr*)&localAddr, (void*)&sockaddr_size) != 0)
|
||||||
|
safethrow("can't get implicitely bound socket local address", ;);
|
||||||
|
|
||||||
|
socket->localEndpoint = knIPV4Endpoint_fromSockaddr(localAddr);
|
||||||
|
|
||||||
|
return MaybeNull;
|
||||||
|
}
|
||||||
|
|
||||||
|
Maybe knSocketUDP_receiveAny(knSocketUDP* socket, char* buffer, u32 bufferLength, knIPV4Endpoint* senderEnd){
|
||||||
|
struct sockaddr_in remote_saddr = {0};
|
||||||
|
u64 remote_saddr_size = sizeof(remote_saddr);
|
||||||
|
int receivedCount = recvfrom(
|
||||||
|
socket->socketfd,
|
||||||
|
buffer,
|
||||||
|
bufferLength,
|
||||||
|
0,
|
||||||
|
(struct sockaddr*)&remote_saddr,
|
||||||
|
(void*)&remote_saddr_size
|
||||||
|
);
|
||||||
|
|
||||||
|
if(receivedCount == -1 || receivedCount == 0)
|
||||||
|
safethrow("can't receive data from socket", ;)
|
||||||
|
|
||||||
|
*senderEnd = knIPV4Endpoint_fromSockaddr(remote_saddr);
|
||||||
|
return SUCCESS(UniUInt64(receivedCount));
|
||||||
|
}
|
||||||
49
src/Network/sockets/knSocketUDP.h
Normal file
49
src/Network/sockets/knSocketUDP.h
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "../network_types.h"
|
||||||
|
|
||||||
|
STRUCT(knSocketUDP,
|
||||||
|
i64 socketfd;
|
||||||
|
knIPV4Endpoint localEndpoint;
|
||||||
|
/* TODO socket status enum */
|
||||||
|
)
|
||||||
|
|
||||||
|
///@note EXAMPLE 1: socket = open(false); bind(socket, localhost:8080); close(socket); - the socket on port 8080 still unavaliable for several minutes
|
||||||
|
///@note EXAMPLE 2: socket = open(true); bind(socket, localhost:8080); close(socket); - the socket on port 8080 can be opened again
|
||||||
|
///@param allowReuse enables binding multiple sockets to single port. Set to TRUE on a listening socket if you want to bind it to the same port after close.
|
||||||
|
///@return Maybe<knSocketUDP*> new socket
|
||||||
|
Maybe knSocketUDP_open(bool allowReuse);
|
||||||
|
|
||||||
|
///@param direction receive/send/both
|
||||||
|
///@return Maybe<void> error or nothing
|
||||||
|
Maybe knSocketUDP_shutdown(knSocketUDP* socket, knShutdownType direction);
|
||||||
|
|
||||||
|
/// closes file descriptor and frees socket pointer
|
||||||
|
///@return Maybe<void> error or nothing
|
||||||
|
Maybe knSocketUDP_close(knSocketUDP* socket);
|
||||||
|
|
||||||
|
/// binds socket to a local endpoint
|
||||||
|
///@return Maybe<void> error or nothing
|
||||||
|
Maybe knSocketUDP_bind(knSocketUDP* socket, knIPV4Endpoint localEndp);
|
||||||
|
|
||||||
|
/// sends one package to destination endpoint
|
||||||
|
///@param buffer buffer for receiving data
|
||||||
|
///@param dataLength 0-64k
|
||||||
|
///@param destEnd destination endpoint
|
||||||
|
///@return Maybe<void>
|
||||||
|
Maybe knSocketUDP_sendTo(knSocketUDP* socket, char* buffer, u32 dataLength, knIPV4Endpoint destEnd);
|
||||||
|
|
||||||
|
/// receives one package from anywhere
|
||||||
|
///@param buffer buffer for receiving data
|
||||||
|
///@param bufferLength 0-64k
|
||||||
|
///@param senderEnd [OUT] endpoint UPD package was sent from
|
||||||
|
///@return Maybe<u64> received bytes amount
|
||||||
|
Maybe knSocketUDP_receiveAny(knSocketUDP* socket, char* buffer, u32 bufferLength, knIPV4Endpoint* senderEnd);
|
||||||
|
|
||||||
|
#if __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
#include "SearchTree.h"
|
#include "SearchTree.h"
|
||||||
|
|
||||||
kt_define(STNode, __STNode_destruct, NULL);
|
kt_define(STNode, __STNode_free, NULL);
|
||||||
|
|
||||||
STNode* STNode_create(){
|
STNode* STNode_create(){
|
||||||
STNode* node=malloc(sizeof(STNode));
|
STNode* node=malloc(sizeof(STNode));
|
||||||
@@ -9,7 +9,7 @@ STNode* STNode_create(){
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
void __STNode_destruct(void* _node){
|
void __STNode_free(void* _node){
|
||||||
STNode* node=_node;
|
STNode* node=_node;
|
||||||
if (!node) throw(ERR_NULLPTR);
|
if (!node) throw(ERR_NULLPTR);
|
||||||
if(node->branches){
|
if(node->branches){
|
||||||
@@ -22,7 +22,7 @@ void __STNode_destruct(void* _node){
|
|||||||
for(u8 rem=0;rem<4;rem++){
|
for(u8 rem=0;rem<4;rem++){
|
||||||
STNode* ptrrem=ptrn4[rem];
|
STNode* ptrrem=ptrn4[rem];
|
||||||
if(ptrrem)
|
if(ptrrem)
|
||||||
STNode_destruct(ptrrem);
|
STNode_free(ptrrem);
|
||||||
}
|
}
|
||||||
free(ptrn4);
|
free(ptrn4);
|
||||||
}
|
}
|
||||||
@@ -33,10 +33,10 @@ void __STNode_destruct(void* _node){
|
|||||||
free(node->branches);
|
free(node->branches);
|
||||||
}
|
}
|
||||||
if(node->value.VoidPtr)
|
if(node->value.VoidPtr)
|
||||||
Unitype_destruct(&node->value);
|
Unitype_free(node->value);
|
||||||
}
|
}
|
||||||
void STNode_destruct(STNode* node){
|
void STNode_free(STNode* node){
|
||||||
__STNode_destruct(node);
|
__STNode_free(node);
|
||||||
free(node);
|
free(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ STRUCT(STNode,
|
|||||||
)
|
)
|
||||||
|
|
||||||
STNode* STNode_create();
|
STNode* STNode_create();
|
||||||
void STNode_destruct(STNode* node);
|
void STNode_free(STNode* node);
|
||||||
void __STNode_destruct(void* node);
|
void __STNode_free(void* node);
|
||||||
|
|
||||||
void ST_push(STNode* node, char* key, Unitype value);
|
void ST_push(STNode* node, char* key, Unitype value);
|
||||||
void ST_pushString(STNode* node, string key, Unitype value);
|
void ST_pushString(STNode* node, string key, Unitype value);
|
||||||
|
|||||||
@@ -1,90 +1,144 @@
|
|||||||
#include "StringBuilder.h"
|
#include "StringBuilder.h"
|
||||||
|
|
||||||
kt_define(StringBuilder, (destruct_t)StringBuilder_destruct, NULL);
|
kt_define(StringBuilder, __StringBuilder_free, NULL);
|
||||||
|
|
||||||
#define BL_C 32
|
#define BL_C 32
|
||||||
#define BL_L 1024
|
#define BL_L 1024
|
||||||
|
|
||||||
#define createBuffer() (MemoryChunk){.data = allocator_alloc(InternalAllocator_getPtr(b), 512), .size=512, .occupied_size=0}
|
|
||||||
|
|
||||||
|
|
||||||
void complete_buf(StringBuilder* b){
|
void complete_buf(StringBuilder* b){
|
||||||
if(b->curr_buf.occupied_size == 0)
|
if(!b->compl_bufs)
|
||||||
return;
|
b->compl_bufs=Autoarr_create(string,BL_C,BL_L);
|
||||||
string str={ .length=b->curr_buf.occupied_size, .ptr= b->curr_buf.data };
|
u32 len=Autoarr_length(b->curr_buf);
|
||||||
Autoarr_add(&b->compl_bufs,str);
|
if(!len) return;
|
||||||
b->curr_buf = createBuffer();
|
string str={.length=len, .ptr=malloc(len)};
|
||||||
|
u32 i=0;
|
||||||
|
Autoarr_foreach(b->curr_buf, c,
|
||||||
|
str.ptr[i++]=c;
|
||||||
|
);
|
||||||
|
Autoarr_add(b->compl_bufs,str);
|
||||||
|
Autoarr_free(b->curr_buf, true);
|
||||||
|
b->curr_buf=Autoarr_create(i8,BL_C,BL_L);
|
||||||
|
}
|
||||||
|
|
||||||
|
void try_complete_buf(StringBuilder* b){
|
||||||
|
if(b->curr_buf->blocks_count==BL_C)
|
||||||
|
complete_buf(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void StringBuilder_construct(StringBuilder* b, allocator_ptr external_al){
|
StringBuilder* StringBuilder_create(){
|
||||||
InternalAllocator_setExternalOrConstruct(b, external_al, LinearAllocator, 1024);
|
StringBuilder* b=malloc(sizeof(StringBuilder));
|
||||||
Autoarr_construct(&b->compl_bufs, string, 0, InternalAllocator_getPtr(b));
|
b->compl_bufs=NULL;
|
||||||
b->curr_buf = createBuffer();
|
b->curr_buf=Autoarr_create(i8,BL_C,BL_L);
|
||||||
b->total_length = 0;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
void StringBuilder_destruct(StringBuilder* b){
|
void __StringBuilder_free(void* _b){
|
||||||
Autoarr_destruct(&b->compl_bufs);
|
StringBuilder* b=_b;
|
||||||
allocator_free(InternalAllocator_getPtr(b), b->curr_buf.data);
|
if(b->compl_bufs) Autoarr_free(b->compl_bufs, true);
|
||||||
InternalAllocator_destructIfInternal(LinearAllocator, b);
|
Autoarr_free(b->curr_buf, true);
|
||||||
|
}
|
||||||
|
void StringBuilder_free(StringBuilder* b){
|
||||||
|
__StringBuilder_free(b);
|
||||||
|
free(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
string StringBuilder_build(StringBuilder* b){
|
string StringBuilder_build(StringBuilder* b){
|
||||||
complete_buf(b);
|
complete_buf(b);
|
||||||
string str= {
|
u32 len=0;
|
||||||
.length = b->total_length,
|
Autoarr_foreach(b->compl_bufs, cs,
|
||||||
.ptr = allocator_alloc(InternalAllocator_getPtr(b), b->total_length+1)
|
len+=cs.length;
|
||||||
};
|
|
||||||
str.ptr[b->total_length]='\0';
|
|
||||||
char* free_space_ptr = str.ptr;
|
|
||||||
Autoarr_foreach(&b->compl_bufs, buf,
|
|
||||||
memcpy(free_space_ptr, buf.ptr, buf.length);
|
|
||||||
free_space_ptr += buf.length;
|
|
||||||
);
|
);
|
||||||
StringBuilder_destruct(b);
|
string str= { .length=len, .ptr=malloc(len+1) };
|
||||||
|
str.ptr[len]='\0';
|
||||||
|
u32 i=0;
|
||||||
|
Autoarr_foreach(b->compl_bufs, cs,
|
||||||
|
for(u32 n=0;n<cs.length;n++)
|
||||||
|
str.ptr[i++]=cs.ptr[n];
|
||||||
|
free(cs.ptr);
|
||||||
|
);
|
||||||
|
StringBuilder_free(b);
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void StringBuilder_rmchar(StringBuilder* b){
|
void StringBuilder_rmchar(StringBuilder* b){
|
||||||
if(b->curr_buf.occupied_size != 0)
|
if(b->curr_buf->block_length!=0)
|
||||||
b->curr_buf.occupied_size--;
|
Autoarr_pop(b->curr_buf)
|
||||||
else {
|
else {
|
||||||
for(u32 buf_i = Autoarr_length(&b->compl_bufs) - 1; buf_i != (u32)-1; buf_i--){
|
if(!b->compl_bufs) throw(ERR_NULLPTR);
|
||||||
string* lastcb = Autoarr_getPtr(&b->compl_bufs, buf_i);
|
string* lastcb=Autoarr_getPtr(b->compl_bufs, (Autoarr_length(b->compl_bufs)-1));
|
||||||
if(lastcb->length != 0){
|
|
||||||
lastcb->length--;
|
lastcb->length--;
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void StringBuilder_append_char(StringBuilder* b, char c){
|
void StringBuilder_append_char(StringBuilder* b, char c){
|
||||||
if(b->curr_buf.occupied_size==b->curr_buf.size)
|
try_complete_buf(b);
|
||||||
complete_buf(b);
|
Autoarr_add(b->curr_buf,c);
|
||||||
((char*)b->curr_buf.data)[b->curr_buf.occupied_size] = c;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void StringBuilder_append_string(StringBuilder* b, string s){
|
void StringBuilder_append_string(StringBuilder* b, string s){
|
||||||
complete_buf(b);
|
complete_buf(b);
|
||||||
Autoarr_add(&b->compl_bufs, s);
|
Autoarr_add(b->compl_bufs, string_copy(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
void StringBuilder_append_cptr(StringBuilder* b, char* s){
|
void StringBuilder_append_cptr(StringBuilder* b, char* s){
|
||||||
string str={ .ptr=s, .length=cptr_length(s) };
|
string str={
|
||||||
StringBuilder_append_string(b, str);
|
.ptr=s,
|
||||||
|
.length=cptr_length(s)
|
||||||
|
};
|
||||||
|
StringBuilder_append_string(b,str);
|
||||||
|
}
|
||||||
|
|
||||||
|
void curr_buf_add_string(StringBuilder* b, string s){
|
||||||
|
for(u32 i=0; i<s.length; i++)
|
||||||
|
Autoarr_add(b->curr_buf,s.ptr[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StringBuilder_append_i64(StringBuilder* b, i64 a){
|
void StringBuilder_append_i64(StringBuilder* b, i64 a){
|
||||||
StringBuilder_append_cptr(b, toString_i64(InternalAllocator_getPtr(b), a));
|
try_complete_buf(b);
|
||||||
|
u8 i=0;
|
||||||
|
if(a==0){
|
||||||
|
Autoarr_add(b->curr_buf,'0');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if(a<0){
|
||||||
|
Autoarr_add(b->curr_buf,'-');
|
||||||
|
a=-a;
|
||||||
|
}
|
||||||
|
char buf[24];
|
||||||
|
while(a!=0){
|
||||||
|
buf[i++]='0'+a%10;
|
||||||
|
a/=10;
|
||||||
|
}
|
||||||
|
string rev=string_reverse((string){buf,i});
|
||||||
|
curr_buf_add_string(b,rev);
|
||||||
|
free(rev.ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StringBuilder_append_u64(StringBuilder* b, u64 a){
|
void StringBuilder_append_u64(StringBuilder* b, u64 a){
|
||||||
StringBuilder_append_cptr(b, toString_u64(InternalAllocator_getPtr(b), a, 0, 0));
|
try_complete_buf(b);
|
||||||
|
u8 i=0;
|
||||||
|
if(a==0){
|
||||||
|
Autoarr_add(b->curr_buf,'0');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
char buf[24];
|
||||||
|
while(a!=0){
|
||||||
|
buf[i++]='0'+a%10;
|
||||||
|
a/=10;
|
||||||
|
}
|
||||||
|
string rev=string_reverse((string){buf,i});
|
||||||
|
curr_buf_add_string(b,rev);
|
||||||
|
free(rev.ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StringBuilder_append_f64(StringBuilder* b, f64 a){
|
void StringBuilder_append_f64(StringBuilder* b, f64 a){
|
||||||
StringBuilder_append_cptr(b, toString_f64(InternalAllocator_getPtr(b), a, toString_f64_max_precision, 0, 0));
|
try_complete_buf(b);
|
||||||
|
char buf[32];
|
||||||
|
ksprintf(buf,32,"%lf",a);
|
||||||
|
curr_buf_add_string(b, (string){.ptr=buf, .length=cptr_length(buf)});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,25 +8,20 @@ extern "C" {
|
|||||||
#include "string.h"
|
#include "string.h"
|
||||||
|
|
||||||
STRUCT(StringBuilder,
|
STRUCT(StringBuilder,
|
||||||
InternalAllocator_declare(LinearAllocator);
|
Autoarr(string)* compl_bufs;
|
||||||
Autoarr(string) compl_bufs;
|
Autoarr(i8)* curr_buf;
|
||||||
MemoryChunk curr_buf;
|
|
||||||
u64 total_length;
|
|
||||||
)
|
)
|
||||||
|
|
||||||
///@param external_al if null, creates internal allocator
|
StringBuilder* StringBuilder_create(void);
|
||||||
void StringBuilder_construct(StringBuilder* b, allocator_ptr external_al);
|
void StringBuilder_free(StringBuilder* b);
|
||||||
void StringBuilder_destruct(StringBuilder* b);
|
void __StringBuilder_free(void* b);
|
||||||
|
|
||||||
// Joins all strings from compl_bufs.
|
// Joins all strings from compl_bufs.
|
||||||
// Returns zero-terminated string.
|
// Returns zero-terminated string.
|
||||||
// No need to call string_extract!
|
// No need to call string_extract()!
|
||||||
// Destructs StringBuilder.
|
// Frees StringBuilder.
|
||||||
string StringBuilder_build(StringBuilder* b);
|
string StringBuilder_build(StringBuilder* b);
|
||||||
|
// removes last char
|
||||||
/// OBSOLETE! Will be removed later
|
|
||||||
void StringBuilder_rmchar(StringBuilder* b);
|
void StringBuilder_rmchar(StringBuilder* b);
|
||||||
|
|
||||||
void StringBuilder_append_char(StringBuilder* b, char c);
|
void StringBuilder_append_char(StringBuilder* b, char c);
|
||||||
void StringBuilder_append_cptr(StringBuilder* b, char* s);
|
void StringBuilder_append_cptr(StringBuilder* b, char* s);
|
||||||
void StringBuilder_append_string(StringBuilder* b, string s);
|
void StringBuilder_append_string(StringBuilder* b, string s);
|
||||||
|
|||||||
@@ -1,35 +1,36 @@
|
|||||||
#include "string.h"
|
#include "string.h"
|
||||||
|
|
||||||
kt_define(string, NULL, NULL);
|
kt_define(string, NULL, NULL);
|
||||||
Autoarr_define(string);
|
Array_define(string)
|
||||||
|
Autoarr_define(string, false)
|
||||||
|
|
||||||
// copies str content to new char pointer value (adding '\0' at the end)
|
// copies str content to new char pointer value (adding '\0' at the end)
|
||||||
char* string_extract(allocator_ptr al, string str){
|
char* string_extract(string str){
|
||||||
if(str.length==0) return NULL;
|
if(str.length==0) return NULL;
|
||||||
char* cptr=allocator_alloc(al, str.length+1);
|
char* cptr=malloc(str.length*sizeof(char)+1);
|
||||||
memcpy(cptr, str.ptr, str.length);
|
|
||||||
cptr[str.length]=0;
|
cptr[str.length]=0;
|
||||||
|
while(str.length-->0)
|
||||||
|
cptr[str.length]=str.ptr[str.length];
|
||||||
return cptr;
|
return cptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// copies src.ptr content to new string and adds \0 at the end
|
// copies src.ptr content to new string and adds \0 at the end
|
||||||
string string_copy(allocator_ptr al, string src){
|
string string_copy(string src){
|
||||||
if(!src.ptr)
|
if(!src.ptr)
|
||||||
throw(ERR_NULLPTR);
|
return src;
|
||||||
string nstr;
|
string nstr;
|
||||||
nstr.length=src.length;
|
nstr.length=src.length;
|
||||||
nstr.ptr=allocator_alloc(al, nstr.length+1);
|
nstr.ptr=malloc(nstr.length+1);
|
||||||
memcpy(nstr.ptr, src.ptr, nstr.length);
|
for(u32 i=0;i<nstr.length;i++)
|
||||||
|
nstr.ptr[i]=src.ptr[i];
|
||||||
nstr.ptr[nstr.length]='\0';
|
nstr.ptr[nstr.length]='\0';
|
||||||
return nstr;
|
return nstr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// compares two strings, NullPtr-friendly
|
// compares two strings, NullPtr-friendly
|
||||||
bool string_compare(string str0, string str1){
|
bool string_compare(string str0, string str1){
|
||||||
if(str0.length!=str1.length)
|
if(str0.length!=str1.length) return false;
|
||||||
return false;
|
if(!str0.ptr) return str1.ptr ? false : true;
|
||||||
if(!str0.ptr)
|
|
||||||
return str1.ptr ? false : true;
|
|
||||||
else if(!str1.ptr) return false;
|
else if(!str1.ptr) return false;
|
||||||
while(str0.length-->0)
|
while(str0.length-->0)
|
||||||
if(*str0.ptr++ != *str1.ptr++)
|
if(*str0.ptr++ != *str1.ptr++)
|
||||||
@@ -38,12 +39,9 @@ bool string_compare(string str0, string str1){
|
|||||||
}
|
}
|
||||||
|
|
||||||
// creates new string which is reversed variant of <s>
|
// creates new string which is reversed variant of <s>
|
||||||
string string_reverse(allocator_ptr al, string s){
|
string string_reverse(string s){
|
||||||
if(s.length==0)
|
if(s.length==0) return s;
|
||||||
return s;
|
string r={malloc(s.length), s.length};
|
||||||
string r;
|
|
||||||
r.ptr=allocator_alloc(al, s.length);
|
|
||||||
r.length=s.length;
|
|
||||||
for(u32 i=0; i<s.length; i++)
|
for(u32 i=0; i<s.length; i++)
|
||||||
r.ptr[i]=s.ptr[s.length-i-1];
|
r.ptr[i]=s.ptr[s.length-i-1];
|
||||||
return r;
|
return r;
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "../base/base.h"
|
#include "../base/base.h"
|
||||||
|
#include "../Array/Array.h"
|
||||||
#include "../Autoarr/Autoarr.h"
|
#include "../Autoarr/Autoarr.h"
|
||||||
|
|
||||||
// my fixed length string struct
|
// my fixed length string struct
|
||||||
@@ -14,6 +15,7 @@ STRUCT(string,
|
|||||||
u64 length; // amount of chars in ptr value
|
u64 length; // amount of chars in ptr value
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Array_declare(string)
|
||||||
Autoarr_declare(string)
|
Autoarr_declare(string)
|
||||||
|
|
||||||
static const string stringNull={NULL,0};
|
static const string stringNull={NULL,0};
|
||||||
@@ -22,16 +24,16 @@ static const string stringNull={NULL,0};
|
|||||||
#define string_fromCptr(CPTR) (string){ .ptr=CPTR, .length=cptr_length(CPTR) }
|
#define string_fromCptr(CPTR) (string){ .ptr=CPTR, .length=cptr_length(CPTR) }
|
||||||
|
|
||||||
// copies str content to new char pointer value (adding '\0' at the end)
|
// copies str content to new char pointer value (adding '\0' at the end)
|
||||||
char* string_extract(allocator_ptr al, string str);
|
char* string_extract(string str);
|
||||||
|
|
||||||
// copies src.ptr content to new string and adds \0 at the end
|
// copies src.ptr content to new string and adds \0 at the end
|
||||||
string string_copy(allocator_ptr al, string src);
|
string string_copy(string src);
|
||||||
|
|
||||||
// compares two strings, NullPtr-friendly
|
// compares two strings, NullPtr-friendly
|
||||||
bool string_compare(string str0, string str1);
|
bool string_compare(string str0, string str1);
|
||||||
|
|
||||||
// creates new string which is reversed variant of <s>
|
// creates new string which is reversed variant of <s>
|
||||||
string string_reverse(allocator_ptr al, string s);
|
string string_reverse(string s);
|
||||||
|
|
||||||
#if __cplusplus
|
#if __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ extern "C" {
|
|||||||
#include "type_system/type_system.h"
|
#include "type_system/type_system.h"
|
||||||
#include "../kprint/kprintf.h"
|
#include "../kprint/kprintf.h"
|
||||||
#include "endian.h"
|
#include "endian.h"
|
||||||
#include "memory/memory.h"
|
|
||||||
|
|
||||||
#if __cplusplus
|
#if __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,16 +11,17 @@ u32 cptr_length(const char* str){
|
|||||||
}
|
}
|
||||||
|
|
||||||
// allocates new char[] and copies src there
|
// allocates new char[] and copies src there
|
||||||
char* cptr_copy(allocator_ptr al, const char* src){
|
char* cptr_copy(const char* src){
|
||||||
u32 len=cptr_length(src)+1;
|
u32 len=cptr_length(src)+1;
|
||||||
char* dst=allocator_alloc(al, len);
|
char* dst=malloc(len);
|
||||||
memcpy(dst, src, len);
|
while(len--!=0)
|
||||||
|
dst[len]=src[len];
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
// multiplies char n times
|
// multiplies char n times
|
||||||
char* char_multiply(allocator_ptr al, char c, u32 n){
|
char* char_multiply(char c, u32 n){
|
||||||
char* rez=allocator_alloc(al, n+1);
|
char* rez=malloc(n+1);
|
||||||
rez[n]=0;
|
rez[n]=0;
|
||||||
while(n--!=0)
|
while(n--!=0)
|
||||||
rez[n]=c;
|
rez[n]=c;
|
||||||
@@ -130,9 +131,9 @@ i32 cptr_seekCharReverse(const char* src, char fragment, u32 startIndex, u32 see
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* __cptr_concat(allocator_ptr al, u32 n, ...){
|
char* __cptr_concat(u32 n, ...){
|
||||||
char** strs=(char**)allocator_alloc(al, n*sizeof(char*));
|
char** strs=(char**)malloc(n*sizeof(char*));
|
||||||
u32* lengths=allocator_alloc(al, n*sizeof(u32));
|
u32* lengths=malloc(n*sizeof(u32));
|
||||||
u32 totalLength=0;
|
u32 totalLength=0;
|
||||||
|
|
||||||
// reading args from va_list
|
// reading args from va_list
|
||||||
@@ -148,41 +149,41 @@ char* __cptr_concat(allocator_ptr al, u32 n, ...){
|
|||||||
va_end(vl);
|
va_end(vl);
|
||||||
|
|
||||||
// allocating memory for output value
|
// allocating memory for output value
|
||||||
char* totality=allocator_alloc(al, totalLength+1);
|
char* totality=malloc(totalLength+1);
|
||||||
char* output=totality;
|
char* output=totality;
|
||||||
totality[totalLength]=0;
|
totality[totalLength]=0;
|
||||||
|
|
||||||
// copying content of all strings to rezult
|
// copying content of all strings to result
|
||||||
for(u16 k=0; k<n; k++){
|
for(u16 k=0; k<n; k++){
|
||||||
memcpy(totality, strs[k], lengths[k]);
|
memcpy(totality, strs[k], lengths[k]);
|
||||||
totality+=lengths[k];
|
totality+=lengths[k];
|
||||||
}
|
}
|
||||||
|
|
||||||
allocator_free(al, lengths);
|
free(strs);
|
||||||
allocator_free(al, strs);
|
free(lengths);
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* cptr_toLower(allocator_ptr al, const char* src) {
|
char* cptr_toLower(const char* src) {
|
||||||
u32 length=cptr_length(src);
|
u32 length=cptr_length(src);
|
||||||
char *p=allocator_alloc(al, length+1);
|
char *p=malloc(length+1);
|
||||||
p[length]=0;
|
p[length]=0;
|
||||||
for(u32 i=0; i<length; i++)
|
for(u32 i=0; i<length; i++)
|
||||||
p[i]=tolower(src[i]);
|
p[i]=tolower(src[i]);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* cptr_toUpper(allocator_ptr al, const char* src) {
|
char* cptr_toUpper(const char* src) {
|
||||||
u32 length=cptr_length(src);
|
u32 length=cptr_length(src);
|
||||||
char *p=allocator_alloc(al, length+1);
|
char *p=malloc(length+1);
|
||||||
p[length]=0;
|
p[length]=0;
|
||||||
for(u32 i=0; i<length; i++)
|
for(u32 i=0; i<length; i++)
|
||||||
p[i]=toupper(src[i]);
|
p[i]=toupper(src[i]);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* cptr_replaceCharIn(allocator_ptr al, const char* src, char c_old, char c_new, u32 startIndex, u32 seekLength){
|
char* cptr_replaceCharIn(const char* src, char c_old, char c_new, u32 startIndex, u32 seekLength){
|
||||||
char* rzlt=cptr_copy(al, src);
|
char* rzlt=cptr_copy(src);
|
||||||
for(u32 i=startIndex; i!=seekLength && src[i]!=0; i++){
|
for(u32 i=startIndex; i!=seekLength && src[i]!=0; i++){
|
||||||
if(src[i]==c_old)
|
if(src[i]==c_old)
|
||||||
rzlt[i]=c_new;
|
rzlt[i]=c_new;
|
||||||
@@ -190,10 +191,8 @@ char* cptr_replaceCharIn(allocator_ptr al, const char* src, char c_old, char c_n
|
|||||||
return rzlt;
|
return rzlt;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* cptr_replaceIn(allocator_ptr al, const char* src, const char* str_old, const char* str_new, u32 startIndex, u32 seekLength){
|
char* cptr_replaceIn(const char* src, const char* str_old, const char* str_new, u32 startIndex, u32 seekLength){
|
||||||
StringBuilder _sb;
|
StringBuilder* sb=StringBuilder_create();
|
||||||
StringBuilder* sb=&_sb;
|
|
||||||
StringBuilder_construct(sb, al);
|
|
||||||
const u32 str_old_len=cptr_length(str_old);
|
const u32 str_old_len=cptr_length(str_old);
|
||||||
const u32 str_new_len=cptr_length(str_new);
|
const u32 str_new_len=cptr_length(str_new);
|
||||||
i32 i=startIndex;
|
i32 i=startIndex;
|
||||||
@@ -206,6 +205,6 @@ char* cptr_replaceIn(allocator_ptr al, const char* src, const char* str_old, con
|
|||||||
u32 src_remains_len=cptr_length(src);
|
u32 src_remains_len=cptr_length(src);
|
||||||
if(src_remains_len>0)
|
if(src_remains_len>0)
|
||||||
StringBuilder_append_string(sb, (string){.ptr=(char*)src, .length=src_remains_len});
|
StringBuilder_append_string(sb, (string){.ptr=(char*)src, .length=src_remains_len});
|
||||||
string rezult=StringBuilder_build(sb);
|
string result=StringBuilder_build(sb);
|
||||||
return rezult.ptr;
|
return result.ptr;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,13 +5,12 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "std.h"
|
#include "std.h"
|
||||||
#include "memory/allocator_base.h"
|
|
||||||
|
|
||||||
// returns length of char buffer (without \0)
|
// returns length of char buffer (without \0)
|
||||||
u32 cptr_length(const char* str);
|
u32 cptr_length(const char* str);
|
||||||
|
|
||||||
// allocates new char[] and copies src there
|
// allocates new char[] and copies src there
|
||||||
char* cptr_copy(allocator_ptr al, const char* src);
|
char* cptr_copy(const char* src);
|
||||||
|
|
||||||
bool cptr_equals(const char* key0, const char* key1);
|
bool cptr_equals(const char* key0, const char* key1);
|
||||||
|
|
||||||
@@ -20,7 +19,7 @@ bool cptr_startsWith(const char* src, const char* fragment);
|
|||||||
bool cptr_endsWith(const char* src, const char* fragment);
|
bool cptr_endsWith(const char* src, const char* fragment);
|
||||||
|
|
||||||
// multiplies char n times
|
// multiplies char n times
|
||||||
char* char_multiply(allocator_ptr al, char c, u32 n);
|
char* char_multiply(char c, u32 n);
|
||||||
|
|
||||||
/// @param startIndex 0 ... src length
|
/// @param startIndex 0 ... src length
|
||||||
/// @param seekLength 0 ... -1
|
/// @param seekLength 0 ... -1
|
||||||
@@ -64,29 +63,33 @@ static inline i32 cptr_lastIndexOfChar(const char* src, char fragment)
|
|||||||
|
|
||||||
|
|
||||||
static inline bool cptr_contains(const char* src, const char* fragment){
|
static inline bool cptr_contains(const char* src, const char* fragment){
|
||||||
return cptr_seek(src, fragment, 0, -1) +1;
|
return cptr_seek(src, fragment, 0, -1) != -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* __cptr_concat(allocator_ptr al, u32 n, ...);
|
static inline bool cptr_containsChar(const char* src, char c){
|
||||||
#define cptr_concat(ALLOCATOR, STR...) __cptr_concat(ALLOCATOR, count_args(STR), STR)
|
return cptr_seekChar(src, c, 0, -1) != -1;
|
||||||
|
}
|
||||||
|
|
||||||
char* cptr_toLower(allocator_ptr al, const char* src);
|
char* __cptr_concat(u32 n, ...);
|
||||||
char* cptr_toUpper(allocator_ptr al, const char* src);
|
#define cptr_concat(STR...) __cptr_concat(count_args(STR), STR)
|
||||||
|
|
||||||
|
char* cptr_toLower(const char* src);
|
||||||
|
char* cptr_toUpper(const char* src);
|
||||||
|
|
||||||
/// @param startIndex 0 ... src length
|
/// @param startIndex 0 ... src length
|
||||||
/// @param seekLength 0 ... -1
|
/// @param seekLength 0 ... -1
|
||||||
/// @return <src> with <str_old> replaced by <str_new> or empty cstring if <str_old> not found
|
/// @return <src> with <str_old> replaced by <str_new> or empty cstring if <str_old> not found
|
||||||
char* cptr_replaceIn(allocator_ptr al, const char* src, const char* str_old, const char* str_new, u32 startIndex, u32 seekLength);
|
char* cptr_replaceIn(const char* src, const char* str_old, const char* str_new, u32 startIndex, u32 seekLength);
|
||||||
/// @param startIndex 0 ... src length
|
/// @param startIndex 0 ... src length
|
||||||
/// @param seekLength 0 ... -1
|
/// @param seekLength 0 ... -1
|
||||||
/// @return <src> with <c_old> replaced by <c_new> or empty cstring if <str_old> not found
|
/// @return <src> with <c_old> replaced by <c_new> or empty cstring if <str_old> not found
|
||||||
char* cptr_replaceCharIn(allocator_ptr al, const char* src, char c_old, char c_new, u32 startIndex, u32 seekLength);
|
char* cptr_replaceCharIn(const char* src, char c_old, char c_new, u32 startIndex, u32 seekLength);
|
||||||
|
|
||||||
static inline char* cptr_replace(allocator_ptr al, const char* src, const char* str_old, const char* str_new)
|
static inline char* cptr_replace(const char* src, const char* str_old, const char* str_new)
|
||||||
{ return cptr_replaceIn(al, src, str_old, str_new, 0, -1); }
|
{ return cptr_replaceIn(src, str_old, str_new, 0, -1); }
|
||||||
|
|
||||||
static inline char* cptr_replaceChar(allocator_ptr al, const char* src, char c_old, char c_new)
|
static inline char* cptr_replaceChar(const char* src, char c_old, char c_new)
|
||||||
{ return cptr_replaceCharIn(al, src, c_old, c_new, 0, -1); }
|
{ return cptr_replaceCharIn(src, c_old, c_new, 0, -1); }
|
||||||
|
|
||||||
#if __cplusplus
|
#if __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,4 @@
|
|||||||
#include "std.h"
|
#include "base.h"
|
||||||
#include "errors.h"
|
|
||||||
#include "cptr.h"
|
|
||||||
#include "../kprint/kprintf.h"
|
|
||||||
|
|
||||||
char* errname(ErrorId err){
|
char* errname(ErrorId err){
|
||||||
switch(err){
|
switch(err){
|
||||||
@@ -21,26 +18,26 @@ char* errname(ErrorId err){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ERRMSG_MAXLENGTH 1024
|
#define ERRMSG_MAXLENGTH 4096
|
||||||
|
|
||||||
char* __genErrMsg(const char* errmsg, const char* srcfile, i32 line, const char* funcname){
|
char* __genErrMsg(const char* errmsg, const char* srcfile, i32 line, const char* funcname){
|
||||||
size_t bufsize=ERRMSG_MAXLENGTH;
|
size_t bufsize=ERRMSG_MAXLENGTH;
|
||||||
char* rezult=malloc(bufsize);
|
char* result=malloc(bufsize);
|
||||||
sprintf_s(rezult,bufsize,"[%s:%d] %s() throwed error: %s",srcfile,line,funcname,errmsg);
|
ksprintf(result,bufsize,"[%s:%d] %s() throwed error: %s",srcfile,line,funcname,errmsg);
|
||||||
return rezult;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* __extendErrMsg(const char* errmsg, const char* srcfile, i32 line, const char* funcname){
|
char* __extendErrMsg(const char* errmsg, const char* srcfile, i32 line, const char* funcname){
|
||||||
size_t bufsize=cptr_length(errmsg)+ERRMSG_MAXLENGTH;
|
size_t bufsize=cptr_length(errmsg)+ERRMSG_MAXLENGTH;
|
||||||
char* rezult=malloc(bufsize);
|
char* result=malloc(bufsize);
|
||||||
sprintf_s(rezult,bufsize,"%s\n \\___[%s:%d] %s()",errmsg,srcfile,line,funcname);
|
ksprintf(result,bufsize,"%s\n \\___[%s:%d] %s()",errmsg,srcfile,line,funcname);
|
||||||
free(errmsg);
|
free(errmsg);
|
||||||
return rezult;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Maybe_destruct(Maybe e){
|
void Maybe_free(Maybe e){
|
||||||
free(e.errmsg);
|
free(e.errmsg);
|
||||||
Unitype_destruct(&e.value);
|
Unitype_free(e.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void printMaybe(Maybe e){
|
void printMaybe(Maybe e){
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ STRUCT(Maybe,
|
|||||||
// .value .errmsg
|
// .value .errmsg
|
||||||
#define MaybeNull (Maybe){UniNull, NULL}
|
#define MaybeNull (Maybe){UniNull, NULL}
|
||||||
|
|
||||||
void Maybe_destruct(Maybe e);
|
void Maybe_free(Maybe e);
|
||||||
void printMaybe(Maybe e);
|
void printMaybe(Maybe e);
|
||||||
|
|
||||||
|
|
||||||
@@ -60,10 +60,10 @@ char* __unknownErr( );
|
|||||||
__RETURN_EXCEPTION(((char*)__genErrMsg(E, __FILE__,__LINE__,__func__))); \
|
__RETURN_EXCEPTION(((char*)__genErrMsg(E, __FILE__,__LINE__,__func__))); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define try_cpp(_funcCall, _rezult, freeMem) Maybe _rezult=_funcCall; if(_rezult.errmsg){ \
|
#define try_cpp(_funcCall, _result, freeMem) Maybe _result=_funcCall; if(_result.errmsg){ \
|
||||||
freeMem; \
|
freeMem; \
|
||||||
_rezult.errmsg=__extendErrMsg(_rezult.errmsg, __FILE__,__LINE__,__func__); \
|
_result.errmsg=__extendErrMsg(_result.errmsg, __FILE__,__LINE__,__func__); \
|
||||||
return _rezult; \
|
return _result; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
@@ -73,16 +73,17 @@ char* __unknownErr( );
|
|||||||
__RETURN_EXCEPTION(((char*)__genErrMsg((__stringify_err(E)), __FILE__,__LINE__,__func__))); \
|
__RETURN_EXCEPTION(((char*)__genErrMsg((__stringify_err(E)), __FILE__,__LINE__,__func__))); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define try(_funcCall, _rezult, freeMem) Maybe _rezult=_funcCall; if(_rezult.errmsg){ \
|
#define try(_funcCall, _result, freeMem) Maybe _result=_funcCall; if(_result.errmsg){ \
|
||||||
freeMem; \
|
freeMem; \
|
||||||
_rezult.errmsg=__extendErrMsg(_rezult.errmsg, __FILE__,__LINE__,__func__); \
|
_result.errmsg=__extendErrMsg(_result.errmsg, __FILE__,__LINE__,__func__); \
|
||||||
return _rezult; \
|
return _result; \
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define tryLast(_funcCall, _rezult, ON_EXIT) Maybe _rezult=_funcCall; if(_rezult.errmsg){ \
|
#define tryLast(_funcCall, _result, ON_EXIT) Maybe _result=_funcCall; if(_result.errmsg){ \
|
||||||
_rezult.errmsg=__extendErrMsg(_rezult.errmsg, __FILE__,__LINE__,__func__); \
|
ON_EXIT; \
|
||||||
__EXIT(_rezult.errmsg); \
|
_result.errmsg=__extendErrMsg(_result.errmsg, __FILE__,__LINE__,__func__); \
|
||||||
|
__EXIT(_result.errmsg); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#if __cplusplus
|
#if __cplusplus
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
#include "allocators_internal.h"
|
|
||||||
|
|
||||||
void* CstdAllocator_alloc(allocator_ptr self, alloc_size_t size){
|
|
||||||
// assert(size>0);
|
|
||||||
return malloc(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CstdAllocator_free(allocator_ptr self, void* ptr){
|
|
||||||
// assert(ptr!=NULL);
|
|
||||||
free(ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
kt_define(CstdAllocator, NULL, NULL);
|
|
||||||
|
|
||||||
CstdAllocator CstdAllocator_instance=(CstdAllocator){.base.alloc_f=CstdAllocator_alloc, .base.free_f=CstdAllocator_free};
|
|
||||||
@@ -1,102 +0,0 @@
|
|||||||
#include "allocators_internal.h"
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
|
|
||||||
#define default_chunks_per_allocation 16
|
|
||||||
// growing chunk array size
|
|
||||||
#define new_max_chunks_count ( default_chunks_per_allocation*(self->chunks_count/16 == 0) + \
|
|
||||||
default_chunks_per_allocation*add_padding(self->chunks_count/2)/4 )
|
|
||||||
|
|
||||||
#define default_chunk_size 1024
|
|
||||||
// growing chunk size
|
|
||||||
#define new_chunk_size ( default_chunk_size*(self->chunks_count/16 == 0) + \
|
|
||||||
default_chunk_size*add_padding(self->chunks_count/8) )
|
|
||||||
|
|
||||||
#define chunk_alloc(SZ, OCCUPIED) (MemoryChunk){ .data=malloc(SZ), .size=SZ, .occupied_size=OCCUPIED }
|
|
||||||
#define curr_chunk (self->chunks+self->curr_chunk_i)
|
|
||||||
|
|
||||||
__attribute__ ((noinline)) void* ___alloc_realloc_chunk(LinearAllocator* self, alloc_size_t alloc_size){
|
|
||||||
free(curr_chunk->data);
|
|
||||||
*curr_chunk=chunk_alloc(alloc_size, alloc_size);
|
|
||||||
return curr_chunk->data;
|
|
||||||
}
|
|
||||||
|
|
||||||
__attribute__ ((noinline)) void* __alloc_new_chunk(LinearAllocator* self, alloc_size_t alloc_size){
|
|
||||||
self->curr_chunk_i++;
|
|
||||||
// next chunk has been already allocated
|
|
||||||
if(self->curr_chunk_i < self->chunks_count)
|
|
||||||
return curr_chunk->data;
|
|
||||||
|
|
||||||
// self->chunks array is full
|
|
||||||
if(self->chunks_count == self->max_chunks_count){
|
|
||||||
self->max_chunks_count = new_max_chunks_count;
|
|
||||||
self->chunks = realloc(self->chunks, sizeof(MemoryChunk) * self->max_chunks_count);
|
|
||||||
}
|
|
||||||
|
|
||||||
// new chunk allocation
|
|
||||||
self->chunks_count++;
|
|
||||||
alloc_size_t _new_chunk_size= alloc_size > new_chunk_size ? alloc_size : new_chunk_size;
|
|
||||||
*curr_chunk=chunk_alloc(_new_chunk_size, alloc_size);
|
|
||||||
return curr_chunk->data;
|
|
||||||
}
|
|
||||||
|
|
||||||
void* LinearAllocator_alloc(allocator_ptr _self, alloc_size_t alloc_size){
|
|
||||||
// assert(_self!=NULL);
|
|
||||||
// assert(alloc_size>0);
|
|
||||||
LinearAllocator* self = (LinearAllocator*)_self;
|
|
||||||
alloc_size=add_padding(alloc_size);
|
|
||||||
|
|
||||||
// aligned alloc_size can fit into the current chunk
|
|
||||||
if(curr_chunk->occupied_size + alloc_size <= curr_chunk->size){
|
|
||||||
void* data_ptr=curr_chunk->data + curr_chunk->occupied_size;
|
|
||||||
curr_chunk->occupied_size += alloc_size;
|
|
||||||
return data_ptr;
|
|
||||||
}
|
|
||||||
// reallocation of current chunk because it is clean
|
|
||||||
if(curr_chunk->occupied_size == 0){
|
|
||||||
// It is very unefficient operation.
|
|
||||||
// If it happens not only in the first chunk, code have to be refactored
|
|
||||||
assert(self->curr_chunk_i==0);
|
|
||||||
return ___alloc_realloc_chunk(self, alloc_size);
|
|
||||||
}
|
|
||||||
// creation of a new chunk
|
|
||||||
else {
|
|
||||||
return __alloc_new_chunk(self, alloc_size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void LinearAllocator_free(allocator_ptr _self, void* ptr){
|
|
||||||
// LinearAllocator can't free pointers
|
|
||||||
}
|
|
||||||
|
|
||||||
void LinearAllocator_destruct(LinearAllocator* self){
|
|
||||||
// assert(_self!=NULL);
|
|
||||||
u32 size=0;
|
|
||||||
u32 oc_size=0;
|
|
||||||
for(u32 chunk_i=0; chunk_i < self->chunks_count; chunk_i++){
|
|
||||||
free(self->chunks[chunk_i].data);
|
|
||||||
size+=self->chunks[chunk_i].size;
|
|
||||||
oc_size+=self->chunks[chunk_i].occupied_size;
|
|
||||||
}
|
|
||||||
printf("\e[35m%u/%u\n",oc_size,size);
|
|
||||||
free(self->chunks);
|
|
||||||
self->chunks=NULL;
|
|
||||||
self->chunks_count=0;
|
|
||||||
self->curr_chunk_i=0;
|
|
||||||
self->max_chunks_count=0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void LinearAllocator_construct(LinearAllocator* self, alloc_size_t starting_size){
|
|
||||||
assert(self!=NULL);
|
|
||||||
assert(starting_size>0);
|
|
||||||
self->base.alloc_f=LinearAllocator_alloc;
|
|
||||||
self->base.free_f=LinearAllocator_free;
|
|
||||||
|
|
||||||
self->curr_chunk_i=0;
|
|
||||||
self->chunks_count=1;
|
|
||||||
self->max_chunks_count=new_max_chunks_count;
|
|
||||||
self->chunks=malloc(sizeof(MemoryChunk) * new_max_chunks_count);
|
|
||||||
self->chunks[0]=chunk_alloc(starting_size, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
kt_define(LinearAllocator, (destruct_t)LinearAllocator_destruct, NULL)
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
#include "allocators_internal.h"
|
|
||||||
|
|
||||||
#define chunk_alloc(SZ) (MemoryChunk){ .data=malloc(SZ), .size=SZ, .occupied_size=0 }
|
|
||||||
#define linear self->base
|
|
||||||
#define curr_chunk (linear.chunks+linear.curr_chunk_i)
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
alloc_size_t data_size;
|
|
||||||
} AllocationHeader;
|
|
||||||
|
|
||||||
void* StackingAllocator_alloc(allocator_ptr _self, alloc_size_t size){
|
|
||||||
assert(_self!=NULL);
|
|
||||||
assert(size>0);
|
|
||||||
StackingAllocator* self = (StackingAllocator*)_self;
|
|
||||||
size=add_padding(size);
|
|
||||||
|
|
||||||
// allocates memory with header struct before data
|
|
||||||
AllocationHeader* header_ptr=LinearAllocator_alloc(_self, sizeof(AllocationHeader) + size);
|
|
||||||
void* data_ptr = (void*)header_ptr + sizeof(AllocationHeader);
|
|
||||||
header_ptr->data_size = size;
|
|
||||||
|
|
||||||
self->allocations_count++;
|
|
||||||
return data_ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void StackingAllocator_free(allocator_ptr _self, void* data_ptr){
|
|
||||||
assert(_self!=NULL);
|
|
||||||
assert(data_ptr!=NULL);
|
|
||||||
StackingAllocator* self = (StackingAllocator*)_self;
|
|
||||||
AllocationHeader* header_ptr = data_ptr - sizeof(AllocationHeader);
|
|
||||||
// TODO check is data_ptr pointer to the last allocation
|
|
||||||
// chunk is empty
|
|
||||||
if(curr_chunk->occupied_size==0){
|
|
||||||
// isn't the first chunk
|
|
||||||
assert(linear.curr_chunk_i>0);
|
|
||||||
linear.curr_chunk_i--;
|
|
||||||
}
|
|
||||||
|
|
||||||
alloc_size_t allocation_size=header_ptr->data_size+sizeof(*header_ptr);
|
|
||||||
// data must fit in chunk
|
|
||||||
assert(allocation_size <= curr_chunk->occupied_size);
|
|
||||||
curr_chunk->occupied_size -= allocation_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
void StackingAllocator_destruct(StackingAllocator* self){
|
|
||||||
LinearAllocator_destruct(&self->base);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StackingAllocator_construct(StackingAllocator* self, alloc_size_t starting_size){
|
|
||||||
assert(self!=NULL);
|
|
||||||
assert(starting_size>0);
|
|
||||||
LinearAllocator_construct(&linear, starting_size);
|
|
||||||
linear.base.alloc_f=StackingAllocator_alloc;
|
|
||||||
linear.base.free_f=StackingAllocator_free;
|
|
||||||
self->allocations_count=0;
|
|
||||||
}
|
|
||||||
|
|
||||||
kt_define(StackingAllocator, (destruct_t)StackingAllocator_destruct, NULL)
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "../std.h"
|
|
||||||
|
|
||||||
///////////////////////////////////////////
|
|
||||||
// MemoryAllocator interface //
|
|
||||||
///////////////////////////////////////////
|
|
||||||
|
|
||||||
typedef u32 alloc_size_t;
|
|
||||||
typedef struct MemoryAllocator MemoryAllocator;
|
|
||||||
typedef MemoryAllocator* allocator_ptr;
|
|
||||||
|
|
||||||
typedef void* (*alloc_t)(allocator_ptr, alloc_size_t size);
|
|
||||||
typedef void (*free_t)(allocator_ptr, void* ptr);
|
|
||||||
|
|
||||||
typedef struct MemoryAllocator {
|
|
||||||
alloc_t alloc_f;
|
|
||||||
free_t free_f;
|
|
||||||
} MemoryAllocator;
|
|
||||||
|
|
||||||
#define allocator_alloc(ALLOCATOR, SIZE) \
|
|
||||||
((allocator_ptr)ALLOCATOR)->alloc_f(ALLOCATOR, SIZE)
|
|
||||||
#define allocator_free(ALLOCATOR, PTR) \
|
|
||||||
((allocator_ptr)ALLOCATOR)->free_f(ALLOCATOR, PTR)
|
|
||||||
#define allocator_destruct(ALLOCATOR) \
|
|
||||||
((allocator_ptr)ALLOCATOR)->destruct_f(ALLOCATOR)
|
|
||||||
|
|
||||||
void* allocator_transfer(allocator_ptr src, allocator_ptr dest, void* data, alloc_size_t data_size);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
#include "memory.h"
|
|
||||||
|
|
||||||
void* allocator_transfer(allocator_ptr src, allocator_ptr dest, void* data, alloc_size_t data_size)
|
|
||||||
{
|
|
||||||
void* transfered=allocator_alloc(dest, data_size);
|
|
||||||
memcpy(transfered, data, data_size);
|
|
||||||
allocator_free(src, data);
|
|
||||||
return transfered;
|
|
||||||
}
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#if __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "../std.h"
|
|
||||||
#include "../type_system/ktDescriptor.h"
|
|
||||||
#include "allocator_base.h"
|
|
||||||
|
|
||||||
///////////////////////////////////////////
|
|
||||||
// CstdAllocator //
|
|
||||||
///////////////////////////////////////////
|
|
||||||
// Just wrapper for malloc() and free() //
|
|
||||||
///////////////////////////////////////////
|
|
||||||
|
|
||||||
STRUCT(CstdAllocator,
|
|
||||||
MemoryAllocator base;
|
|
||||||
);
|
|
||||||
|
|
||||||
extern CstdAllocator CstdAllocator_instance;
|
|
||||||
#define CstdAllocator_instPtr (allocator_ptr)(&CstdAllocator_instance)
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////
|
|
||||||
// LinearAllocator //
|
|
||||||
///////////////////////////////////////////
|
|
||||||
// Can't free allocated memory. //
|
|
||||||
// Allocates new memory chunk when the //
|
|
||||||
// current is full. //
|
|
||||||
///////////////////////////////////////////
|
|
||||||
|
|
||||||
typedef struct MemoryChunk {
|
|
||||||
void* data;
|
|
||||||
alloc_size_t size;
|
|
||||||
alloc_size_t occupied_size; /* free memory position in the current chunk. */
|
|
||||||
} MemoryChunk;
|
|
||||||
|
|
||||||
STRUCT(LinearAllocator,
|
|
||||||
MemoryAllocator base;
|
|
||||||
MemoryChunk* chunks; /* MemoryChunk[max_chunks_count] */
|
|
||||||
u32 chunks_count; /* allocated chunks */
|
|
||||||
u32 max_chunks_count; /* chunks that can be allocated without reallocating .chunks */
|
|
||||||
u32 curr_chunk_i; /* index of current chunk in .chunks, can be < .chunks_count */
|
|
||||||
);
|
|
||||||
|
|
||||||
void LinearAllocator_construct(LinearAllocator* self, alloc_size_t starting_size);
|
|
||||||
void LinearAllocator_destruct(LinearAllocator* self);
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////
|
|
||||||
// StackingAllocator //
|
|
||||||
///////////////////////////////////////////
|
|
||||||
// The same as Linear, but can free //
|
|
||||||
// allocations in reverse order //
|
|
||||||
///////////////////////////////////////////
|
|
||||||
|
|
||||||
STRUCT(StackingAllocator,
|
|
||||||
LinearAllocator base;
|
|
||||||
u32 allocations_count;
|
|
||||||
);
|
|
||||||
|
|
||||||
void StackingAllocator_construct(StackingAllocator* self, alloc_size_t starting_size);
|
|
||||||
void StackingAllocator_destruct(StackingAllocator* self);
|
|
||||||
|
|
||||||
|
|
||||||
#if __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
#include <assert.h>
|
|
||||||
#include "memory.h"
|
|
||||||
|
|
||||||
void* LinearAllocator_alloc(allocator_ptr _self, alloc_size_t size);
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
#include "allocators.h"
|
|
||||||
|
|
||||||
// addresses must be aligned to this value
|
|
||||||
#define memory_align sizeof(void*)
|
|
||||||
// adds padding if memory_align if N isn't a multiple of memory_aligh
|
|
||||||
#define add_padding(N) (N + (N%memory_align != 0)*(memory_align - N%memory_align))
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////
|
|
||||||
// NOT AN ALLOCATOR //
|
|
||||||
///////////////////////////////////////////
|
|
||||||
// Macros to embed internal allocator //
|
|
||||||
// into some collection struct. //
|
|
||||||
///////////////////////////////////////////
|
|
||||||
|
|
||||||
/// call this macro inside struct declaration
|
|
||||||
#define InternalAllocator_declare(AL_TYPE) \
|
|
||||||
AL_TYPE _internal_al; \
|
|
||||||
allocator_ptr _internal_al_ptr;
|
|
||||||
|
|
||||||
/// get pointer to allocator
|
|
||||||
#define InternalAllocator_getPtr(STRUCT_PTR) ((STRUCT_PTR)->_internal_al_ptr)
|
|
||||||
|
|
||||||
/// true if allocator is stored inside the struct, otherwise false
|
|
||||||
#define InternalAllocator_isInternal(STRUCT_PTR) (bool)((STRUCT_PTR)->_internal_al_ptr == (allocator_ptr)&(STRUCT_PTR)->_internal_al)
|
|
||||||
|
|
||||||
/// set ptr to external allocator
|
|
||||||
#define InternalAllocator_setExternal(STRUCT_PTR, EXT_AL_PTR) ((STRUCT_PTR)->_internal_al_ptr = EXT_AL_PTR);
|
|
||||||
|
|
||||||
/// create internal allocator and set ptr to it
|
|
||||||
#define InternalAllocator_construct(STRUCT_PTR, TYPE, CTOR_ARGS...) { \
|
|
||||||
TYPE##_construct(&(STRUCT_PTR)->_internal_al, CTOR_ARGS); \
|
|
||||||
(STRUCT_PTR)->_internal_al_ptr = (allocator_ptr)&(STRUCT_PTR)->_internal_al; \
|
|
||||||
}
|
|
||||||
|
|
||||||
/// if EXT_AL_PTR isn't null, set external allocator, otherwise create new
|
|
||||||
#define InternalAllocator_setExternalOrConstruct(STRUCT_PTR, EXT_AL_PTR, TYPE, CTOR_ARGS...) \
|
|
||||||
if(EXT_AL_PTR!=NULL) InternalAllocator_setExternal(STRUCT_PTR, EXT_AL_PTR) \
|
|
||||||
else InternalAllocator_construct(STRUCT_PTR, TYPE, CTOR_ARGS)
|
|
||||||
|
|
||||||
#define InternalAllocator_destructIfInternal(TYPE, STRUCT_PTR) {\
|
|
||||||
if(InternalAllocator_isInternal(STRUCT_PTR)) \
|
|
||||||
TYPE##_destruct((TYPE*)InternalAllocator_getPtr(STRUCT_PTR)); \
|
|
||||||
}
|
|
||||||
@@ -13,8 +13,7 @@
|
|||||||
tni=1; \
|
tni=1; \
|
||||||
} else tni=2; \
|
} else tni=2; \
|
||||||
kprintf("\e[93moperation \e[94m%s\e[93m lasted \e[94m%f \e[93m%s\n", \
|
kprintf("\e[93moperation \e[94m%s\e[93m lasted \e[94m%f \e[93m%s\n", \
|
||||||
opname, t, tnames[tni]); \
|
opname, t, tnames[tni]);
|
||||||
fflush(stdout);
|
|
||||||
|
|
||||||
#ifdef CLOCK_REALTIME
|
#ifdef CLOCK_REALTIME
|
||||||
/// executes codeblock and prints execution time
|
/// executes codeblock and prints execution time
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ extern "C" {
|
|||||||
#include <setjmp.h>
|
#include <setjmp.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
typedef int8_t i8;
|
typedef int8_t i8;
|
||||||
typedef uint8_t u8;
|
typedef uint8_t u8;
|
||||||
@@ -25,7 +26,7 @@ typedef int64_t i64;
|
|||||||
typedef uint64_t u64;
|
typedef uint64_t u64;
|
||||||
typedef float f32;
|
typedef float f32;
|
||||||
typedef double f64;
|
typedef double f64;
|
||||||
/// anonymous pointer without specified destruct() func
|
/// anonymous pointer without specified freeMembers() func
|
||||||
typedef void* Pointer;
|
typedef void* Pointer;
|
||||||
|
|
||||||
// Usually bool from stdbool.h is defined as macro,
|
// Usually bool from stdbool.h is defined as macro,
|
||||||
@@ -38,14 +39,6 @@ typedef u8 bool;
|
|||||||
#define false 0
|
#define false 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef memcpy
|
|
||||||
extern void* memcpy(void *dest, const void * src, size_t n);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef typeof
|
|
||||||
#define typeof __typeof__
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define dbg(N) kprintf("\e[95m%d\n",N)
|
#define dbg(N) kprintf("\e[95m%d\n",N)
|
||||||
|
|
||||||
#define nameof(V) #V
|
#define nameof(V) #V
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ and register it.
|
|||||||
|
|
||||||
## type descriptors
|
## type descriptors
|
||||||
|
|
||||||
Every registered type should have it's own descriptor (`ktDescriptor`). It's a struct, which contains some information about type and pointers to some specific functions for this type (`toString`, `destruct`).
|
Every registered type should have it's own descriptor (`ktDescriptor`). It's a struct, which contains some information about type and pointers to some specific functions for this type (`toString`, `freeMembers`).
|
||||||
|
|
||||||
## type registration
|
## type registration
|
||||||
|
|
||||||
|
|||||||
@@ -5,14 +5,14 @@
|
|||||||
|
|
||||||
// accepts char* (ptr to char) and char* (ptr to string)
|
// accepts char* (ptr to char) and char* (ptr to string)
|
||||||
// uses format kp_s and kp_c to determine what type is <c> argument
|
// uses format kp_s and kp_c to determine what type is <c> argument
|
||||||
char* __toString_char(allocator_ptr al, void* c, u32 fmt) {
|
char* __toString_char(void* c, u32 fmt) {
|
||||||
// *c=char*
|
// *c=char*
|
||||||
if(kp_fmt_dataFormat(fmt)==kp_s){
|
if(kp_fmt_dataFormat(fmt)==kp_s){
|
||||||
return cptr_copy(al, (char*)c); // to avoid segmentation fault on free() when *c allocalet on stack
|
return cptr_copy((char*)c); // to avoid segmentation fault on free() when *c allocalet on stack
|
||||||
}
|
}
|
||||||
// *c=char
|
// *c=char
|
||||||
if(kp_fmt_dataFormat(fmt)==kp_c){
|
if(kp_fmt_dataFormat(fmt)==kp_c){
|
||||||
char* cc=allocator_alloc(al, 2);
|
char* cc=malloc(2);
|
||||||
cc[0]=*(char*)c;
|
cc[0]=*(char*)c;
|
||||||
cc[1]=0;
|
cc[1]=0;
|
||||||
return cc;
|
return cc;
|
||||||
@@ -20,10 +20,10 @@ char* __toString_char(allocator_ptr al, void* c, u32 fmt) {
|
|||||||
else throw(ERR_FORMAT);
|
else throw(ERR_FORMAT);
|
||||||
}
|
}
|
||||||
|
|
||||||
char* __toString_bool(allocator_ptr al, void* c, u32 fmt) {
|
char* __toString_bool(void* c, u32 fmt) {
|
||||||
static const char _strbool[4][6]={ "false", "true\0", "False", "True\0" };
|
static const char _strbool[4][6]={ "false", "true\0", "False", "True\0" };
|
||||||
u8 strind=*(bool*)c==1 + kp_fmt_isUpper(fmt)*2;
|
u8 strind=*(bool*)c==1 + kp_fmt_isUpper(fmt)*2;
|
||||||
char* rez=allocator_alloc(al, 6);
|
char* rez=malloc(6);
|
||||||
rez[0]=_strbool[strind][0];
|
rez[0]=_strbool[strind][0];
|
||||||
rez[1]=_strbool[strind][1];
|
rez[1]=_strbool[strind][1];
|
||||||
rez[2]=_strbool[strind][2];
|
rez[2]=_strbool[strind][2];
|
||||||
@@ -33,7 +33,7 @@ char* __toString_bool(allocator_ptr al, void* c, u32 fmt) {
|
|||||||
return rez;
|
return rez;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* toString_i64(allocator_ptr al, i64 n){
|
char* toString_i64(i64 n){
|
||||||
i64 d=n<0 ? -1*n : n;
|
i64 d=n<0 ? -1*n : n;
|
||||||
char str[32];
|
char str[32];
|
||||||
u8 i=sizeof(str);
|
u8 i=sizeof(str);
|
||||||
@@ -46,10 +46,10 @@ char* toString_i64(allocator_ptr al, i64 n){
|
|||||||
}
|
}
|
||||||
if(n<0)
|
if(n<0)
|
||||||
str[--i]='-';
|
str[--i]='-';
|
||||||
return cptr_copy(al, (char*)str+i);
|
return cptr_copy((char*)str+i);
|
||||||
}
|
}
|
||||||
|
|
||||||
char* toString_u64(allocator_ptr al, u64 n, bool withPostfix, bool uppercase){
|
char* toString_u64(u64 n, bool withPostfix, bool uppercase){
|
||||||
char str[32];
|
char str[32];
|
||||||
u8 i=sizeof(str);
|
u8 i=sizeof(str);
|
||||||
str[--i]=0;
|
str[--i]=0;
|
||||||
@@ -61,30 +61,30 @@ char* toString_u64(allocator_ptr al, u64 n, bool withPostfix, bool uppercase){
|
|||||||
str[--i]='0' + n%10;
|
str[--i]='0' + n%10;
|
||||||
n/=10;
|
n/=10;
|
||||||
}
|
}
|
||||||
return cptr_copy(al, (char*)str+i);
|
return cptr_copy((char*)str+i);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define _toString_float_impl(al, bufsize, maxPrecision) { \
|
#define _toString_float_impl(bufsize, maxPrecision) { \
|
||||||
char str[bufsize]; \
|
char str[bufsize]; \
|
||||||
if(precision>maxPrecision) \
|
if(precision>maxPrecision) \
|
||||||
throw("too big precision"); \
|
throw("too big precision"); \
|
||||||
if(precision==0) \
|
if(precision==0) \
|
||||||
precision=toString_float_default_precision; \
|
precision=toString_float_default_precision; \
|
||||||
i32 cn=sprintf_s(str, bufsize, "%.*f", precision, n); \
|
i32 cn = sprintf_s(str, bufsize, "%.*f", precision, n); \
|
||||||
/* remove trailing zeroes except .0*/ \
|
/* remove trailing zeroes except .0*/ \
|
||||||
while(str[cn-1]=='0' && str[cn-2]!='.') \
|
while(str[cn-1]=='0' && str[cn-2]!='.') \
|
||||||
cn--; \
|
cn--; \
|
||||||
if(withPostfix) \
|
if(withPostfix) \
|
||||||
str[cn++]= uppercase ? 'F' : 'f'; \
|
str[cn++]= uppercase ? 'F' : 'f'; \
|
||||||
str[cn]='\0'; \
|
str[cn]='\0'; \
|
||||||
return cptr_copy(al, str); \
|
return cptr_copy(str); \
|
||||||
}
|
}
|
||||||
|
|
||||||
char* toString_f32(allocator_ptr al, f32 n, u8 precision, bool withPostfix, bool uppercase)
|
char* toString_f32(f32 n, u8 precision, bool withPostfix, bool uppercase)
|
||||||
_toString_float_impl(al, 48, toString_f32_max_precision)
|
_toString_float_impl(48, toString_f32_max_precision)
|
||||||
|
|
||||||
char* toString_f64(allocator_ptr al, f64 n, u8 precision, bool withPostfix, bool uppercase)
|
char* toString_f64(f64 n, u8 precision, bool withPostfix, bool uppercase)
|
||||||
_toString_float_impl(al, 512, toString_f64_max_precision)
|
_toString_float_impl(512, toString_f64_max_precision)
|
||||||
|
|
||||||
#define byte_to_bits(byte) { \
|
#define byte_to_bits(byte) { \
|
||||||
str[cn++]='0' + (u8)((byte>>7)&1); /* 8th bit */ \
|
str[cn++]='0' + (u8)((byte>>7)&1); /* 8th bit */ \
|
||||||
@@ -97,9 +97,9 @@ char* toString_f64(allocator_ptr al, f64 n, u8 precision, bool withPostfix, bool
|
|||||||
str[cn++]='0' + (u8)((byte>>0)&1); /* 1th bit */ \
|
str[cn++]='0' + (u8)((byte>>0)&1); /* 1th bit */ \
|
||||||
}
|
}
|
||||||
|
|
||||||
char* toString_bin(allocator_ptr al, void* _bytes, u32 size, bool inverse, bool withPrefix){
|
char* toString_bin(void* _bytes, u32 size, bool inverse, bool withPrefix){
|
||||||
char* bytes=_bytes;
|
char* bytes=_bytes;
|
||||||
char* str=allocator_alloc(al, size*8 + (withPrefix?2:0) +1);
|
char* str=malloc(size*8 + (withPrefix?2:0) +1);
|
||||||
u32 cn=0; // char number
|
u32 cn=0; // char number
|
||||||
if(withPrefix){
|
if(withPrefix){
|
||||||
str[cn++]='0';
|
str[cn++]='0';
|
||||||
@@ -129,13 +129,13 @@ char _4bitsHex(u8 u, bool uppercase){
|
|||||||
default:
|
default:
|
||||||
dbg(u);
|
dbg(u);
|
||||||
throw("incorrect number");
|
throw("incorrect number");
|
||||||
return (char)219;
|
return 219;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
char* toString_hex(allocator_ptr al, void* _bytes, u32 size, bool inverse, bool withPrefix, bool uppercase){
|
char* toString_hex(void* _bytes, u32 size, bool inverse, bool withPrefix, bool uppercase){
|
||||||
char* bytes=_bytes;
|
char* bytes=_bytes;
|
||||||
char* str=allocator_alloc(al, size*2 + (withPrefix?2:0) + 1);
|
char* str=malloc(size*2 + (withPrefix?2:0) + 1);
|
||||||
u32 cn=0; // char number
|
u32 cn=0; // char number
|
||||||
if(withPrefix){
|
if(withPrefix){
|
||||||
str[cn++]='0';
|
str[cn++]='0';
|
||||||
@@ -163,58 +163,67 @@ char* toString_hex(allocator_ptr al, void* _bytes, u32 size, bool inverse, bool
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#define __toString_i_def(BITS) char* __toString_i##BITS(allocator_ptr al, void* _n, u32 f){ \
|
#define __toString_i32_def(BITS) char* __toString_i##BITS(void* _n, u32 f){ \
|
||||||
switch(kp_fmt_dataFormat(f)){ \
|
switch(kp_fmt_dataFormat(f)){ \
|
||||||
case kp_i: ; \
|
case kp_i: ; \
|
||||||
i##BITS n=*(i##BITS*)_n; \
|
i##BITS n=*(i##BITS*)_n; \
|
||||||
return toString_i64(al,n); \
|
return toString_i64(n); \
|
||||||
case kp_b: \
|
case kp_b: \
|
||||||
return toString_bin(al, _n, BITS/8, getEndian()==LittleEndian, kp_fmt_withPrefix(f)); \
|
return toString_bin(_n, BITS/8, getEndian()==LittleEndian, kp_fmt_withPrefix(f)); \
|
||||||
case kp_h: \
|
case kp_h: \
|
||||||
return toString_hex(al, _n, BITS/8, getEndian()==LittleEndian, kp_fmt_withPrefix(f), kp_fmt_isUpper(f)); \
|
return toString_hex(_n, BITS/8, getEndian()==LittleEndian, kp_fmt_withPrefix(f), kp_fmt_isUpper(f)); \
|
||||||
default: \
|
default: \
|
||||||
kprintf("\n%u\n", kp_fmt_dataFormat(f)); \
|
kprintf("\n%u\n", kp_fmt_dataFormat(f)); \
|
||||||
throw(ERR_FORMAT); \
|
throw(ERR_FORMAT); \
|
||||||
return NULL; \
|
return NULL; \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
__toString_i32_def(8)
|
||||||
|
__toString_i32_def(16)
|
||||||
|
__toString_i32_def(32)
|
||||||
|
__toString_i32_def(64)
|
||||||
|
|
||||||
__toString_i_def(8)
|
#define __toString_u_def(BITS) char* __toString_u##BITS(void* _n, u32 f){ \
|
||||||
__toString_i_def(16)
|
|
||||||
__toString_i_def(32)
|
|
||||||
__toString_i_def(64)
|
|
||||||
|
|
||||||
#define __toString_u_def(BITS) char* __toString_u##BITS(allocator_ptr al, void* _n, u32 f){ \
|
|
||||||
switch(kp_fmt_dataFormat(f)){ \
|
switch(kp_fmt_dataFormat(f)){ \
|
||||||
case kp_u: ; \
|
case kp_u: ; \
|
||||||
u##BITS n=*(u##BITS*)_n; \
|
u##BITS n=*(u##BITS*)_n; \
|
||||||
return toString_u64(al, n, kp_fmt_withPostfix(f), kp_fmt_isUpper(f)); \
|
return toString_u64(n, kp_fmt_withPostfix(f), kp_fmt_isUpper(f)); \
|
||||||
case kp_b: \
|
case kp_b: \
|
||||||
return toString_bin(al, _n, BITS/8, getEndian()==LittleEndian, kp_fmt_withPrefix(f)); \
|
return toString_bin(_n, BITS/8, getEndian()==LittleEndian, kp_fmt_withPrefix(f)); \
|
||||||
case kp_h: \
|
case kp_h: \
|
||||||
return toString_hex(al, _n, BITS/8, getEndian()==LittleEndian, kp_fmt_withPrefix(f), kp_fmt_isUpper(f)); \
|
return toString_hex(_n, BITS/8, getEndian()==LittleEndian, kp_fmt_withPrefix(f), kp_fmt_isUpper(f)); \
|
||||||
default: \
|
default: \
|
||||||
kprintf("\n%u\n", kp_fmt_dataFormat(f)); \
|
kprintf("\n%u\n", kp_fmt_dataFormat(f)); \
|
||||||
throw(ERR_FORMAT); \
|
throw(ERR_FORMAT); \
|
||||||
return NULL; \
|
return NULL; \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
__toString_u_def(8)
|
__toString_u_def(8)
|
||||||
__toString_u_def(16)
|
__toString_u_def(16)
|
||||||
__toString_u_def(32)
|
__toString_u_def(32)
|
||||||
__toString_u_def(64)
|
// __toString_u_def(64)
|
||||||
|
char* __toString_u64(void* _n, u32 f){
|
||||||
|
switch(kp_fmt_dataFormat(f)){
|
||||||
|
case kp_u: ;
|
||||||
|
u64 n=*(u64*)_n;
|
||||||
|
return toString_u64(n, kp_fmt_withPostfix(f), kp_fmt_isUpper(f));
|
||||||
|
case kp_b:
|
||||||
|
return toString_bin(_n, 64/8, getEndian()==LittleEndian, kp_fmt_withPrefix(f));
|
||||||
|
case kp_h:
|
||||||
|
return toString_hex(_n, 64/8, getEndian()==LittleEndian, kp_fmt_withPrefix(f), kp_fmt_isUpper(f));
|
||||||
|
default:
|
||||||
|
kprintf("\n%u\n", kp_fmt_dataFormat(f)); throw(ERR_FORMAT); return NULL; }
|
||||||
|
}
|
||||||
|
|
||||||
|
#define __toString_float_def(BITS) char* __toString_f##BITS(void* _n, u32 f){ \
|
||||||
#define __toString_f_def(BITS) char* __toString_f##BITS(allocator_ptr al, void* _n, u32 f){ \
|
|
||||||
switch(kp_fmt_dataFormat(f)){ \
|
switch(kp_fmt_dataFormat(f)){ \
|
||||||
case kp_f: ; \
|
case kp_f: ; \
|
||||||
f##BITS n=*(f##BITS*)_n; \
|
f##BITS n=*(f##BITS*)_n; \
|
||||||
return toString_f64(al, n, toString_float_default_precision, kp_fmt_withPostfix(f), kp_fmt_isUpper(f)); \
|
return toString_f64(n, toString_float_default_precision, kp_fmt_withPostfix(f), kp_fmt_isUpper(f)); \
|
||||||
case kp_b: \
|
case kp_b: \
|
||||||
return toString_bin(al, _n, BITS/8, getEndian()==LittleEndian, kp_fmt_withPrefix(f)); \
|
return toString_bin(_n, BITS/8, getEndian()==LittleEndian, kp_fmt_withPrefix(f)); \
|
||||||
case kp_h: \
|
case kp_h: \
|
||||||
return toString_hex(al, _n, BITS/8, getEndian()==LittleEndian, kp_fmt_withPrefix(f), kp_fmt_isUpper(f)); \
|
return toString_hex(_n, BITS/8, getEndian()==LittleEndian, kp_fmt_withPrefix(f), kp_fmt_isUpper(f)); \
|
||||||
default: \
|
default: \
|
||||||
kprintf("\n%u\n", kp_fmt_dataFormat(f)); \
|
kprintf("\n%u\n", kp_fmt_dataFormat(f)); \
|
||||||
throw(ERR_FORMAT); \
|
throw(ERR_FORMAT); \
|
||||||
@@ -222,5 +231,5 @@ __toString_u_def(64)
|
|||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
__toString_f_def(32)
|
__toString_float_def(32)
|
||||||
__toString_f_def(64)
|
__toString_float_def(64)
|
||||||
|
|||||||
@@ -5,43 +5,42 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "../errors.h"
|
#include "../errors.h"
|
||||||
#include "../memory/allocator_base.h"
|
|
||||||
|
|
||||||
// accepts char* (ptr to char) and char* (ptr to string)
|
// accepts char* (ptr to char) and char* (ptr to string)
|
||||||
// uses format kp_s and kp_c to determine what type is <c> argument
|
// uses format kp_s and kp_c to determine what type is <c> argument
|
||||||
char* __toString_char(allocator_ptr al, void* c, u32 fmt);
|
char* __toString_char(void* c, u32 fmt);
|
||||||
|
|
||||||
// bool
|
// bool
|
||||||
char* __toString_bool(allocator_ptr al, void* c, u32 fmt);
|
char* __toString_bool(void* c, u32 fmt);
|
||||||
|
|
||||||
// signed int
|
// signed int
|
||||||
char* toString_i64(allocator_ptr al, i64 n);
|
char* toString_i64(i64 n);
|
||||||
char* __toString_i8(allocator_ptr al, void* n, u32 fmt);
|
char* __toString_i8(void* n, u32 fmt);
|
||||||
char* __toString_i16(allocator_ptr al, void* n, u32 fmt);
|
char* __toString_i16(void* n, u32 fmt);
|
||||||
char* __toString_i32(allocator_ptr al, void* n, u32 fmt);
|
char* __toString_i32(void* n, u32 fmt);
|
||||||
char* __toString_i64(allocator_ptr al, void* n, u32 fmt);
|
char* __toString_i64(void* n, u32 fmt);
|
||||||
|
|
||||||
// unsigned int
|
// unsigned int
|
||||||
char* toString_u64(allocator_ptr al, u64 n, bool withPostfix, bool uppercase);
|
char* toString_u64(u64 n, bool withPostfix, bool uppercase);
|
||||||
char* __toString_u8(allocator_ptr al, void* n, u32 fmt);
|
char* __toString_u8(void* n, u32 fmt);
|
||||||
char* __toString_u16(allocator_ptr al, void* n, u32 fmt);
|
char* __toString_u16(void* n, u32 fmt);
|
||||||
char* __toString_u32(allocator_ptr al, void* n, u32 fmt);
|
char* __toString_u32(void* n, u32 fmt);
|
||||||
char* __toString_u64(allocator_ptr al, void* n, u32 fmt);
|
char* __toString_u64(void* n, u32 fmt);
|
||||||
|
|
||||||
// float
|
// float
|
||||||
#define toString_f32_max_precision 6
|
#define toString_f32_max_precision 6
|
||||||
#define toString_f64_max_precision 15
|
#define toString_f64_max_precision 15
|
||||||
#define toString_float_default_precision 6
|
#define toString_float_default_precision 6
|
||||||
char* toString_f32(allocator_ptr al, f32 n, u8 precision, bool withPostfix, bool uppercase); // uses sprintf
|
char* toString_f32(f32 n, u8 precision, bool withPostfix, bool uppercase); // uses sprintf
|
||||||
char* toString_f64(allocator_ptr al, f64 n, u8 precision, bool withPostfix, bool uppercase); // uses sprintf
|
char* toString_f64(f64 n, u8 precision, bool withPostfix, bool uppercase); // uses sprintf
|
||||||
char* __toString_f32(allocator_ptr al, void* n, u32 fmt);
|
char* __toString_f32(void* n, u32 fmt);
|
||||||
char* __toString_f64(allocator_ptr al, void* n, u32 fmt);
|
char* __toString_f64(void* n, u32 fmt);
|
||||||
|
|
||||||
|
|
||||||
///@param inverse set to true for little endian numbers (their bytes are in reverse order)
|
///@param inverse set to true for little endian numbers (their bytes are in reverse order)
|
||||||
char* toString_bin(allocator_ptr al, void* bytes, u32 size, bool inverse, bool withPrefix);
|
char* toString_bin(void* bytes, u32 size, bool inverse, bool withPrefix);
|
||||||
///@param inverse set to true for little endian numbers (their bytes are in reverse order)
|
///@param inverse set to true for little endian numbers (their bytes are in reverse order)
|
||||||
char* toString_hex(allocator_ptr al, void* bytes, u32 size, bool inverse, bool withPrefix, bool uppercase);
|
char* toString_hex(void* bytes, u32 size, bool inverse, bool withPrefix, bool uppercase);
|
||||||
|
|
||||||
#if __cplusplus
|
#if __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
#include "../base.h"
|
#include "../base.h"
|
||||||
|
#include "../../Array/Array.h"
|
||||||
#include "../../Autoarr/Autoarr.h"
|
#include "../../Autoarr/Autoarr.h"
|
||||||
#include "../../SearchTree/SearchTree.h"
|
#include "../../SearchTree/SearchTree.h"
|
||||||
#include "../../Hashtable/Hashtable.h"
|
#include "../../Hashtable/Hashtable.h"
|
||||||
#include "../../String/StringBuilder.h"
|
#include "../../String/StringBuilder.h"
|
||||||
#include "../../Filesystem/filesystem.h"
|
#include "../../Filesystem/filesystem.h"
|
||||||
|
#include "../../Network/network.h"
|
||||||
#include "base_toString.h"
|
#include "base_toString.h"
|
||||||
|
|
||||||
void kt_initKerepTypes(){
|
void kt_initKerepTypes(){
|
||||||
@@ -28,6 +30,21 @@ void kt_initKerepTypes(){
|
|||||||
// ktDescriptor
|
// ktDescriptor
|
||||||
kt_register(ktDescriptor);
|
kt_register(ktDescriptor);
|
||||||
|
|
||||||
|
// base type arrays
|
||||||
|
kt_register(Array_char);
|
||||||
|
kt_register(Array_bool);
|
||||||
|
kt_register(Array_f32);
|
||||||
|
kt_register(Array_f64);
|
||||||
|
kt_register(Array_i8);
|
||||||
|
kt_register(Array_u8);
|
||||||
|
kt_register(Array_i16);
|
||||||
|
kt_register(Array_u16);
|
||||||
|
kt_register(Array_i32);
|
||||||
|
kt_register(Array_u32);
|
||||||
|
kt_register(Array_i64);
|
||||||
|
kt_register(Array_u64);
|
||||||
|
kt_register(Array_Pointer);
|
||||||
|
|
||||||
// base type autoarrs
|
// base type autoarrs
|
||||||
kt_register(Autoarr_Pointer);
|
kt_register(Autoarr_Pointer);
|
||||||
kt_register(Autoarr_char);
|
kt_register(Autoarr_char);
|
||||||
@@ -45,6 +62,7 @@ void kt_initKerepTypes(){
|
|||||||
|
|
||||||
// Unitype
|
// Unitype
|
||||||
kt_register(Unitype);
|
kt_register(Unitype);
|
||||||
|
kt_register(Array_Unitype);
|
||||||
kt_register(Autoarr_Unitype);
|
kt_register(Autoarr_Unitype);
|
||||||
|
|
||||||
// STNode
|
// STNode
|
||||||
@@ -59,6 +77,7 @@ void kt_initKerepTypes(){
|
|||||||
|
|
||||||
// string
|
// string
|
||||||
kt_register(string);
|
kt_register(string);
|
||||||
|
kt_register(Array_string);
|
||||||
kt_register(Autoarr_string);
|
kt_register(Autoarr_string);
|
||||||
|
|
||||||
// StringBuilder
|
// StringBuilder
|
||||||
@@ -67,8 +86,10 @@ void kt_initKerepTypes(){
|
|||||||
// File
|
// File
|
||||||
kt_register(FileHandle);
|
kt_register(FileHandle);
|
||||||
|
|
||||||
// Allocators
|
// Network
|
||||||
kt_register(CstdAllocator);
|
kt_register(knIPV4Address);
|
||||||
kt_register(LinearAllocator);
|
kt_register(knIPV4Endpoint);
|
||||||
kt_register(StackingAllocator);
|
kt_register(knSocketTCP);
|
||||||
|
kt_register(knSocketUDP);
|
||||||
|
kt_register(knSocketChanneled);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ extern "C" {
|
|||||||
#include "../std.h"
|
#include "../std.h"
|
||||||
#include "ktid.h"
|
#include "ktid.h"
|
||||||
#include "typedef_macros.h"
|
#include "typedef_macros.h"
|
||||||
#include "../memory/allocator_base.h"
|
|
||||||
|
|
||||||
#define kt_declare(TYPE)\
|
#define kt_declare(TYPE)\
|
||||||
ktid_declare(TYPE);\
|
ktid_declare(TYPE);\
|
||||||
@@ -20,25 +19,25 @@ extern "C" {
|
|||||||
.name=#TYPE, \
|
.name=#TYPE, \
|
||||||
.id=ktid_undefined, \
|
.id=ktid_undefined, \
|
||||||
.size=sizeof(TYPE), \
|
.size=sizeof(TYPE), \
|
||||||
.destruct=FREE_MEMBERS_F, \
|
.freeMembers=FREE_MEMBERS_F, \
|
||||||
.toString=TOSTRING_F \
|
.toString=TOSTRING_F \
|
||||||
}; \
|
}; \
|
||||||
ktDescriptor ktDescriptor_##TYPE##_Ptr={\
|
ktDescriptor ktDescriptor_##TYPE##_Ptr={\
|
||||||
.name=#TYPE "_Ptr", \
|
.name=#TYPE "_Ptr", \
|
||||||
.id=ktid_undefined, \
|
.id=ktid_undefined, \
|
||||||
.size=sizeof(TYPE), \
|
.size=sizeof(TYPE), \
|
||||||
.destruct=FREE_MEMBERS_F, \
|
.freeMembers=FREE_MEMBERS_F, \
|
||||||
.toString=TOSTRING_F \
|
.toString=TOSTRING_F \
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef void (*destruct_t)(void*);
|
typedef void (*freeMembers_t)(void*);
|
||||||
typedef char* (*toString_t)(allocator_ptr al, void* obj, u32 fmt);
|
typedef char* (*toString_t)(void* obj, u32 fmt);
|
||||||
|
|
||||||
STRUCT(ktDescriptor,
|
STRUCT(ktDescriptor,
|
||||||
char* name;
|
char* name;
|
||||||
ktid id;
|
ktid id;
|
||||||
u16 size;
|
u16 size;
|
||||||
destruct_t destruct; // NULL or function which frees all struct members
|
freeMembers_t freeMembers; // NULL or function which frees all struct members
|
||||||
toString_t toString; // NULL or function which generates string representaion of object
|
toString_t toString; // NULL or function which generates string representaion of object
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -17,27 +17,27 @@ kt_define(i64, NULL, __toString_i64);
|
|||||||
kt_define(u64, NULL, __toString_u64);
|
kt_define(u64, NULL, __toString_u64);
|
||||||
|
|
||||||
|
|
||||||
char* ktDescriptor_toString(allocator_ptr al, ktDescriptor* d){
|
char* ktDescriptor_toString(ktDescriptor* d){
|
||||||
const char* n="null";
|
const char* n="null";
|
||||||
char *s0 = toString_u64(al, d->id, 0,0);
|
char *s0 = toString_u64(d->id, 0,0);
|
||||||
char *s1 = toString_u64(al, d->size, 0,0);
|
char *s1 = toString_u64(d->size, 0,0);
|
||||||
char *s2 = d->toString ? toString_hex(al, d->toString, sizeof(void*), 0,1,0) : n;
|
char *s2 = d->toString ? toString_hex(d->toString, sizeof(void*), 0,1,0) : n;
|
||||||
char *s3 = d->destruct ? toString_hex(al, d->destruct, sizeof(void*), 0,1,0) : n;
|
char *s3 = d->freeMembers ? toString_hex(d->freeMembers, sizeof(void*), 0,1,0) : n;
|
||||||
char *rez=cptr_concat(al, "ktDescriptor {"
|
char *rez=cptr_concat("ktDescriptor {"
|
||||||
" name:", d->name,
|
" name:", d->name,
|
||||||
" id:",s0,
|
" id:",s0,
|
||||||
" size:",s1,
|
" size:",s1,
|
||||||
" toString:",s2,
|
" toString:",s2,
|
||||||
" destruct:",s3,
|
" freeMembers:",s3,
|
||||||
" }");
|
" }");
|
||||||
if(s3!=n) allocator_free(al, s3);
|
free(s0);
|
||||||
if(s2!=n) allocator_free(al, s2);
|
free(s1);
|
||||||
allocator_free(al, s1);
|
if(s2!=n) free(s2);
|
||||||
allocator_free(al, s0);
|
if(s3!=n) free(s3);
|
||||||
return rez;
|
return rez;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* _ktDescriptor_toString(allocator_ptr al, void* _d, u32 fmt) { return ktDescriptor_toString(al, _d); }
|
char* _ktDescriptor_toString(void* _d, u32 fmt) { return ktDescriptor_toString(_d); }
|
||||||
|
|
||||||
kt_define(ktDescriptor, NULL, _ktDescriptor_toString);
|
kt_define(ktDescriptor, NULL, _ktDescriptor_toString);
|
||||||
|
|
||||||
@@ -52,20 +52,25 @@ ktid ktid_last=-1;
|
|||||||
ENUM(ktDescriptorsState,
|
ENUM(ktDescriptorsState,
|
||||||
NotInitialized, Initializing, Initialized
|
NotInitialized, Initializing, Initialized
|
||||||
)
|
)
|
||||||
|
|
||||||
ktDescriptorsState initState=NotInitialized;
|
ktDescriptorsState initState=NotInitialized;
|
||||||
|
|
||||||
void kt_beginInit(){
|
bool _printDebugMessages = false;
|
||||||
|
|
||||||
|
void kt_beginInit(bool printDebugMessages){
|
||||||
|
_printDebugMessages = printDebugMessages;
|
||||||
|
if(printDebugMessages)
|
||||||
kprintf("\e[94mtype descriptors initializing...\n");
|
kprintf("\e[94mtype descriptors initializing...\n");
|
||||||
Autoarr_construct(__descriptorPointers, Pointer, 256, NULL);
|
__descriptorPointers=Autoarr_create(Pointer, 256, 256);
|
||||||
}
|
}
|
||||||
|
|
||||||
void kt_endInit(){
|
void kt_endInit(){
|
||||||
if(__descriptorPointers==NULL)
|
if(__descriptorPointers==NULL)
|
||||||
throw(ERR_NULLPTR);
|
throw(ERR_NULLPTR);
|
||||||
typeDescriptors=(ktDescriptor**)Autoarr_toArray(__descriptorPointers, CstdAllocator_instPtr);
|
typeDescriptors=(ktDescriptor**)Autoarr_toArray(__descriptorPointers);
|
||||||
Autoarr_destruct(__descriptorPointers);
|
Autoarr_free(__descriptorPointers,true);
|
||||||
if(typeDescriptors==NULL)
|
if(typeDescriptors==NULL) throw(ERR_NULLPTR);
|
||||||
throw(ERR_NULLPTR);
|
if(_printDebugMessages)
|
||||||
kprintf("\e[92minitialized %u type descriptors\n", ktid_last);
|
kprintf("\e[92minitialized %u type descriptors\n", ktid_last);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,13 +80,12 @@ void __kt_register(ktDescriptor* descriptor){
|
|||||||
}
|
}
|
||||||
|
|
||||||
ktDescriptor* ktDescriptor_get(ktid id){
|
ktDescriptor* ktDescriptor_get(ktid id){
|
||||||
if(id>ktid_last || id==ktid_undefined) {
|
if(id>ktid_last || id==ktid_undefined)
|
||||||
kprintf("\ntype id: %u\n",id);
|
throw(cptr_concat("invalid type id ", toString_i64(id)));
|
||||||
throw("invalid type id");
|
|
||||||
}
|
|
||||||
return typeDescriptors[id];
|
return typeDescriptors[id];
|
||||||
}
|
}
|
||||||
|
|
||||||
void kt_deinit(){
|
void kt_free(){
|
||||||
free(typeDescriptors);
|
free(typeDescriptors);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,16 +17,16 @@ void __kt_register(ktDescriptor* descriptor);
|
|||||||
__kt_register(&ktDescriptor_##TYPE##_Ptr); \
|
__kt_register(&ktDescriptor_##TYPE##_Ptr); \
|
||||||
ktid_##TYPE##_Ptr=ktid_last;
|
ktid_##TYPE##_Ptr=ktid_last;
|
||||||
|
|
||||||
void kt_beginInit();
|
void kt_beginInit(bool printDebugMessages);
|
||||||
void kt_endInit();
|
void kt_endInit();
|
||||||
|
|
||||||
/// @param id id of registered type
|
/// @param id id of registered type
|
||||||
ktDescriptor* ktDescriptor_get(ktid id);
|
ktDescriptor* ktDescriptor_get(ktid id);
|
||||||
|
|
||||||
char* ktDescriptor_toString(allocator_ptr al, ktDescriptor* d);
|
char* ktDescriptor_toString(ktDescriptor* d);
|
||||||
|
|
||||||
// call it to free heap-allocated ktDescriptors array
|
// call it to free heap-allocated ktDescriptors array
|
||||||
void kt_deinit();
|
void kt_free();
|
||||||
|
|
||||||
kt_declare(Pointer);
|
kt_declare(Pointer);
|
||||||
kt_declare(char);
|
kt_declare(char);
|
||||||
|
|||||||
@@ -8,10 +8,6 @@
|
|||||||
ENUM_MEMBERS \
|
ENUM_MEMBERS \
|
||||||
} __attribute__((__packed__)) ENUM_NAME;
|
} __attribute__((__packed__)) ENUM_NAME;
|
||||||
|
|
||||||
#define PACKED_STRUCT(STRUCT_NAME, STRUCT_MEMBERS...) typedef struct STRUCT_NAME { \
|
|
||||||
STRUCT_MEMBERS \
|
|
||||||
} __attribute__((__packed__)) STRUCT_NAME;
|
|
||||||
|
|
||||||
#define STRUCT(STRUCT_NAME, STRUCT_MEMBERS...) typedef struct STRUCT_NAME STRUCT_NAME; \
|
#define STRUCT(STRUCT_NAME, STRUCT_MEMBERS...) typedef struct STRUCT_NAME STRUCT_NAME; \
|
||||||
typedef struct STRUCT_NAME { \
|
typedef struct STRUCT_NAME { \
|
||||||
STRUCT_MEMBERS \
|
STRUCT_MEMBERS \
|
||||||
|
|||||||
@@ -1,36 +1,40 @@
|
|||||||
#include "../../kprint/kprint_format.h"
|
#include "../../kprint/kprint_format.h"
|
||||||
#include "../base.h"
|
#include "../base.h"
|
||||||
|
|
||||||
char *__Unitype_toString(allocator_ptr al, void *_u, u32 fmt)
|
char *__Unitype_toString(void *_u, u32 fmt)
|
||||||
{
|
{
|
||||||
return Unitype_toString(al, *(Unitype *)_u, fmt);
|
return Unitype_toString(*(Unitype *)_u, fmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
kt_define(Unitype, (destruct_t)Unitype_destruct, __Unitype_toString);
|
kt_define(Unitype, __UnitypePtr_free, __Unitype_toString);
|
||||||
|
|
||||||
void Unitype_destruct(Unitype* u)
|
void Unitype_free(Unitype u)
|
||||||
{
|
|
||||||
if (u->typeId == ktid_undefined)
|
|
||||||
{
|
|
||||||
if (u->VoidPtr != NULL)
|
|
||||||
throw("unitype with undefined typeId has value");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ktDescriptor *type = ktDescriptor_get(u->typeId);
|
|
||||||
if (type->destruct)
|
|
||||||
type->destruct(u->VoidPtr);
|
|
||||||
if (u->allocatedInHeap)
|
|
||||||
free(u->VoidPtr);
|
|
||||||
}
|
|
||||||
|
|
||||||
char *Unitype_toString(allocator_ptr al, Unitype u, u32 fmt)
|
|
||||||
{
|
{
|
||||||
if (u.typeId == ktid_undefined)
|
if (u.typeId == ktid_undefined)
|
||||||
{
|
{
|
||||||
if (u.VoidPtr != NULL)
|
if (u.VoidPtr != NULL)
|
||||||
throw("unitype with undefined typeId has value");
|
throw("unitype with undefined typeId has value");
|
||||||
return cptr_copy(al, "{ERROR_TYPE}");
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ktDescriptor *type = ktDescriptor_get(u.typeId);
|
||||||
|
if (type->freeMembers)
|
||||||
|
type->freeMembers(u.VoidPtr);
|
||||||
|
if (u.allocatedInHeap)
|
||||||
|
free(u.VoidPtr);
|
||||||
|
}
|
||||||
|
void __UnitypePtr_free(void *u)
|
||||||
|
{
|
||||||
|
Unitype_free(*(Unitype *)u);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *Unitype_toString(Unitype u, u32 fmt)
|
||||||
|
{
|
||||||
|
if (u.typeId == ktid_undefined)
|
||||||
|
{
|
||||||
|
if (u.VoidPtr != NULL)
|
||||||
|
throw("unitype with undefined typeId has value");
|
||||||
|
return cptr_copy("{ERROR_TYPE}");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fmt == 0)
|
if (fmt == 0)
|
||||||
@@ -70,7 +74,7 @@ char *Unitype_toString(allocator_ptr al, Unitype u, u32 fmt)
|
|||||||
else if (u.typeId == ktid_name(Pointer))
|
else if (u.typeId == ktid_name(Pointer))
|
||||||
{
|
{
|
||||||
if (u.VoidPtr == NULL)
|
if (u.VoidPtr == NULL)
|
||||||
return cptr_copy(al, "{ UniNull }");
|
return cptr_copy("{ UniNull }");
|
||||||
fmt = kp_h;
|
fmt = kp_h;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -78,22 +82,19 @@ char *Unitype_toString(allocator_ptr al, Unitype u, u32 fmt)
|
|||||||
ktDescriptor *type = ktDescriptor_get(u.typeId);
|
ktDescriptor *type = ktDescriptor_get(u.typeId);
|
||||||
char *valuestr;
|
char *valuestr;
|
||||||
if (type->toString)
|
if (type->toString)
|
||||||
valuestr = type->toString(al, u.VoidPtr, fmt);
|
valuestr = type->toString(u.VoidPtr, fmt);
|
||||||
else
|
else
|
||||||
valuestr = "ERR_NO_TOSTRING_FUNC";
|
valuestr = "ERR_NO_TOSTRING_FUNC";
|
||||||
char *rezult = cptr_concat(al, "{ type: ", type->name, ", allocated on heap: ", (u.allocatedInHeap ? "true" : "false"),
|
char *result = cptr_concat("{ type: ", type->name, ", allocated on heap: ", (u.allocatedInHeap ? "true" : "false"),
|
||||||
", value:", valuestr, " }");
|
", value:", valuestr, " }");
|
||||||
if (type->toString)
|
if (type->toString)
|
||||||
allocator_free(al, valuestr);
|
free(valuestr);
|
||||||
return rezult;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void printuni(Unitype v)
|
void printuni(Unitype v)
|
||||||
{
|
{
|
||||||
LinearAllocator _al;
|
char *s = Unitype_toString(v, 0);
|
||||||
LinearAllocator_construct(&_al, 128);
|
|
||||||
allocator_ptr al=&_al.base;
|
|
||||||
char *s = Unitype_toString(al, v, 0);
|
|
||||||
fputs(s, stdout);
|
fputs(s, stdout);
|
||||||
LinearAllocator_destruct(&_al);
|
free(s);
|
||||||
}
|
}
|
||||||
@@ -17,7 +17,7 @@ STRUCT(Unitype,
|
|||||||
char Bytes[8];
|
char Bytes[8];
|
||||||
};
|
};
|
||||||
ktid typeId;
|
ktid typeId;
|
||||||
bool allocatedInHeap; // should Unitype_destruct call free() to VoidPtr*
|
bool allocatedInHeap; // should Unitype_free call free() to VoidPtr*
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -45,8 +45,9 @@ STRUCT(Unitype,
|
|||||||
#define UniCheckTypePtr(UNI, TYPE) UniCheckTypeId(UNI, ktid_ptrName(TYPE))
|
#define UniCheckTypePtr(UNI, TYPE) UniCheckTypeId(UNI, ktid_ptrName(TYPE))
|
||||||
|
|
||||||
// frees VoidPtr value or does nothing if type isn't pointer
|
// frees VoidPtr value or does nothing if type isn't pointer
|
||||||
void Unitype_destruct(Unitype* u);
|
void Unitype_free(Unitype u);
|
||||||
char* Unitype_toString(allocator_ptr al, Unitype v, u32 fmt);
|
void __UnitypePtr_free(void* u);
|
||||||
|
char* Unitype_toString(Unitype v, u32 fmt);
|
||||||
void printuni(Unitype v);
|
void printuni(Unitype v);
|
||||||
|
|
||||||
#if __cplusplus
|
#if __cplusplus
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ ktid __typeFromFormat(kp_fmt f){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Maybe __next_toString(allocator_ptr al, kp_fmt f, void* object){
|
Maybe __next_toString(kp_fmt f, void* object){
|
||||||
// detecting type
|
// detecting type
|
||||||
ktid typeId=__typeFromFormat(f);
|
ktid typeId=__typeFromFormat(f);
|
||||||
if(typeId==ktid_undefined)
|
if(typeId==ktid_undefined)
|
||||||
@@ -35,62 +35,54 @@ Maybe __next_toString(allocator_ptr al, kp_fmt f, void* object){
|
|||||||
ktDescriptor* type=ktDescriptor_get(typeId);
|
ktDescriptor* type=ktDescriptor_get(typeId);
|
||||||
if(!type->toString)
|
if(!type->toString)
|
||||||
safethrow("type descriptor doesnt have toString() func",;);
|
safethrow("type descriptor doesnt have toString() func",;);
|
||||||
return SUCCESS(UniHeapPtr(char, type->toString(al, object, f)));
|
return SUCCESS(UniHeapPtr(char, type->toString(object, f)));
|
||||||
}
|
}
|
||||||
|
|
||||||
Maybe check_argsN(u8 n){
|
Maybe check_argsN(u8 n){
|
||||||
if(n%2 != 0) safethrow("kprint recieved non-even number of arguments",;);
|
if(n%2 != 0) safethrow("kprint received non-even number of arguments",;);
|
||||||
if(n > 32) safethrow("kprint recieved >32 number of arguments",;);
|
if(n > 32) safethrow("kprint received >32 number of arguments",;);
|
||||||
return MaybeNull;
|
return MaybeNull;
|
||||||
}
|
}
|
||||||
|
|
||||||
Maybe __ksprint(allocator_ptr al, u8 n, kp_fmt* formats, __kp_value_union* objects){
|
Maybe __ksprint(u8 n, kp_fmt* formats, __kp_value_union* objects){
|
||||||
try(check_argsN(n), _,;);
|
try(check_argsN(n), _,;);
|
||||||
n/=2;
|
n/=2;
|
||||||
StringBuilder _sb;
|
StringBuilder* strb=StringBuilder_create();
|
||||||
StringBuilder* sb=&_sb;
|
|
||||||
StringBuilder_construct(sb, al);
|
|
||||||
for(u8 i=0; i<n; i++){
|
for(u8 i=0; i<n; i++){
|
||||||
try(__next_toString(al, formats[i], &objects[i]),mStr,;);
|
try(__next_toString(formats[i], &objects[i]),mStr,;);
|
||||||
StringBuilder_append_cptr(sb, mStr.value.VoidPtr);
|
StringBuilder_append_cptr(strb, mStr.value.VoidPtr);
|
||||||
allocator_free(al, mStr.value.VoidPtr);
|
Unitype_free(mStr.value);
|
||||||
}
|
}
|
||||||
char* rezult=StringBuilder_build(sb).ptr;
|
char* result=StringBuilder_build(strb).ptr;
|
||||||
return SUCCESS(UniHeapPtr(char, rezult));
|
return SUCCESS(UniHeapPtr(char, result));
|
||||||
}
|
}
|
||||||
|
|
||||||
Maybe __kfprint(FILE* file, u8 n, kp_fmt* formats, __kp_value_union* objects){
|
Maybe __kfprint(FILE* file, u8 n, kp_fmt* formats, __kp_value_union* objects){
|
||||||
try(check_argsN(n), _,;);
|
try(check_argsN(n), _,;);
|
||||||
n/=2;
|
n/=2;
|
||||||
LinearAllocator _al;
|
|
||||||
LinearAllocator_construct(&_al, 256);
|
|
||||||
allocator_ptr al=&_al.base;
|
|
||||||
for(u8 i=0; i<n; i++){
|
for(u8 i=0; i<n; i++){
|
||||||
try(__next_toString(al, formats[i], &objects[i]),maybeStr, LinearAllocator_destruct(&_al));
|
try(__next_toString(formats[i], &objects[i]),maybeStr,;);
|
||||||
if(fputs(maybeStr.value.VoidPtr, file)==EOF)
|
if(fputs(maybeStr.value.VoidPtr, file)==EOF)
|
||||||
safethrow("can't write string to file", LinearAllocator_destruct(&_al));
|
safethrow("can't write string to file", Unitype_free(maybeStr.value));
|
||||||
|
Unitype_free(maybeStr.value);
|
||||||
}
|
}
|
||||||
fflush(file);
|
fflush(file);
|
||||||
LinearAllocator_destruct(&_al);
|
|
||||||
return MaybeNull;
|
return MaybeNull;
|
||||||
}
|
}
|
||||||
|
|
||||||
void __kprint(u8 n, kp_fmt* formats, __kp_value_union* objects){
|
void __kprint(u8 n, kp_fmt* formats, __kp_value_union* objects){
|
||||||
tryLast(check_argsN(n), _,;);
|
tryLast(check_argsN(n), _,;);
|
||||||
n/=2;
|
n/=2;
|
||||||
LinearAllocator _al;
|
|
||||||
LinearAllocator_construct(&_al, 256);
|
|
||||||
allocator_ptr al=&_al.base;
|
|
||||||
for(u8 i=0; i<n; i++){
|
for(u8 i=0; i<n; i++){
|
||||||
kp_fmt fmt=formats[i];
|
kp_fmt fmt=formats[i];
|
||||||
kprint_setColor(fmt);
|
kprint_setColor(fmt);
|
||||||
tryLast(__next_toString(al, fmt, &objects[i]), maybeStr,
|
tryLast(__next_toString(fmt, &objects[i]),maybeStr, kprint_setColor(kp_bgBlack|kp_fgGray));
|
||||||
kprint_setColor(kp_bgBlack|kp_fgGray););
|
if(fputs(maybeStr.value.VoidPtr, stdout)==EOF) \
|
||||||
if(fputs(maybeStr.value.VoidPtr, stdout)==EOF)
|
|
||||||
throw("can't write string to stdout");
|
throw("can't write string to stdout");
|
||||||
|
//, Unitype_free(maybeStr.value)
|
||||||
|
Unitype_free(maybeStr.value);
|
||||||
}
|
}
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
LinearAllocator_destruct(&_al);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(_WIN32)|| defined(_WIN64)
|
#if defined(_WIN32)|| defined(_WIN64)
|
||||||
@@ -98,7 +90,6 @@ void __kprint(u8 n, kp_fmt* formats, __kp_value_union* objects){
|
|||||||
#define FOREGROUND_YELLOW FOREGROUND_GREEN | FOREGROUND_RED
|
#define FOREGROUND_YELLOW FOREGROUND_GREEN | FOREGROUND_RED
|
||||||
|
|
||||||
DWORD kp_fgColor_toWin(kp_fgColor f){
|
DWORD kp_fgColor_toWin(kp_fgColor f){
|
||||||
//kprintf("fg: %x\n", f);
|
|
||||||
switch(f){
|
switch(f){
|
||||||
case kp_fgBlack: return 0;
|
case kp_fgBlack: return 0;
|
||||||
case kp_fgRedD: return FOREGROUND_RED;
|
case kp_fgRedD: return FOREGROUND_RED;
|
||||||
@@ -121,7 +112,6 @@ DWORD kp_fgColor_toWin(kp_fgColor f){
|
|||||||
}
|
}
|
||||||
|
|
||||||
DWORD kp_bgColor_toWin(kp_bgColor f){
|
DWORD kp_bgColor_toWin(kp_bgColor f){
|
||||||
//kprintf("bg: %x\n", f);
|
|
||||||
switch(f){
|
switch(f){
|
||||||
case kp_bgBlack: return 0;
|
case kp_bgBlack: return 0;
|
||||||
case kp_bgRedD: return BACKGROUND_RED;
|
case kp_bgRedD: return BACKGROUND_RED;
|
||||||
@@ -175,19 +165,17 @@ void kprint_setColor(kp_fmt f){
|
|||||||
ktDescriptor* type=ktDescriptor_get(format.typeId);
|
ktDescriptor* type=ktDescriptor_get(format.typeId);
|
||||||
if(!type->toString)
|
if(!type->toString)
|
||||||
safethrow("type descriptor doesnt have toString() func",;);
|
safethrow("type descriptor doesnt have toString() func",;);
|
||||||
StringBuilder _sb;
|
StringBuilder* strb=StringBuilder_create();
|
||||||
StringBuilder* sb=&_sb;
|
StringBuilder_append_char(strb, '[');
|
||||||
StringBuilder_construct(sb, al);
|
|
||||||
StringBuilder_append_char(sb, '[');
|
|
||||||
for (u16 e=1; e<count; e++){
|
for (u16 e=1; e<count; e++){
|
||||||
StringBuilder_append_char(sb, ' ');
|
StringBuilder_append_char(strb, ' ');
|
||||||
char* elStr=type->toString(array+type->size*e, &format);
|
char* elStr=type->toString(array+type->size*e, &format);
|
||||||
StringBuilder_append_cptr(sb, elStr);
|
StringBuilder_append_cptr(strb, elStr);
|
||||||
StringBuilder_append_char(sb, ',');
|
StringBuilder_append_char(strb, ',');
|
||||||
}
|
}
|
||||||
StringBuilder_rmchar(sb);
|
StringBuilder_rmchar(strb);
|
||||||
StringBuilder_append_char(sb, ' ');
|
StringBuilder_append_char(strb, ' ');
|
||||||
StringBuilder_append_char(sb, ']');
|
StringBuilder_append_char(strb, ']');
|
||||||
} */
|
} */
|
||||||
|
|
||||||
static const char* _kp_colorNames[16]={
|
static const char* _kp_colorNames[16]={
|
||||||
@@ -209,12 +197,12 @@ static const char* _kp_colorNames[16]={
|
|||||||
"white"
|
"white"
|
||||||
};
|
};
|
||||||
|
|
||||||
char* kp_bgColor_toString(allocator_ptr al, kp_bgColor c){
|
char* kp_bgColor_toString(kp_bgColor c){
|
||||||
u32 color_index=(c&0x00f00000)>>20;
|
u32 color_index=(c&0x00f00000)>>20;
|
||||||
if(color_index>15) throw(ERR_WRONGINDEX);
|
if(color_index>15) throw(ERR_WRONGINDEX);
|
||||||
return _kp_colorNames[color_index];
|
return _kp_colorNames[color_index];
|
||||||
}
|
}
|
||||||
char* kp_fgColor_toString(allocator_ptr al, kp_fgColor c){
|
char* kp_fgColor_toString(kp_fgColor c){
|
||||||
u32 color_index=(c&0x00f00000)>>24;
|
u32 color_index=(c&0x00f00000)>>24;
|
||||||
if(color_index>15) throw(ERR_WRONGINDEX);
|
if(color_index>15) throw(ERR_WRONGINDEX);
|
||||||
return _kp_colorNames[color_index];
|
return _kp_colorNames[color_index];
|
||||||
|
|||||||
@@ -70,12 +70,12 @@ static inline __kp_value_union __kpVU_i(i64 f) { return (__kp_value_union){ .i64
|
|||||||
__kp_argsToObjs32(ARGS))
|
__kp_argsToObjs32(ARGS))
|
||||||
|
|
||||||
|
|
||||||
Maybe __ksprint(allocator_ptr al, u8 n, kp_fmt* formats, __kp_value_union* objects);
|
Maybe __ksprint(u8 n, kp_fmt* formats, __kp_value_union* objects);
|
||||||
|
|
||||||
/// @param ARGS kp_fmt, value, kp_fmt, value...
|
/// @param ARGS kp_fmt, value, kp_fmt, value...
|
||||||
///@returns Maybe<char*>
|
///@returns Maybe<char*>
|
||||||
#define ksprint(ALLOCATOR, ARGS...) WARNING_DISABLE( W_INT_CONVERSION, \
|
#define ksprint(ARGS...) WARNING_DISABLE( W_INT_CONVERSION, \
|
||||||
__ksprint(ALLOCATOR, count_args(ARGS), __kp_argsToArrs(count_args(ARGS),ARGS, __32zeroes)) \
|
__ksprint(count_args(ARGS), __kp_argsToArrs(count_args(ARGS),ARGS, __32zeroes)) \
|
||||||
)
|
)
|
||||||
/*-Wint-conversion warning was produced during value to __kp_value_union conversion*/
|
/*-Wint-conversion warning was produced during value to __kp_value_union conversion*/
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "../base/memory/allocator_base.h"
|
#include "../base/type_system/typedef_macros.h"
|
||||||
|
|
||||||
// 10000000 00000000 00000000 00000000
|
// 10000000 00000000 00000000 00000000
|
||||||
// ^ ^^^^
|
// ^ ^^^^
|
||||||
@@ -83,8 +83,8 @@ PACKED_ENUM(kp_bgColor,
|
|||||||
kp_bgWhite = 0x40f00000
|
kp_bgWhite = 0x40f00000
|
||||||
)
|
)
|
||||||
|
|
||||||
char* kp_bgColor_toString(allocator_ptr al, kp_bgColor c);
|
char* kp_bgColor_toString(kp_bgColor c);
|
||||||
char* kp_fgColor_toString(allocator_ptr al, kp_fgColor c);
|
char* kp_fgColor_toString(kp_fgColor c);
|
||||||
|
|
||||||
#if __cplusplus
|
#if __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,93 +45,90 @@ WORD unixColorToWin(u8 c){
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void kprintf(const char* format, ...){
|
i32 _kprintf(const char* format, const i32 args_count, ...){
|
||||||
va_list vl;
|
va_list vl;
|
||||||
va_start(vl, format);
|
va_start(vl, args_count);
|
||||||
u32 i=0;
|
i32 i = 0;
|
||||||
LinearAllocator _al;
|
i32 args_left = args_count;
|
||||||
LinearAllocator_construct(&_al, 128);
|
for(char c = format[i++]; c != 0; c = format[i++]){
|
||||||
allocator_ptr al=(allocator_ptr)&_al;
|
|
||||||
for(char c=format[i++]; c!=0; c=format[i++]){
|
|
||||||
// value format specifiers
|
// value format specifiers
|
||||||
if(c=='%'){
|
if(c == '%'){
|
||||||
char* argstr=NULL;
|
if(args_left-- == 0)
|
||||||
bool l=false;
|
return kprintf_NOT_ENOUGH_ARGUMENTS;
|
||||||
c=format[i++];
|
|
||||||
|
char* argstr = NULL;
|
||||||
|
bool l = false;
|
||||||
|
c = format[i++];
|
||||||
format_escape_seq:
|
format_escape_seq:
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'u':
|
case 'u':
|
||||||
argstr=toString_u64(al,
|
argstr = toString_u64(
|
||||||
l ? va_arg(vl, u64) : va_arg(vl, u32)
|
l ? va_arg(vl, u64) : va_arg(vl, u32)
|
||||||
,0,0);
|
,0,0);
|
||||||
break;
|
break;
|
||||||
case 'i': case 'd':
|
case 'i': case 'd':
|
||||||
argstr=toString_i64(al,
|
argstr = toString_i64(
|
||||||
l ? va_arg(vl, i64) : va_arg(vl, i32)
|
l ? va_arg(vl, i64) : va_arg(vl, i32)
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case 'f':
|
case 'f':
|
||||||
// f32 is promoted to f64 when passed through '...'
|
// f32 is promoted to f64 when passed through '...'
|
||||||
argstr=toString_f64(al, va_arg(vl, f64), toString_float_default_precision,0,0);
|
argstr = toString_f64(va_arg(vl, f64), toString_float_default_precision,0,0);
|
||||||
break;
|
break;
|
||||||
case 'l':
|
case 'l':
|
||||||
l=true;
|
l = true;
|
||||||
if((c=format[i++]))
|
if((c = format[i++]))
|
||||||
goto format_escape_seq;
|
goto format_escape_seq;
|
||||||
break;
|
break;
|
||||||
case 'p': ;
|
case 'p': ;
|
||||||
void* phex=va_arg(vl, void*);
|
void* phex = va_arg(vl, void*);
|
||||||
argstr=toString_hex(al, &phex,getEndian()==LittleEndian,sizeof(phex),1,0);
|
argstr = toString_hex(&phex,getEndian() == LittleEndian,sizeof(phex),1,0);
|
||||||
break;
|
break;
|
||||||
case 'x': ;
|
case 'x': ;
|
||||||
if(l){
|
if(l){
|
||||||
u64 xhex=va_arg(vl, u64);
|
u64 xhex = va_arg(vl, u64);
|
||||||
argstr=toString_hex(al, &xhex,getEndian()==LittleEndian,sizeof(xhex),0,1);
|
argstr = toString_hex(&xhex,getEndian() == LittleEndian,sizeof(xhex),0,1);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
u32 xhex=va_arg(vl, u32);
|
u32 xhex = va_arg(vl, u32);
|
||||||
argstr=toString_hex(al, &xhex,getEndian()==LittleEndian,sizeof(xhex),0,1);
|
argstr = toString_hex(&xhex,getEndian() == LittleEndian,sizeof(xhex),0,1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 's': ;
|
case 's': ;
|
||||||
char* cptr=va_arg(vl,char*);
|
char* cptr = va_arg(vl,char*);
|
||||||
if(!cptr)
|
if(!cptr)
|
||||||
cptr="<nullstr>";
|
cptr = "<nullstr>";
|
||||||
if(*cptr)
|
if(*cptr)
|
||||||
fputs(cptr, stdout);
|
fputs(cptr, stdout);
|
||||||
break;
|
break;
|
||||||
case 'c':
|
case 'c':
|
||||||
argstr=allocator_alloc(al, 2);
|
putc((char)va_arg(vl,int), stdout);
|
||||||
argstr[0]=(char)va_arg(vl,int);
|
|
||||||
argstr[1]=0;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
putc('\n',stdout);
|
fputs("<INCORRECT FORMAT STRING>", stdout);
|
||||||
putc('<',stdout);
|
return kprintf_INVALID_FORMAT;
|
||||||
putc(c,stdout);
|
|
||||||
putc('>',stdout);
|
|
||||||
throw(ERR_FORMAT);
|
|
||||||
}
|
}
|
||||||
if(argstr){
|
if(argstr){
|
||||||
fputs(argstr, stdout);
|
fputs(argstr, stdout);
|
||||||
|
free(argstr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// escape sequences
|
// escape sequences
|
||||||
else if(c=='\e'){
|
else if(c == '\e'){
|
||||||
IFWIN(
|
//////////////////// WINDOWS ////////////////////
|
||||||
/* WINDOWS */
|
#if defined(_WIN64) || defined(_WIN32)
|
||||||
({
|
if((c = format[i++]) == '['){
|
||||||
if((c=format[i++])=='['){
|
u8 colorUnix = 0;
|
||||||
u8 colorUnix=0;
|
for(i8 n = 0; n<6 && c != 0; n++){
|
||||||
for(i8 n=0; n<6 && c!=0; n++){
|
c = format[i++];
|
||||||
c=format[i++];
|
|
||||||
switch (c){
|
switch (c){
|
||||||
case '0': case '1': case '2': case '3': case '4':
|
case '0': case '1': case '2': case '3': case '4':
|
||||||
case '5': case '6': case '7': case '8': case '9':
|
case '5': case '6': case '7': case '8': case '9':
|
||||||
colorUnix=colorUnix*10+c-'0';
|
colorUnix = colorUnix*10+c-'0';
|
||||||
break;
|
break;
|
||||||
case 'm': ;
|
case 'm': ;
|
||||||
WORD colorWin=unixColorToWin(colorUnix);
|
WORD colorWin = unixColorToWin(colorUnix);
|
||||||
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
SetConsoleTextAttribute(hConsole, colorWin);
|
SetConsoleTextAttribute(hConsole, colorWin);
|
||||||
goto end_iteration;
|
goto end_iteration;
|
||||||
@@ -140,11 +137,12 @@ void kprintf(const char* format, ...){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}),
|
////////////////////// UNIX //////////////////////
|
||||||
/* UNIX */
|
#else
|
||||||
putc(c,stdout);
|
putc(c,stdout);
|
||||||
);
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// common characters
|
// common characters
|
||||||
else {
|
else {
|
||||||
putc(c,stdout);
|
putc(c,stdout);
|
||||||
@@ -154,5 +152,112 @@ void kprintf(const char* format, ...){
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
va_end(vl);
|
va_end(vl);
|
||||||
LinearAllocator_destruct(&_al);
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
i32 _ksprintf(char* buffer, i32 buffer_size, const char* format, const i32 args_count, ...){
|
||||||
|
if(buffer == NULL)
|
||||||
|
return kprintf_BUFFER_IS_NULL;
|
||||||
|
|
||||||
|
va_list vl;
|
||||||
|
va_start(vl, args_count);
|
||||||
|
i32 i = 0;
|
||||||
|
i32 written = 0;
|
||||||
|
i32 args_left = args_count;
|
||||||
|
for(char c = format[i++]; c != 0; c = format[i++]){
|
||||||
|
// value format specifiers
|
||||||
|
if(c == '%'){
|
||||||
|
if(args_left-- == 0)
|
||||||
|
return kprintf_NOT_ENOUGH_ARGUMENTS;
|
||||||
|
|
||||||
|
char* argstr = NULL;
|
||||||
|
bool l = false;
|
||||||
|
c = format[i++];
|
||||||
|
format_escape_seq:
|
||||||
|
switch (c) {
|
||||||
|
case 'u':
|
||||||
|
argstr = toString_u64(
|
||||||
|
l ? va_arg(vl, u64) : va_arg(vl, u32)
|
||||||
|
,0,0);
|
||||||
|
break;
|
||||||
|
case 'i': case 'd':
|
||||||
|
argstr = toString_i64(
|
||||||
|
l ? va_arg(vl, i64) : va_arg(vl, i32)
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
// f32 is promoted to f64 when passed through '...'
|
||||||
|
argstr = toString_f64(va_arg(vl, f64), toString_float_default_precision,0,0);
|
||||||
|
break;
|
||||||
|
case 'l':
|
||||||
|
l = true;
|
||||||
|
if((c = format[i++]))
|
||||||
|
goto format_escape_seq;
|
||||||
|
break;
|
||||||
|
case 'p': ;
|
||||||
|
void* phex = va_arg(vl, void*);
|
||||||
|
argstr = toString_hex(&phex,getEndian() == LittleEndian,sizeof(phex),1,0);
|
||||||
|
break;
|
||||||
|
case 'x': ;
|
||||||
|
if(l){
|
||||||
|
u64 xhex = va_arg(vl, u64);
|
||||||
|
argstr = toString_hex(&xhex,getEndian() == LittleEndian,sizeof(xhex),0,1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
u32 xhex = va_arg(vl, u32);
|
||||||
|
argstr = toString_hex(&xhex,getEndian() == LittleEndian,sizeof(xhex),0,1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 's': ;
|
||||||
|
char* cptr = va_arg(vl,char*);
|
||||||
|
if(!cptr)
|
||||||
|
cptr = "<nullstr>";
|
||||||
|
if(*cptr){
|
||||||
|
i32 str_length = cptr_length(cptr);
|
||||||
|
if(written + str_length > buffer_size)
|
||||||
|
return kprintf_BUFFER_IS_TOO_SMALL;
|
||||||
|
|
||||||
|
memcpy(buffer + written, cptr, str_length);
|
||||||
|
written += str_length;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'c': ;
|
||||||
|
char ch = (char)va_arg(vl,int);
|
||||||
|
if(written > buffer_size)
|
||||||
|
return kprintf_BUFFER_IS_TOO_SMALL;
|
||||||
|
|
||||||
|
buffer[written++] = ch;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
const char errformat_str[] = "<INCORRECT FORMAT STRING>";
|
||||||
|
if(written + (i32)sizeof(errformat_str) <= buffer_size)
|
||||||
|
memcpy(buffer + written, errformat_str, sizeof(errformat_str));
|
||||||
|
return kprintf_INVALID_FORMAT;
|
||||||
|
}
|
||||||
|
if(argstr){
|
||||||
|
i32 str_length = cptr_length(argstr);
|
||||||
|
if(written + str_length > buffer_size)
|
||||||
|
return kprintf_BUFFER_IS_TOO_SMALL;
|
||||||
|
|
||||||
|
memcpy(buffer + written, argstr, str_length);
|
||||||
|
written += str_length;
|
||||||
|
free(argstr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// common characters
|
||||||
|
else {
|
||||||
|
if(written > buffer_size)
|
||||||
|
return kprintf_BUFFER_IS_TOO_SMALL;
|
||||||
|
|
||||||
|
buffer[written++] = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
va_end(vl);
|
||||||
|
if(written > buffer_size)
|
||||||
|
return kprintf_BUFFER_IS_TOO_SMALL;
|
||||||
|
buffer[written] = '\0';
|
||||||
|
return i;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,8 +6,63 @@ extern "C" {
|
|||||||
|
|
||||||
#include "../base/type_system/base_toString.h"
|
#include "../base/type_system/base_toString.h"
|
||||||
|
|
||||||
// cross-platform printf analog
|
#define kprintf_INVALID_FORMAT -1
|
||||||
void kprintf(const char* format, ...);
|
#define kprintf_NOT_ENOUGH_ARGUMENTS -2
|
||||||
|
#define kprintf_BUFFER_IS_TOO_SMALL -3
|
||||||
|
#define kprintf_BUFFER_IS_NULL -4
|
||||||
|
|
||||||
|
/// cross-platform printf analog
|
||||||
|
///@return number of processed format string characters or error code
|
||||||
|
i32 _kprintf(const char* format, const i32 args_count, ...);
|
||||||
|
#define kprintf(FORMAT, ARGS... ) _kprintf(FORMAT, count_args(ARGS) ,##ARGS)
|
||||||
|
|
||||||
|
/// @return number of processed format string characters or error code
|
||||||
|
i32 _ksprintf(char* buffer, i32 buffer_size, const char* format, const i32 args_count, ...);
|
||||||
|
#define ksprintf(BUFFER, BUFFER_SIZE, FORMAT, ARGS... ) _ksprintf(BUFFER, BUFFER_SIZE, FORMAT, count_args(ARGS) ,##ARGS)
|
||||||
|
|
||||||
|
|
||||||
|
// printf format terminal color sequence
|
||||||
|
#define _PRINTF_COLOR(N) "\e["#N"m"
|
||||||
|
|
||||||
|
// foreground dark color codes
|
||||||
|
#define FBLK _PRINTF_COLOR(30)
|
||||||
|
#define FREDD _PRINTF_COLOR(31)
|
||||||
|
#define FGRND _PRINTF_COLOR(32)
|
||||||
|
#define FYELD _PRINTF_COLOR(33)
|
||||||
|
#define FBLUD _PRINTF_COLOR(34)
|
||||||
|
#define FMAGD _PRINTF_COLOR(35)
|
||||||
|
#define FCYND _PRINTF_COLOR(36)
|
||||||
|
#define FGRY _PRINTF_COLOR(37)
|
||||||
|
|
||||||
|
// foreground bright color codes
|
||||||
|
#define FGRYD _PRINTF_COLOR(90)
|
||||||
|
#define FRED _PRINTF_COLOR(91)
|
||||||
|
#define FGRN _PRINTF_COLOR(92)
|
||||||
|
#define FYEL _PRINTF_COLOR(93)
|
||||||
|
#define FBLU _PRINTF_COLOR(94)
|
||||||
|
#define FMAG _PRINTF_COLOR(95)
|
||||||
|
#define FCYN _PRINTF_COLOR(96)
|
||||||
|
#define FWHI _PRINTF_COLOR(97)
|
||||||
|
|
||||||
|
// background dark color codes
|
||||||
|
#define BBLK _PRINTF_COLOR(40)
|
||||||
|
#define BREDD _PRINTF_COLOR(41)
|
||||||
|
#define BGRND _PRINTF_COLOR(42)
|
||||||
|
#define BYELD _PRINTF_COLOR(43)
|
||||||
|
#define BBLUD _PRINTF_COLOR(44)
|
||||||
|
#define BMAGD _PRINTF_COLOR(45)
|
||||||
|
#define BCYND _PRINTF_COLOR(46)
|
||||||
|
#define BGRY _PRINTF_COLOR(47)
|
||||||
|
|
||||||
|
// background bright color codes
|
||||||
|
#define BGRYD _PRINTF_COLOR(100)
|
||||||
|
#define BRED _PRINTF_COLOR(101)
|
||||||
|
#define BGRN _PRINTF_COLOR(102)
|
||||||
|
#define BYEL _PRINTF_COLOR(103)
|
||||||
|
#define BBLU _PRINTF_COLOR(104)
|
||||||
|
#define BMAG _PRINTF_COLOR(105)
|
||||||
|
#define BCYN _PRINTF_COLOR(106)
|
||||||
|
#define BWHI _PRINTF_COLOR(107)
|
||||||
|
|
||||||
#if __cplusplus
|
#if __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
72
src/random/krandom.h
Normal file
72
src/random/krandom.h
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "../base/std.h"
|
||||||
|
#include "splitmix64/splitmix64.h"
|
||||||
|
#include "xoroshiro/xoroshiro.h"
|
||||||
|
#include "xoshiro/xoshiro.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
You can choose any algorithm that has required functions:
|
||||||
|
|
||||||
|
some_alg32_statePtr some_alg32_init(u32 seed);
|
||||||
|
u32 some_alg32_next(some_alg32_statePtr);
|
||||||
|
void some_alg32_free(some_alg32_statePtr);
|
||||||
|
|
||||||
|
#define KRAND_ALG32_init some_alg32_init
|
||||||
|
#define KRAND_ALG32_next some_alg32_next
|
||||||
|
#define KRAND_ALG32_free some_alg32_free
|
||||||
|
#include "kerep/random/krandom.h"
|
||||||
|
|
||||||
|
The same way it works for 64-bit RNGs
|
||||||
|
*/
|
||||||
|
|
||||||
|
// default rng_next function
|
||||||
|
#ifndef KRAND_ALG32_next
|
||||||
|
#define KRAND_ALG32_next xoshiro128plus##_next
|
||||||
|
#endif
|
||||||
|
#ifndef KRAND_ALG32_init
|
||||||
|
#define KRAND_ALG32_init xoshiro128plus##_init
|
||||||
|
#endif
|
||||||
|
#ifndef KRAND_ALG32_free
|
||||||
|
#define KRAND_ALG32_free xoshiro128plus##_free
|
||||||
|
#endif
|
||||||
|
#ifndef KRAND_ALG64_next
|
||||||
|
#define KRAND_ALG64_next xoshiro256plus##_next
|
||||||
|
#endif
|
||||||
|
#ifndef KRAND_ALG64_init
|
||||||
|
#define KRAND_ALG64_init xoshiro256plus##_init
|
||||||
|
#endif
|
||||||
|
#ifndef KRAND_ALG64_free
|
||||||
|
#define KRAND_ALG64_free xoshiro256plus##_free
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef void* krand_statePtr;
|
||||||
|
#define KRAND_ALG32_initFromTime xoshiro128plus##_initFromTime
|
||||||
|
#define KRAND_ALG64_initFromTime xoshiro256plus##_initFromTime
|
||||||
|
|
||||||
|
#define __krand_next_definition(VALUE_SIZE) { return from+KRAND_ALG##VALUE_SIZE##_next(state)%(to-from); }
|
||||||
|
|
||||||
|
// ready-to-use functions
|
||||||
|
static inline i8 krand_next8 (krand_statePtr state, i8 from, i8 to) __krand_next_definition(32)
|
||||||
|
static inline i16 krand_next16(krand_statePtr state, i16 from, i16 to) __krand_next_definition(32)
|
||||||
|
static inline i32 krand_next32(krand_statePtr state, i32 from, i32 to) __krand_next_definition(32)
|
||||||
|
static inline i64 krand_next64(krand_statePtr state, i64 from, i64 to) __krand_next_definition(64)
|
||||||
|
|
||||||
|
// divides random number by 2^64 to return a value between 0 and 1
|
||||||
|
static inline f32 krand_nextFloat32(krand_statePtr state) {return (f32)KRAND_ALG32_next(state) / (u32)(-1); }
|
||||||
|
static inline f64 krand_nextFloat64(krand_statePtr state) {return (f64)KRAND_ALG64_next(state) / (u64)(-1); }
|
||||||
|
|
||||||
|
|
||||||
|
///@param chance (0-1.0) is probability of success
|
||||||
|
static inline bool fate(krand_statePtr state,float chance){
|
||||||
|
i32 limit=1/chance + 0.01f;
|
||||||
|
return KRAND_ALG32_next(state)%limit == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#if __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "../base/std.h"
|
|
||||||
#include "splitmix64/splitmix64.h"
|
|
||||||
#include "xoroshiro/32bitValue/xoroshiro64.h"
|
|
||||||
#include "xoroshiro/64bitValue/xoroshiro128.h"
|
|
||||||
#include "xoshiro/32bitValue/xoshiro128.h"
|
|
||||||
#include "xoshiro/64bitValue/xoshiro256.h"
|
|
||||||
|
|
||||||
|
|
||||||
#define random_seedFromTime() time(NULL)
|
|
||||||
|
|
||||||
/// divides random number by 2^32
|
|
||||||
/// @return value between 0 and 1
|
|
||||||
static inline f32 random_toFloat32(u32 random_value) { return (f32)random_value / (f32)0xffff; }
|
|
||||||
/// divides random number by 2^64
|
|
||||||
/// @return value between 0 and 1
|
|
||||||
static inline f64 random_nextFloat64(u64 random_value) { return (f64)random_value / (f64)0xffffffff; }
|
|
||||||
|
|
||||||
///@param probability (0-1.0) probability of success
|
|
||||||
///@return is action sucsessfull or not
|
|
||||||
static inline bool random_probability(u32 random_value, float probability){
|
|
||||||
i32 limit=1.0f/probability + 0.0002f;
|
|
||||||
return random_value%limit == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
@@ -11,11 +11,20 @@ computations) or xorshift1024* (for massively parallel computations)
|
|||||||
generator.
|
generator.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
u64 splitmix64_next(splitmix64_state* state_ptr) {
|
// The state can be seeded with any (upto) 64 bit integer value.
|
||||||
|
|
||||||
|
void* splitmix64_init(u64 seed){
|
||||||
|
splitmix64_state* state=malloc(sizeof(splitmix64_state));
|
||||||
|
*state=seed;
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 splitmix64_next(void* _state) {
|
||||||
|
splitmix64_state* state=_state;
|
||||||
// increment the state variable
|
// increment the state variable
|
||||||
*state_ptr += 0x9e3779b97f4a7c15;
|
*state += 0x9e3779b97f4a7c15;
|
||||||
// copy the state to a working variable
|
// copy the state to a working variable
|
||||||
u64 z = *state_ptr;
|
u64 z = *state;
|
||||||
// xor the variable with the variable right bit shifted 30 then multiply by a constant
|
// xor the variable with the variable right bit shifted 30 then multiply by a constant
|
||||||
z = (z ^ (z>>30)) * 0xbf58476d1ce4e5b9;
|
z = (z ^ (z>>30)) * 0xbf58476d1ce4e5b9;
|
||||||
// xor the variable with the variable right bit shifted 27 then multiply by a constant
|
// xor the variable with the variable right bit shifted 27 then multiply by a constant
|
||||||
|
|||||||
@@ -7,13 +7,16 @@ extern "C" {
|
|||||||
#include "../../base/base.h"
|
#include "../../base/base.h"
|
||||||
|
|
||||||
typedef u64 splitmix64_state;
|
typedef u64 splitmix64_state;
|
||||||
|
typedef void* splitmix64_statePtr;
|
||||||
|
|
||||||
static inline void splitmix64_construct(splitmix64_state* state, u64 seed){
|
splitmix64_statePtr splitmix64_init(u64 seed);
|
||||||
*state=seed;
|
static inline splitmix64_statePtr splitmix64_initFromTime(void) { return splitmix64_init(time(NULL)); }
|
||||||
|
|
||||||
|
u64 splitmix64_next(splitmix64_statePtr);
|
||||||
|
static inline void splitmix64_free(splitmix64_statePtr state) {
|
||||||
|
free(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 splitmix64_next(splitmix64_state* state_ptr);
|
|
||||||
|
|
||||||
#if __cplusplus
|
#if __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -4,17 +4,31 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "../../../base/std.h"
|
||||||
#include "../../splitmix64/splitmix64.h"
|
#include "../../splitmix64/splitmix64.h"
|
||||||
|
|
||||||
typedef union {
|
typedef union {
|
||||||
u64 merged;
|
u64 merged;
|
||||||
u32 s[2];
|
u32 s[2];
|
||||||
} xoroshiro64_state;
|
} xoroshiro64_state;
|
||||||
|
typedef void* xoroshiro64_statePtr;
|
||||||
|
|
||||||
void xoroshiro64_construct(xoroshiro64_state* state_ptr, u64 seed);
|
xoroshiro64_statePtr xoroshiro64_init(u64 seed);
|
||||||
|
#define xoroshiro64star_init xoroshiro64_init
|
||||||
|
#define xoroshiro64starstar_init xoroshiro64_init
|
||||||
|
|
||||||
u32 xoroshiro64star_next(xoroshiro64_state*);
|
static inline xoroshiro64_statePtr xoroshiro64_initFromTime(void) { return xoroshiro64_init(time(NULL)); }
|
||||||
u32 xoroshiro64starstar_next(xoroshiro64_state*);
|
#define xoroshiro64star_initFromTime xoroshiro64_initFromTime
|
||||||
|
#define xoroshiro64starstar_initFromTime xoroshiro64_initFromTime
|
||||||
|
|
||||||
|
u32 xoroshiro64star_next(xoroshiro64_statePtr);
|
||||||
|
u32 xoroshiro64starstar_next(xoroshiro64_statePtr);
|
||||||
|
|
||||||
|
static inline void xoroshiro64_free(xoroshiro64_statePtr state) {
|
||||||
|
free(state);
|
||||||
|
}
|
||||||
|
#define xoroshiro64star_free xoroshiro64_free
|
||||||
|
#define xoroshiro64starstar_free xoroshiro64_free
|
||||||
|
|
||||||
#if __cplusplus
|
#if __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,8 @@ static inline u32 rotl(const u32 x, i32 k) {
|
|||||||
return (x << k) | (x >> (32 - k));
|
return (x << k) | (x >> (32 - k));
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 xoroshiro64star_next(xoroshiro64_state* state) {
|
u32 xoroshiro64star_next(void* _state) {
|
||||||
|
xoroshiro64_state* state=_state;
|
||||||
const u32 s0 = state->s[0];
|
const u32 s0 = state->s[0];
|
||||||
u32 s1 = state->s[1];
|
u32 s1 = state->s[1];
|
||||||
const u32 result = s0 * 0x9E3779BB;
|
const u32 result = s0 * 0x9E3779BB;
|
||||||
@@ -39,8 +40,10 @@ u32 xoroshiro64star_next(xoroshiro64_state* state) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void xoroshiro64_construct(xoroshiro64_state* state, u64 seed){
|
void* xoroshiro64_init(u64 seed){
|
||||||
splitmix64_state sm_state;
|
xoroshiro64_state* state=malloc(sizeof(xoroshiro64_state));
|
||||||
splitmix64_construct(&sm_state, seed);
|
splitmix64_state* splitmix=splitmix64_init(seed);
|
||||||
state->merged=splitmix64_next(&sm_state);
|
state->merged=splitmix64_next(splitmix);
|
||||||
|
splitmix64_free(splitmix);
|
||||||
|
return state;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,8 @@ static inline u32 rotl(const u32 x, i32 k) {
|
|||||||
return (x << k) | (x >> (32 - k));
|
return (x << k) | (x >> (32 - k));
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 xoroshiro64starstar_next(xoroshiro64_state* state) {
|
u32 xoroshiro64starstar_next(void* _state) {
|
||||||
|
xoroshiro64_state* state=_state;
|
||||||
const u32 s0 = state->s[0];
|
const u32 s0 = state->s[0];
|
||||||
u32 s1 = state->s[1];
|
u32 s1 = state->s[1];
|
||||||
const u32 result = rotl(s0 * 0x9E3779BB, 5) * 5;
|
const u32 result = rotl(s0 * 0x9E3779BB, 5) * 5;
|
||||||
|
|||||||
@@ -4,17 +4,35 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "../../../base/std.h"
|
||||||
#include "../../splitmix64/splitmix64.h"
|
#include "../../splitmix64/splitmix64.h"
|
||||||
|
|
||||||
|
|
||||||
typedef union {
|
typedef union {
|
||||||
u32 s[2];
|
u32 s[2];
|
||||||
} xoroshiro128_state;
|
} xoroshiro128_state;
|
||||||
|
typedef void* xoroshiro128_statePtr;
|
||||||
|
|
||||||
void xoroshiro128_construct(xoroshiro128_state* state, u64 seed);
|
xoroshiro128_statePtr xoroshiro128_init(u64 seed);
|
||||||
|
#define xoroshiro128plus_init xoroshiro128_init
|
||||||
|
#define xoroshiro128plusplus_init xoroshiro128_init
|
||||||
|
#define xoroshiro128starstar_init xoroshiro128_init
|
||||||
|
|
||||||
u64 xoroshiro128plus_next(xoroshiro128_state*);
|
static inline xoroshiro128_statePtr xoroshiro128_initFromTime(void) { return xoroshiro128_init(time(NULL)); }
|
||||||
u64 xoroshiro128plusplus_next(xoroshiro128_state*);
|
#define xoroshiro128plus_initFromTime xoroshiro128_initFromTime
|
||||||
u64 xoroshiro128starstar_next(xoroshiro128_state*);
|
#define xoroshiro128plusplus_initFromTime xoroshiro128_initFromTime
|
||||||
|
#define xoroshiro128starstar_initFromTime xoroshiro128_initFromTime
|
||||||
|
|
||||||
|
u64 xoroshiro128plus_next(xoroshiro128_statePtr);
|
||||||
|
u64 xoroshiro128plusplus_next(xoroshiro128_statePtr);
|
||||||
|
u64 xoroshiro128starstar_next(xoroshiro128_statePtr);
|
||||||
|
|
||||||
|
static inline void xoroshiro128_free(xoroshiro128_statePtr state) {
|
||||||
|
free(state);
|
||||||
|
}
|
||||||
|
#define xoroshiro128plus_free xoroshiro128_free
|
||||||
|
#define xoroshiro128plusplus_free xoroshiro128_free
|
||||||
|
#define xoroshiro128starstar_free xoroshiro128_free
|
||||||
|
|
||||||
#if __cplusplus
|
#if __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,8 @@ static inline u64 rotl(const u64 x, i32 k) {
|
|||||||
return (x << k) | (x >> (64 - k));
|
return (x << k) | (x >> (64 - k));
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 xoroshiro128plus_next(xoroshiro128_state* state){
|
u64 xoroshiro128plus_next(void* _state){
|
||||||
|
xoroshiro128_state* state=_state;
|
||||||
const u64 s0 = state->s[0];
|
const u64 s0 = state->s[0];
|
||||||
u64 s1 = state->s[1];
|
u64 s1 = state->s[1];
|
||||||
const u64 result = s0 + s1;
|
const u64 result = s0 + s1;
|
||||||
@@ -48,9 +49,11 @@ u64 xoroshiro128plus_next(xoroshiro128_state* state){
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void xoroshiro128_construct(xoroshiro128_state* state, u64 seed){
|
void* xoroshiro128_init(u64 seed){
|
||||||
splitmix64_state sm_state;
|
xoroshiro128_state* state=malloc(sizeof(xoroshiro128_state));
|
||||||
splitmix64_construct(&sm_state, seed);
|
splitmix64_state* splitmix=splitmix64_init(seed);
|
||||||
state->s[0]=splitmix64_next(&sm_state);
|
state->s[0]=splitmix64_next(splitmix);
|
||||||
state->s[1]=splitmix64_next(&sm_state);
|
state->s[1]=splitmix64_next(splitmix);
|
||||||
|
splitmix64_free(splitmix);
|
||||||
|
return state;
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user