Compare commits
1 Commits
master
...
vector_sor
Author | SHA1 | Date |
---|---|---|
Evan Burkey | 04e4d07e99 |
|
@ -14,7 +14,7 @@ jobs:
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get install -y libbsd-dev cmake build-essential netcat
|
sudo apt-get install -y libbsd-dev cmake build-essential
|
||||||
|
|
||||||
- name: Build and test
|
- name: Build and test
|
||||||
run: |
|
run: |
|
||||||
|
|
|
@ -5,7 +5,4 @@ compile_commands.json
|
||||||
site
|
site
|
||||||
libflint.so
|
libflint.so
|
||||||
test
|
test
|
||||||
tcptest
|
|
||||||
testrunner
|
|
||||||
.idea
|
.idea
|
||||||
netmanual
|
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/dataSources/
|
||||||
|
/dataSources.local.xml
|
||||||
|
# Editor-based HTTP Client requests
|
||||||
|
/httpRequests/
|
|
@ -0,0 +1 @@
|
||||||
|
flint
|
|
@ -0,0 +1,91 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="BackendCodeEditorSettings">
|
||||||
|
<option name="/Default/Housekeeping/GlobalSettingsUpgraded/IsUpgraded/@EntryValue" value="true" type="bool" />
|
||||||
|
<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="false" 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_REF_IN_DATA_MEMBERS/@EntryValue" value="false" 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_PTR_IN_ABSTRACT_DECL/@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_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_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/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/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>
|
|
@ -0,0 +1,2 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module classpath="CMake" type="CPP_MODULE" version="4" />
|
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="CMakePythonSetting">
|
||||||
|
<option name="pythonIntegrationState" value="YES" />
|
||||||
|
</component>
|
||||||
|
<component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
|
||||||
|
</project>
|
|
@ -0,0 +1,8 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/libfputs.iml" filepath="$PROJECT_DIR$/.idea/libfputs.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
|
@ -2,10 +2,6 @@ cmake_minimum_required(VERSION 3.17)
|
||||||
project(flint C)
|
project(flint C)
|
||||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||||
|
|
||||||
if ((${CMAKE_SYSTEM_NAME} STREQUAL "Linux"))
|
|
||||||
add_compile_definitions(flint __USE_XOPEN_EXTENDED)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(CMAKE_C_STANDARD 99)
|
set(CMAKE_C_STANDARD 99)
|
||||||
include_directories(include)
|
include_directories(include)
|
||||||
|
|
||||||
|
@ -21,8 +17,6 @@ set(SOURCES
|
||||||
src/utility.c
|
src/utility.c
|
||||||
src/crypto.c
|
src/crypto.c
|
||||||
src/parsing.c
|
src/parsing.c
|
||||||
src/network.c
|
|
||||||
src/memory.c
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if ((${CMAKE_SYSTEM_NAME} STREQUAL "Darwin"))
|
if ((${CMAKE_SYSTEM_NAME} STREQUAL "Darwin"))
|
||||||
|
@ -32,7 +26,7 @@ else()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if ((${CMAKE_SYSTEM_NAME} STREQUAL "Linux"))
|
if ((${CMAKE_SYSTEM_NAME} STREQUAL "Linux"))
|
||||||
target_link_libraries(flint pthread bsd)
|
target_link_libraries(flint bsd)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(${CMAKE_PROJECT_NAME} STREQUAL flint)
|
if(${CMAKE_PROJECT_NAME} STREQUAL flint)
|
||||||
|
@ -40,17 +34,8 @@ if(${CMAKE_PROJECT_NAME} STREQUAL flint)
|
||||||
target_include_directories(tests PRIVATE include)
|
target_include_directories(tests PRIVATE include)
|
||||||
|
|
||||||
if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
|
if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
|
||||||
target_link_libraries(tests flint pthread bsd)
|
target_link_libraries(tests flint bsd)
|
||||||
else()
|
else()
|
||||||
target_link_libraries(tests flint pthread)
|
target_link_libraries(tests flint)
|
||||||
endif()
|
|
||||||
|
|
||||||
add_executable(netmanual tests/netmanual.c)
|
|
||||||
target_include_directories(netmanual PRIVATE include)
|
|
||||||
|
|
||||||
if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
|
|
||||||
target_link_libraries(netmanual flint pthread bsd)
|
|
||||||
else()
|
|
||||||
target_link_libraries(netmanual flint pthread)
|
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
37
Makefile
37
Makefile
|
@ -1,13 +1,32 @@
|
||||||
CMAKE_OPTS=-DCMAKE_EXPORT_COMPILE_COMMANDS=1
|
.PHONY : clean
|
||||||
|
|
||||||
all:
|
CFLAGS = -std=c99 -Iinclude -pedantic -Wall -Wextra
|
||||||
mkdir -p build
|
LDFLAGS = -fPIC -shared
|
||||||
cd build && \
|
|
||||||
cmake ${CMAKE_OPTS} .. && \
|
TARGET = libflint.so
|
||||||
$(MAKE) && \
|
SRC != ls src/*.c
|
||||||
cp compile_commands.json ..
|
OBJ = $(SRC:./src/$.c=./obj/%.o)
|
||||||
|
|
||||||
|
PREFIX = $(DESTDIR)/usr/local
|
||||||
|
LIBDIR = $(PREFIX)/lib
|
||||||
|
|
||||||
|
all: $(TARGET)
|
||||||
|
|
||||||
|
$(TARGET): $(OBJ)
|
||||||
|
cc $(CFLAGS) $(LDFLAGS) -o $(TARGET) $(OBJ)
|
||||||
|
|
||||||
|
./obj/%.o: ./src/%.c
|
||||||
|
cc $(CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
install: $(TARGET)
|
||||||
|
cp $(TARGET) $(LIBDIR)
|
||||||
|
|
||||||
|
uninstall:
|
||||||
|
rm -f $(LIBDIR)/$(TARGET)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf build
|
rm -f $(TARGET)
|
||||||
rm -f compile_commands.json
|
rm -f test
|
||||||
|
|
||||||
|
test:
|
||||||
|
cc $(CFLAGS) -o test tests/tests.c src/*.c
|
||||||
|
|
|
@ -4,8 +4,7 @@ My personal library of common C data structures and algorithms. Supports Linux,
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
Extensive documentation can be found [here](https://fputs.com/docs/libflint/). You can also check out `tests/tests.c` to
|
Extensive documentation can be found [here](https://fputs.com/docs/libflint/)
|
||||||
see example usage from most of the library's API.
|
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
#!/bin/sh -e
|
||||||
|
|
||||||
|
# For building outside of CLion
|
||||||
|
|
||||||
|
mkdir -p build
|
||||||
|
cd build
|
||||||
|
cmake ..
|
||||||
|
make
|
||||||
|
cp compile_commands.json ..
|
||||||
|
cd
|
17
clanggen.sh
17
clanggen.sh
|
@ -1,17 +0,0 @@
|
||||||
#!/usr/bin/env sh
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
CFLAGS="-I./include -I/usr/local/include"
|
|
||||||
|
|
||||||
rm -f compile_commands.json
|
|
||||||
|
|
||||||
for f in $(find ./src -type f | grep -v macos); do
|
|
||||||
n=$(echo $f | grep -o '[^/]*$' | sed 's/c$/json/')
|
|
||||||
cc -MJ $n $CFLAGS -c $f
|
|
||||||
done
|
|
||||||
|
|
||||||
rm *.o
|
|
||||||
sed -e '1s/^/[/' -e '$s/,$/]/' *.json > compile_commands.out
|
|
||||||
rm *.json
|
|
||||||
mv compile_commands.out compile_commands.json
|
|
|
@ -92,8 +92,7 @@ printf("%s\n", sp[0]); // Prints "Split"
|
||||||
|
|
||||||
### del_split
|
### del_split
|
||||||
|
|
||||||
Frees all memory used by `split()`. Just like `split`, it does not touch the original string.
|
Frees all memory used by `split()`. Just like `split`, it does not touch the original string
|
||||||
|
|
||||||
```c
|
```c
|
||||||
void del_split(char **sp);
|
void del_split(char **sp);
|
||||||
|
|
||||||
|
@ -102,19 +101,3 @@ size_t sp_sz = 0;
|
||||||
char **sp = split("Delete Me!", &sp_sz, " ");
|
char **sp = split("Delete Me!", &sp_sz, " ");
|
||||||
void del_split(sp);
|
void del_split(sp);
|
||||||
```
|
```
|
||||||
|
|
||||||
### capture_system
|
|
||||||
|
|
||||||
Runs a command on the system shell and returns stdout as a string. `buffsize` is the size of
|
|
||||||
the returned buffer that holds `stdout`. Passing `0` to `buffsize` will use the default buffer size of `1024`.
|
|
||||||
|
|
||||||
User is responsible for freeing the returned string.
|
|
||||||
|
|
||||||
```c
|
|
||||||
const char *capture_system(const char *cmd, int buffsize);
|
|
||||||
|
|
||||||
/* Usage */
|
|
||||||
const char *cap = capture_system("ls $HOME", 0);
|
|
||||||
printf("%s\n", cap);
|
|
||||||
free(cap);
|
|
||||||
```
|
|
|
@ -61,3 +61,12 @@ for (int i = 0; i < 10; i++) {
|
||||||
}
|
}
|
||||||
free(pd);
|
free(pd);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## reallocarray
|
||||||
|
|
||||||
|
reallocarray is reimplemented for macOS because Apple doesn't expose their implementation. This is taken straight
|
||||||
|
from the OpenBSD source
|
||||||
|
|
||||||
|
```c
|
||||||
|
void *reallocarray(void *optr, size_t nmemb, size_t size);
|
||||||
|
```
|
||||||
|
|
13
docs/math.md
13
docs/math.md
|
@ -58,10 +58,17 @@ Works the same as `bresenham()` but uses the `Point` struct instead of `int`
|
||||||
Point *bresenham_p(Point p1, Point p2, size_t *sz);
|
Point *bresenham_p(Point p1, Point p2, size_t *sz);
|
||||||
```
|
```
|
||||||
|
|
||||||
## is_power_of_two
|
## Comparison Functions
|
||||||
|
|
||||||
Returns `1` if `i` is a power of two, otherwise returns `1`.
|
Comparison functions to compare two items. These functions must return `1` if `a > b`, `-1` if
|
||||||
|
`a < b`, or `0` if `a == b`. This follows the pattern defined by `compar` functions in the C standard
|
||||||
|
library, making these usuable in the standard sorting functions like `qsort`
|
||||||
|
|
||||||
```c
|
```c
|
||||||
int is_power_of_two(int i);
|
int compar_int(const void *a, const void *b);
|
||||||
|
int compar_char(const void *a, const void *b);
|
||||||
|
|
||||||
|
// Example
|
||||||
|
qsort(arr, arr_sz, sizeof(int), compar_int);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
194
docs/memory.md
194
docs/memory.md
|
@ -1,194 +0,0 @@
|
||||||
# memory
|
|
||||||
|
|
||||||
Custom allocators and memory functions
|
|
||||||
|
|
||||||
## Arena Allocator
|
|
||||||
|
|
||||||
A simple arena-style allocator
|
|
||||||
|
|
||||||
## Structs
|
|
||||||
|
|
||||||
### ArenaAllocator
|
|
||||||
|
|
||||||
Represents an arena allocator. `ArenaAllocator` holds its own buffer, but managing its size is left to the user. Like
|
|
||||||
most structs in `libflint`, it must be malloc'd first before being passed to `arena_init()`.
|
|
||||||
|
|
||||||
```c
|
|
||||||
typedef struct {
|
|
||||||
unsigned char* buf;
|
|
||||||
size_t buf_sz;
|
|
||||||
size_t offset_cur;
|
|
||||||
size_t offset_prev;
|
|
||||||
} ArenaAllocator;
|
|
||||||
```
|
|
||||||
|
|
||||||
## Functions
|
|
||||||
|
|
||||||
### arena_init
|
|
||||||
|
|
||||||
Initializes the `ArenaAllocator`. The struct must first be created by the user using `malloc()`, see the example below.
|
|
||||||
`buf_sz` is the size of the underlying buffer in bytes.
|
|
||||||
|
|
||||||
```c
|
|
||||||
void arena_init(ArenaAllocator *allocator, size_t buf_sz);
|
|
||||||
|
|
||||||
/* Usage */
|
|
||||||
ArenaAllocator *a = malloc(sizeof(ArenaAllocator));
|
|
||||||
arena_init(a, 1024);
|
|
||||||
```
|
|
||||||
|
|
||||||
### arena_free
|
|
||||||
Frees `allocator` and its underlying buffer. Users should set `allocator` to `NULL` after calling `arena_free()`.
|
|
||||||
```c
|
|
||||||
void arena_free(ArenaAllocator *allocator);
|
|
||||||
|
|
||||||
/* Usage */
|
|
||||||
arena_free(allocator);
|
|
||||||
allocator = NULL;
|
|
||||||
```
|
|
||||||
|
|
||||||
### arena_clear
|
|
||||||
|
|
||||||
Resets the offset markers of the arena to `0`, but does not wipe the underlying buffer. Technically, any assigned pointers
|
|
||||||
will still work and
|
|
||||||
|
|
||||||
```c
|
|
||||||
void arena_clear(ArenaAllocator *allocator);
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
### *arena_malloc
|
|
||||||
|
|
||||||
Request memory of `size` bytes in length from the arena. Returns `NULL` if the assignment failed.
|
|
||||||
|
|
||||||
```c
|
|
||||||
void *arena_malloc(ArenaAllocator* allocator, size_t size);
|
|
||||||
```
|
|
||||||
|
|
||||||
### arena_resize_buf
|
|
||||||
|
|
||||||
Reallocates the underlying buffer in the arena to `new_sz`. You can grow or shrink the arena using this function. Any
|
|
||||||
pointers allocated out of the arena are invalid after using this function.
|
|
||||||
|
|
||||||
```c
|
|
||||||
void arena_resize_buf(ArenaAllocator *allocator, size_t new_sz);
|
|
||||||
```
|
|
||||||
|
|
||||||
### *arena_resize
|
|
||||||
|
|
||||||
Resize an allocated pointer from the arena. See the example below for a simple use case
|
|
||||||
|
|
||||||
```c
|
|
||||||
void *arena_resize(ArenaAllocator *allocator, void *mem, size_t old_sz, size_t new_sz);
|
|
||||||
|
|
||||||
/* Usage */
|
|
||||||
int *i = arena_malloc(a, sizeof(int));
|
|
||||||
*i = 1;
|
|
||||||
long *l = arena_resize(a, i1, sizeof(int), sizeof(long));
|
|
||||||
assert(*l == 1);
|
|
||||||
```
|
|
||||||
|
|
||||||
## Macros
|
|
||||||
|
|
||||||
### arena_sz
|
|
||||||
|
|
||||||
Convenience macro for getting the size of the arena's buffer
|
|
||||||
|
|
||||||
```c
|
|
||||||
#define arena_sz(a) (a)->buf_sz
|
|
||||||
```
|
|
||||||
|
|
||||||
## Pool Allocator
|
|
||||||
|
|
||||||
A pool-based allocator for chunks of the same size. Useful for quickly allocating and using memory of the same size
|
|
||||||
without worrying about order; most operations are `O(1)`
|
|
||||||
|
|
||||||
## Structs
|
|
||||||
|
|
||||||
### PoolAllocator
|
|
||||||
|
|
||||||
Represents a pool allocator. `PoolAllocator` holds its own buffer, but managing its size is left to the user. Like
|
|
||||||
most structs in `libflint`, it must be malloc'd first before being passed to `pool_init()`.
|
|
||||||
|
|
||||||
```c
|
|
||||||
typedef struct {
|
|
||||||
unsigned char *buf;
|
|
||||||
size_t buf_sz;
|
|
||||||
size_t chunk_size;
|
|
||||||
|
|
||||||
List *free_list;
|
|
||||||
} PoolAllocator;
|
|
||||||
```
|
|
||||||
|
|
||||||
## Functions
|
|
||||||
|
|
||||||
### pool_init
|
|
||||||
|
|
||||||
Initializes the `PoolAllocator`. The struct must first be created by the user using `malloc()`, see the example below.
|
|
||||||
|
|
||||||
- `buf_sz`: Size of the underlying buffer in bytes
|
|
||||||
- `chunk_sz`: Size of each chunk in bytes
|
|
||||||
- `chunk_align`: The alignment of the chunks. The`LF_DEFAULT_ALIGNMENT` macro is available as a good default for basic types
|
|
||||||
|
|
||||||
```c
|
|
||||||
void pool_init(PoolAllocator *allocator, size_t buf_sz, size_t chunk_sz, size_t chunk_align);
|
|
||||||
|
|
||||||
/* Usage */
|
|
||||||
PoolAllocator *pool = malloc(sizeof(PoolAllocator));
|
|
||||||
pool_init(pool, 64, 16, LF_DEFAULT_ALIGNMENT);
|
|
||||||
```
|
|
||||||
|
|
||||||
### pool_free
|
|
||||||
|
|
||||||
Return a single chunk back to the pool. `ptr` is a pointer to the allocated chunk.
|
|
||||||
|
|
||||||
```c
|
|
||||||
void pool_free(PoolAllocator *allocator, void *ptr);
|
|
||||||
```
|
|
||||||
|
|
||||||
### pool_free_all
|
|
||||||
|
|
||||||
Returns all chunks back to the pool. Any pointers received before this call are now invalid and must be reasigned with
|
|
||||||
`pool_alloc` or set to `NULL`.
|
|
||||||
|
|
||||||
```c
|
|
||||||
void pool_free_all(PoolAllocator *allocator);
|
|
||||||
```
|
|
||||||
|
|
||||||
### pool_alloc
|
|
||||||
|
|
||||||
Allocate a chunk from the pool. Returns `NULL` on failure.
|
|
||||||
|
|
||||||
```c
|
|
||||||
void *pool_alloc(PoolAllocator *allocator);
|
|
||||||
```
|
|
||||||
|
|
||||||
### pool_destroy
|
|
||||||
|
|
||||||
Destroys the underlying buffer and `List` in `allocator`, then frees it. User is responsible for setting `allocator` to
|
|
||||||
`NULL` afterwards.
|
|
||||||
|
|
||||||
```c
|
|
||||||
void pool_destroy(PoolAllocator *allocator);
|
|
||||||
```
|
|
||||||
|
|
||||||
## Macros
|
|
||||||
|
|
||||||
### pool_count_available
|
|
||||||
|
|
||||||
Returns the amount of chunks left available in the pool
|
|
||||||
|
|
||||||
```c
|
|
||||||
#define pool_count_available(x) (x)->free_list->size
|
|
||||||
```
|
|
||||||
|
|
||||||
### LF_DEFAULT_ALIGNMENT
|
|
||||||
|
|
||||||
The default alignment for allocators. Use this as a simple default (defaults to 16 bytes on amd64 systems) when storing
|
|
||||||
basic types
|
|
||||||
|
|
||||||
```c
|
|
||||||
#ifndef DEFAULT_ALIGNMENT
|
|
||||||
#define LF_DEFAULT_ALIGNMENT (2*sizeof(void*))
|
|
||||||
#endif // DEFAULT_ALIGNMENT
|
|
||||||
```
|
|
106
docs/network.md
106
docs/network.md
|
@ -1,106 +0,0 @@
|
||||||
# network
|
|
||||||
|
|
||||||
This module provides a generic `Server` type that abstracts away the setup and teardown of a socket
|
|
||||||
|
|
||||||
## Enums
|
|
||||||
|
|
||||||
### ServerType
|
|
||||||
|
|
||||||
Types of servers. Currently supports TCP and UDP, will eventually add UNIX sockets.
|
|
||||||
|
|
||||||
```c
|
|
||||||
typedef enum ServerType {
|
|
||||||
SERVERTYPE_TCP,
|
|
||||||
SERVERTYPE_UDP
|
|
||||||
} ServerType;
|
|
||||||
```
|
|
||||||
|
|
||||||
## Structs
|
|
||||||
|
|
||||||
### Server
|
|
||||||
|
|
||||||
Server is a generic abstraction over sockets. The type of the server is defined by `server_type`.
|
|
||||||
|
|
||||||
```c
|
|
||||||
typedef struct Server {
|
|
||||||
ServerType server_type;
|
|
||||||
int fd;
|
|
||||||
int port;
|
|
||||||
void (*handler)(struct Server *s);
|
|
||||||
} Server;
|
|
||||||
```
|
|
||||||
|
|
||||||
## Functions
|
|
||||||
|
|
||||||
### new_server
|
|
||||||
|
|
||||||
Create a `Server*`. User is responsible for freeing the memory.
|
|
||||||
|
|
||||||
```c
|
|
||||||
Server *new_server(ServerType type, const char *port, void(handler)(Server *s));
|
|
||||||
```
|
|
||||||
|
|
||||||
### delete_server
|
|
||||||
|
|
||||||
Frees the memory allocated for `Server*` and sets the pointer to `NULL`.
|
|
||||||
|
|
||||||
```c
|
|
||||||
void delete_server(Server *s);
|
|
||||||
```
|
|
||||||
|
|
||||||
### serve
|
|
||||||
|
|
||||||
Starts up the server. `backlog_size` is the size of the backlog buffer for the underlying socket. Use the macro
|
|
||||||
`DEFAULT_BACKLOG_SIZE` or pass `0` to use a reasonable default.
|
|
||||||
|
|
||||||
```c
|
|
||||||
int serve(Server *s, int backlog_size);
|
|
||||||
```
|
|
||||||
|
|
||||||
### get_in_addr
|
|
||||||
|
|
||||||
Convenience method to get an IP address from a `struct sockaddr_storage` of either IPV4 or IPV6.
|
|
||||||
|
|
||||||
```c
|
|
||||||
void *get_in_addr(struct sockaddr *sa);
|
|
||||||
|
|
||||||
/* Usage */
|
|
||||||
struct sockaddr_storage client_addr;
|
|
||||||
socklen_t client_addr_sz = sizeof(client_addr);
|
|
||||||
char buf[33];
|
|
||||||
|
|
||||||
if (new_fd = accept(s->fd, (struct sockaddr *)&client_addr, &client_addr_sz) == -1) {
|
|
||||||
/* error handling */
|
|
||||||
}
|
|
||||||
inet_ntop(client_addr.ss_family, get_in_addr((struct sockaddr *)&client_addr), buf, 32);
|
|
||||||
printf("Received connection from %s\n", buf);
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
### handler_tcp_echo
|
|
||||||
|
|
||||||
An example handler for a multithreaded tcp echo server.
|
|
||||||
|
|
||||||
```c
|
|
||||||
void handler_tcp_echo(Server *s);
|
|
||||||
|
|
||||||
/* Usage */
|
|
||||||
#include "lfnetwork.h"
|
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
|
||||||
Server *server = new_server(SERVERTYPE_TCP, "80", handler_tcp_echo);
|
|
||||||
serve(server, DEFAULT_BACKLOG);
|
|
||||||
delete_server(server);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Macros
|
|
||||||
|
|
||||||
### DEFAULT_BACKLOG_SIZE
|
|
||||||
|
|
||||||
A default size for the socket's backlog buffer. `5` is a standard default size, providing some backlog but not
|
|
||||||
enough to make huge buffers for each socket
|
|
||||||
|
|
||||||
```c
|
|
||||||
#define DEFAULT_BACKLOG_SIZE 5
|
|
||||||
```
|
|
|
@ -137,16 +137,6 @@ comparison function to compare the data in the vector. This function must return
|
||||||
const void *vec_max(const Vector *vec, int(*cmp)(const void *a, const void *b));
|
const void *vec_max(const Vector *vec, int(*cmp)(const void *a, const void *b));
|
||||||
```
|
```
|
||||||
|
|
||||||
## Comparison Functions
|
|
||||||
|
|
||||||
Comparison functions to compare data in a vector. These functions must return `1` if `a > b`, `-1` if
|
|
||||||
`a < b`, or `0` if `a == b`.
|
|
||||||
|
|
||||||
```c
|
|
||||||
int vec_cmp_int(const void *a, const void *b);
|
|
||||||
int vec_cmp_char(const void *a, const void *b);
|
|
||||||
```
|
|
||||||
|
|
||||||
## Macros
|
## Macros
|
||||||
|
|
||||||
### vec_at
|
### vec_at
|
||||||
|
|
|
@ -3,15 +3,15 @@
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
char *b64_encode(const unsigned char *s, size_t sz);
|
const char *b64_encode(const unsigned char *s, size_t sz);
|
||||||
unsigned char *b64_decode(const char *s, size_t sz, size_t *decode_sz);
|
unsigned char *b64_decode(const char *s, size_t sz, size_t *decode_sz);
|
||||||
|
|
||||||
char *hex_encode(const unsigned char *hex, size_t sz);
|
const char *hex_encode(const unsigned char *hex, size_t sz);
|
||||||
unsigned char *hex_decode(const char *orig, size_t *sz);
|
unsigned char *hex_decode(const char *orig, size_t *sz);
|
||||||
char *hex_to_str(const unsigned char *hex, size_t sz);
|
const char *hex_to_str(const unsigned char *hex, size_t sz);
|
||||||
|
|
||||||
unsigned char* repeating_key_xor(const unsigned char* s, size_t s_sz, const unsigned char* key, size_t k_sz);
|
const unsigned char* repeating_key_xor(const unsigned char* s, size_t s_sz, const unsigned char* key, size_t k_sz);
|
||||||
unsigned char *repeating_key_xor_s(const char* s, const char* key);
|
const unsigned char *repeating_key_xor_s(const char* s, const char* key);
|
||||||
|
|
||||||
unsigned int hamming_distance_s(const char *a, const char *b);
|
unsigned int hamming_distance_s(const char *a, const char *b);
|
||||||
unsigned int hamming_distance(unsigned char *a, unsigned char *b, size_t sz);
|
unsigned int hamming_distance(unsigned char *a, unsigned char *b, size_t sz);
|
||||||
|
|
|
@ -17,8 +17,4 @@ void del_split(char **);
|
||||||
|
|
||||||
void del_lines(char **);
|
void del_lines(char **);
|
||||||
|
|
||||||
#define DEFAULT_CAPTURE_SYSTEM_BUFSIZE 1024
|
|
||||||
|
|
||||||
const char *capture_system(const char *cmd, int buf_sz);
|
|
||||||
|
|
||||||
#endif // LIBFLINT_INPUT_H
|
#endif // LIBFLINT_INPUT_H
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
#ifndef LIBFLINT_H_MATH
|
#ifndef LIBFLINT_H_MATH
|
||||||
#define LIBFLINT_H_MATH
|
#define LIBFLINT_H_MATH
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
#include "lfutility.h"
|
#include "lfutility.h"
|
||||||
|
|
||||||
int max_int(int a, int b);
|
int max_int(int a, int b);
|
||||||
|
@ -13,10 +11,13 @@ int clamp_int(int i, int low, int high);
|
||||||
|
|
||||||
int binstr_to_int(const char *s);
|
int binstr_to_int(const char *s);
|
||||||
|
|
||||||
int is_power_of_two(int i);
|
|
||||||
|
|
||||||
Point *bresenham(int x0, int y0, int x1, int y1, size_t *sz);
|
Point *bresenham(int x0, int y0, int x1, int y1, size_t *sz);
|
||||||
|
|
||||||
Point *bresenham_p(Point p1, Point p2, size_t *sz);
|
Point *bresenham_p(Point p1, Point p2, size_t *sz);
|
||||||
|
|
||||||
|
int compar_int(const void *a, const void *b);
|
||||||
|
|
||||||
|
int compar_char(const void *a, const void *b);
|
||||||
|
|
||||||
|
|
||||||
#endif // LIBFLINT_H_MATH
|
#endif // LIBFLINT_H_MATH
|
||||||
|
|
|
@ -1,42 +0,0 @@
|
||||||
#ifndef LIBFLINT_H_MEMORY
|
|
||||||
#define LIBFLINT_H_MEMORY
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
#include "lflinkedlist.h"
|
|
||||||
|
|
||||||
#ifndef DEFAULT_ALIGNMENT
|
|
||||||
#define LF_DEFAULT_ALIGNMENT (2*sizeof(void*))
|
|
||||||
#endif // DEFAULT_ALIGNMENT
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
unsigned char* buf;
|
|
||||||
size_t buf_sz;
|
|
||||||
size_t offset_cur;
|
|
||||||
size_t offset_prev;
|
|
||||||
} ArenaAllocator;
|
|
||||||
|
|
||||||
void arena_init(ArenaAllocator *allocator, size_t buf_sz);
|
|
||||||
void arena_free(ArenaAllocator *allocator);
|
|
||||||
void *arena_malloc(ArenaAllocator* allocator, size_t size);
|
|
||||||
void arena_resize_buf(ArenaAllocator *allocator, size_t new_sz);
|
|
||||||
void *arena_resize(ArenaAllocator *allocator, void *mem, size_t old_sz, size_t new_sz);
|
|
||||||
void arena_clear(ArenaAllocator *allocator);
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
unsigned char *buf;
|
|
||||||
size_t buf_sz;
|
|
||||||
size_t chunk_size;
|
|
||||||
|
|
||||||
List *free_list;
|
|
||||||
} PoolAllocator;
|
|
||||||
|
|
||||||
void pool_init(PoolAllocator *allocator, size_t buf_sz, size_t chunk_sz, size_t chunk_align);
|
|
||||||
void pool_free(PoolAllocator *allocator, void *ptr);
|
|
||||||
void pool_free_all(PoolAllocator *allocator);
|
|
||||||
void *pool_alloc(PoolAllocator *allocator);
|
|
||||||
void pool_destroy(PoolAllocator *allocator);
|
|
||||||
|
|
||||||
#define pool_count_available(x) (x)->free_list->size
|
|
||||||
|
|
||||||
#endif // LIBFLINT_H_MEMORY
|
|
|
@ -1,28 +0,0 @@
|
||||||
#ifndef LIBFLINT_NET_H
|
|
||||||
#define LIBFLINT_NET_H
|
|
||||||
|
|
||||||
#include <netdb.h>
|
|
||||||
|
|
||||||
typedef enum ServerType {
|
|
||||||
SERVERTYPE_TCP,
|
|
||||||
SERVERTYPE_UDP
|
|
||||||
} ServerType;
|
|
||||||
|
|
||||||
typedef struct Server {
|
|
||||||
ServerType server_type;
|
|
||||||
int fd;
|
|
||||||
int port;
|
|
||||||
void (*handler)(struct Server *s);
|
|
||||||
} Server;
|
|
||||||
|
|
||||||
#define DEFAULT_BACKLOG 5
|
|
||||||
|
|
||||||
Server *new_server(ServerType type, const char *port, void(handler)(Server *s));
|
|
||||||
void delete_server(Server *s);
|
|
||||||
int serve(Server *s, int backlog_size);
|
|
||||||
void *get_in_addr(struct sockaddr *sa);
|
|
||||||
|
|
||||||
// Example handlers
|
|
||||||
void handler_tcp_echo(Server *s);
|
|
||||||
|
|
||||||
#endif //LIBFLINT_NET_H
|
|
|
@ -5,6 +5,6 @@
|
||||||
|
|
||||||
int find_substrings(const char* haystack, const char* needle, size_t *num_substrings, size_t **substrings);
|
int find_substrings(const char* haystack, const char* needle, size_t *num_substrings, size_t **substrings);
|
||||||
|
|
||||||
char* substr(const char* str, size_t idx, size_t len);
|
const char* substr(const char* str, size_t idx, size_t len);
|
||||||
|
|
||||||
#endif // LIBFLINT_H_STRING
|
#endif // LIBFLINT_H_STRING
|
||||||
|
|
|
@ -18,7 +18,7 @@ void vec_destroy(Vector *vec);
|
||||||
|
|
||||||
int vec_insert(Vector *vec, void *data, size_t index);
|
int vec_insert(Vector *vec, void *data, size_t index);
|
||||||
|
|
||||||
int vec_push(Vector *vec, void *data, size_t *index);
|
int vec_push(Vector *vec, void *data);
|
||||||
|
|
||||||
void *vec_safe_at(Vector *vec, size_t index);
|
void *vec_safe_at(Vector *vec, size_t index);
|
||||||
|
|
||||||
|
@ -30,9 +30,7 @@ const void *vec_min(const Vector *vec, int(*cmp)(const void *a, const void *b));
|
||||||
|
|
||||||
const void *vec_max(const Vector *vec, int(*cmp)(const void *a, const void *b));
|
const void *vec_max(const Vector *vec, int(*cmp)(const void *a, const void *b));
|
||||||
|
|
||||||
int vec_cmp_int(const void *a, const void *b);
|
int vec_sort(Vector *vec, int(*cmp)(const void *a, const void *b));
|
||||||
|
|
||||||
int vec_cmp_char(const void *a, const void *b);
|
|
||||||
|
|
||||||
#define vec_at(v, i) (v)->elements[(i)]
|
#define vec_at(v, i) (v)->elements[(i)]
|
||||||
|
|
||||||
|
|
|
@ -12,8 +12,6 @@ nav:
|
||||||
- 'Linked List': 'linkedlist.md'
|
- 'Linked List': 'linkedlist.md'
|
||||||
- 'Math': 'math.md'
|
- 'Math': 'math.md'
|
||||||
- 'macOS': 'macos.md'
|
- 'macOS': 'macos.md'
|
||||||
- 'Memory': 'memory.md'
|
|
||||||
- 'Network': 'network.md'
|
|
||||||
- 'Parsing': 'parsing.md'
|
- 'Parsing': 'parsing.md'
|
||||||
- 'Set': 'set.md'
|
- 'Set': 'set.md'
|
||||||
- 'Stack': 'stack.md'
|
- 'Stack': 'stack.md'
|
||||||
|
|
12
run_tests.sh
12
run_tests.sh
|
@ -1,12 +0,0 @@
|
||||||
set -e
|
|
||||||
|
|
||||||
#./testrunner
|
|
||||||
./tcptest &
|
|
||||||
tcpout=$(echo "hello" | nc localhost 18632)
|
|
||||||
echo "tcpout: $tcpout"
|
|
||||||
if [ "$tcpout" != "TEST SEND" ]; then
|
|
||||||
echo "Error: \"$tcpout\" != \"TEST SEND\""
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
exit 0
|
|
|
@ -146,8 +146,8 @@ void print_node(char *prefix, BinTreeNode *node, int is_left, void (*pfunc)(void
|
||||||
pfunc(node->data);
|
pfunc(node->data);
|
||||||
char new_prefix[64];
|
char new_prefix[64];
|
||||||
memset(new_prefix, 0, 64);
|
memset(new_prefix, 0, 64);
|
||||||
strlcat(new_prefix, prefix, 64);
|
strcat(new_prefix, prefix);
|
||||||
strlcat(new_prefix, (is_left == 1 ? "│ " : " "), 64 - strlen(prefix));
|
strcat(new_prefix, (is_left == 1 ? "│ " : " "));
|
||||||
print_node(new_prefix, node->left, 1, pfunc);
|
print_node(new_prefix, node->left, 1, pfunc);
|
||||||
print_node(new_prefix, node->right, 0, pfunc);
|
print_node(new_prefix, node->right, 0, pfunc);
|
||||||
}
|
}
|
||||||
|
|
18
src/crypto.c
18
src/crypto.c
|
@ -20,7 +20,7 @@ static const char b64_table[] = {
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
unsigned char *ptr;
|
unsigned char *ptr;
|
||||||
size_t count;
|
int count;
|
||||||
} b64_buf;
|
} b64_buf;
|
||||||
|
|
||||||
static int new_b64_buf(b64_buf *b) {
|
static int new_b64_buf(b64_buf *b) {
|
||||||
|
@ -45,7 +45,7 @@ static int resize_b64_buf(b64_buf *b, size_t sz) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *b64_encode(const unsigned char *s, size_t sz) {
|
const char *b64_encode(const unsigned char *s, size_t sz) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
b64_buf encbuf;
|
b64_buf encbuf;
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
|
@ -204,7 +204,7 @@ unsigned char *b64_decode(const char *s, size_t sz, size_t *decode_sz) {
|
||||||
|
|
||||||
unsigned char *hex_decode(const char *orig, size_t *sz) {
|
unsigned char *hex_decode(const char *orig, size_t *sz) {
|
||||||
size_t buf_sz = strlen(orig) + 1;
|
size_t buf_sz = strlen(orig) + 1;
|
||||||
const char *sptr = orig;
|
char *sptr = orig;
|
||||||
if (strncmp(orig, "0x", 2) == 0) {
|
if (strncmp(orig, "0x", 2) == 0) {
|
||||||
buf_sz -= 2;
|
buf_sz -= 2;
|
||||||
sptr += 2;
|
sptr += 2;
|
||||||
|
@ -216,10 +216,10 @@ unsigned char *hex_decode(const char *orig, size_t *sz) {
|
||||||
|
|
||||||
char *buf = malloc(sizeof(char) * buf_sz);
|
char *buf = malloc(sizeof(char) * buf_sz);
|
||||||
if (strlen(sptr) % 2 != 0) {
|
if (strlen(sptr) % 2 != 0) {
|
||||||
strlcpy(buf + 1, sptr, buf_sz - 1);
|
strcpy(buf+ 1, sptr);
|
||||||
buf[0] = '0';
|
buf[0] = '0';
|
||||||
} else {
|
} else {
|
||||||
strlcpy(buf, sptr, buf_sz);
|
strcpy(buf, sptr);
|
||||||
}
|
}
|
||||||
buf[buf_sz - 1] = '\0';
|
buf[buf_sz - 1] = '\0';
|
||||||
|
|
||||||
|
@ -236,7 +236,7 @@ unsigned char *hex_decode(const char *orig, size_t *sz) {
|
||||||
return hex;
|
return hex;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *hex_encode(const unsigned char *hex, size_t sz) {
|
const char *hex_encode(const unsigned char *hex, size_t sz) {
|
||||||
size_t ssz = sz * 2 + 1;
|
size_t ssz = sz * 2 + 1;
|
||||||
char *s = malloc(sizeof(char) * ssz);
|
char *s = malloc(sizeof(char) * ssz);
|
||||||
char *pos = s;
|
char *pos = s;
|
||||||
|
@ -250,7 +250,7 @@ char *hex_encode(const unsigned char *hex, size_t sz) {
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *hex_to_str(const unsigned char *hex, size_t sz) {
|
const char *hex_to_str(const unsigned char *hex, size_t sz) {
|
||||||
char *s = malloc(sizeof(char) * (sz + 1));
|
char *s = malloc(sizeof(char) * (sz + 1));
|
||||||
for (size_t i = 0; i < sz; ++i) {
|
for (size_t i = 0; i < sz; ++i) {
|
||||||
s[i] = (char)hex[i];
|
s[i] = (char)hex[i];
|
||||||
|
@ -259,7 +259,7 @@ char *hex_to_str(const unsigned char *hex, size_t sz) {
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char* repeating_key_xor(const unsigned char* s, size_t s_sz, const unsigned char* key, size_t k_sz) {
|
const unsigned char* repeating_key_xor(const unsigned char* s, size_t s_sz, const unsigned char* key, size_t k_sz) {
|
||||||
unsigned char* r = malloc(sizeof(unsigned char) * s_sz);
|
unsigned char* r = malloc(sizeof(unsigned char) * s_sz);
|
||||||
for (size_t i = 0, j = 0; i < s_sz; ++i) {
|
for (size_t i = 0, j = 0; i < s_sz; ++i) {
|
||||||
r[i] = s[i] ^ key[j];
|
r[i] = s[i] ^ key[j];
|
||||||
|
@ -268,7 +268,7 @@ unsigned char* repeating_key_xor(const unsigned char* s, size_t s_sz, const unsi
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char *repeating_key_xor_s(const char* s, const char* key) {
|
const unsigned char *repeating_key_xor_s(const char* s, const char* key) {
|
||||||
return repeating_key_xor((unsigned char*)s, strlen(s), (unsigned char*)key, strlen(key));
|
return repeating_key_xor((unsigned char*)s, strlen(s), (unsigned char*)key, strlen(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
16
src/input.c
16
src/input.c
|
@ -2,7 +2,6 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
|
|
||||||
|
@ -122,18 +121,3 @@ void del_split(char **sp) {
|
||||||
void del_lines(char **lines) {
|
void del_lines(char **lines) {
|
||||||
del_split(lines);
|
del_split(lines);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *capture_system(const char *cmd, int buf_sz) {
|
|
||||||
if (buf_sz == 0) {
|
|
||||||
buf_sz = DEFAULT_CAPTURE_SYSTEM_BUFSIZE;
|
|
||||||
}
|
|
||||||
char *buf = malloc(buf_sz);
|
|
||||||
FILE *tmp = popen(cmd, "r");
|
|
||||||
if (tmp == NULL) {
|
|
||||||
fprintf(stderr, "libflint: failed to open FILE *tmp in capture_system. Errno: %d\n", errno);
|
|
||||||
free(buf);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
fgets(buf, buf_sz, tmp);
|
|
||||||
return buf;
|
|
||||||
}
|
|
|
@ -77,6 +77,11 @@ Point *bresenham_p(Point p1, Point p2, size_t *sz) {
|
||||||
return bresenham(p1.x, p1.y, p2.x, p2.y, sz);
|
return bresenham(p1.x, p1.y, p2.x, p2.y, sz);
|
||||||
}
|
}
|
||||||
|
|
||||||
int is_power_of_two(int i) {
|
|
||||||
return (i & (i - 1)) == 0;
|
int compar_int(const void *a, const void *b) {
|
||||||
|
return (*(int*)a - *(int*)b);
|
||||||
|
}
|
||||||
|
|
||||||
|
int compar_char(const void *a, const void *b) {
|
||||||
|
return (*(char*)a - *(char*)b);
|
||||||
}
|
}
|
||||||
|
|
180
src/memory.c
180
src/memory.c
|
@ -1,180 +0,0 @@
|
||||||
#include <lfmath.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include "lfmemory.h"
|
|
||||||
|
|
||||||
#define arena_sz(a) (a)->buf_sz
|
|
||||||
|
|
||||||
void arena_init(ArenaAllocator *allocator, size_t buf_sz) {
|
|
||||||
if (allocator == NULL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
allocator->buf = malloc(sizeof(unsigned char) * buf_sz);
|
|
||||||
allocator->buf_sz = buf_sz;
|
|
||||||
allocator->offset_cur = 0;
|
|
||||||
allocator->offset_prev = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void arena_free(ArenaAllocator *allocator) {
|
|
||||||
free(allocator->buf);
|
|
||||||
free(allocator);
|
|
||||||
}
|
|
||||||
|
|
||||||
void arena_clear(ArenaAllocator *allocator) {
|
|
||||||
allocator->offset_cur = 0;
|
|
||||||
allocator->offset_prev = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uintptr_t align_forward_uintptr(const uintptr_t ptr, const uintptr_t align) {
|
|
||||||
if (!is_power_of_two(align)) {
|
|
||||||
// TODO: Error
|
|
||||||
}
|
|
||||||
uintptr_t p = ptr;
|
|
||||||
const uintptr_t m = p & (align - 1);
|
|
||||||
|
|
||||||
if (m != 0) {
|
|
||||||
p += align - m;
|
|
||||||
}
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uintptr_t align_forward_size(const size_t ptr, const size_t align) {
|
|
||||||
if (!is_power_of_two(align)) {
|
|
||||||
// TODO: Error
|
|
||||||
}
|
|
||||||
uintptr_t p = ptr;
|
|
||||||
const uintptr_t m = p & (align - 1);
|
|
||||||
|
|
||||||
if (m != 0) {
|
|
||||||
p += align - m;
|
|
||||||
}
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void *arena_malloc_align(ArenaAllocator *allocator, const size_t size, size_t align) {
|
|
||||||
uintptr_t cur_ptr = (uintptr_t)allocator->buf + allocator->offset_cur;
|
|
||||||
|
|
||||||
// Push forward to align, then change to relative offset
|
|
||||||
uintptr_t offset = align_forward_uintptr(cur_ptr, align);
|
|
||||||
offset -= (uintptr_t)allocator->buf;
|
|
||||||
|
|
||||||
if (offset + size <= allocator->buf_sz) {
|
|
||||||
void *ptr = &allocator->buf[offset];
|
|
||||||
allocator->offset_prev = offset;
|
|
||||||
allocator->offset_cur = offset + size;
|
|
||||||
memset(ptr, 0, size);
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Arena is full
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void *arena_resize_align(ArenaAllocator *allocator, void *mem, const size_t old_sz, const size_t new_sz, size_t align) {
|
|
||||||
unsigned char *old_mem = mem;
|
|
||||||
if (!is_power_of_two(align)) {
|
|
||||||
// TODO: Error handling
|
|
||||||
}
|
|
||||||
|
|
||||||
if (old_mem == NULL || old_sz == 0) {
|
|
||||||
return arena_malloc_align(allocator, new_sz, align);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (allocator->buf <= (unsigned char*)mem && (unsigned char*)mem < allocator->buf + allocator->buf_sz) {
|
|
||||||
if (allocator->buf + allocator->offset_prev == old_mem) {
|
|
||||||
allocator->offset_cur = allocator->offset_prev + new_sz;
|
|
||||||
if (new_sz > old_sz) {
|
|
||||||
// Zero out memory
|
|
||||||
memset(&allocator->buf[allocator->offset_cur], 0, new_sz - old_sz);
|
|
||||||
}
|
|
||||||
return old_mem;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *new_mem = arena_malloc_align(allocator, new_sz, align);
|
|
||||||
size_t copy_size = old_sz < new_sz ? old_sz : new_sz;
|
|
||||||
memmove(new_mem, old_mem, copy_size);
|
|
||||||
return new_mem;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void arena_resize_buf(ArenaAllocator *allocator, const size_t new_sz) {
|
|
||||||
allocator->buf = realloc(allocator->buf, sizeof(unsigned char) * new_sz);
|
|
||||||
}
|
|
||||||
|
|
||||||
void *arena_malloc(ArenaAllocator *allocator, const size_t size) {
|
|
||||||
return arena_malloc_align(allocator, size, LF_DEFAULT_ALIGNMENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
void *arena_resize(ArenaAllocator *allocator, void *mem, const size_t old_sz, const size_t new_sz) {
|
|
||||||
return arena_resize_align(allocator, mem, old_sz, new_sz, LF_DEFAULT_ALIGNMENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
void pool_init(PoolAllocator *allocator, size_t buf_sz, size_t chunk_sz, size_t chunk_align) {
|
|
||||||
if (allocator == NULL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
allocator->buf = malloc(sizeof(unsigned char) * buf_sz);
|
|
||||||
uintptr_t istart = (uintptr_t)allocator->buf;
|
|
||||||
uintptr_t start = align_forward_uintptr(istart, chunk_align);
|
|
||||||
allocator->buf_sz = buf_sz - (start - istart);
|
|
||||||
|
|
||||||
allocator->chunk_size = align_forward_size(chunk_sz, chunk_align);
|
|
||||||
if (allocator->chunk_size < sizeof(void *) || allocator->buf_sz < allocator->chunk_size) {
|
|
||||||
//TODO: Handle error better
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
allocator->free_list = malloc(sizeof(List));
|
|
||||||
ll_init(allocator->free_list, NULL);
|
|
||||||
|
|
||||||
pool_free_all(allocator);
|
|
||||||
}
|
|
||||||
|
|
||||||
void pool_free(PoolAllocator *allocator, void *ptr) {
|
|
||||||
ListNode *node = NULL;
|
|
||||||
const void *start = allocator->buf;
|
|
||||||
const void *end = &allocator->buf[allocator->buf_sz];
|
|
||||||
|
|
||||||
if (ptr == NULL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(start <= ptr && ptr < end)) {
|
|
||||||
// TODO: Handle error better
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ll_ins_next(allocator->free_list, allocator->free_list->tail, ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void pool_free_all(PoolAllocator *allocator) {
|
|
||||||
size_t chunk_count = allocator->buf_sz / allocator->chunk_size;
|
|
||||||
for (size_t i = 0; i < chunk_count; ++i) {
|
|
||||||
ll_ins_next(allocator->free_list, allocator->free_list->head, &allocator->buf[i * allocator->chunk_size]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void *pool_alloc(PoolAllocator *allocator) {
|
|
||||||
ListNode *node = allocator->free_list->head;
|
|
||||||
if (node == NULL) {
|
|
||||||
// TODO: Handle error better
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *tmp;
|
|
||||||
ll_remove(allocator->free_list, allocator->free_list->head, &tmp);
|
|
||||||
return memset(tmp, 0, allocator->chunk_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void pool_destroy(PoolAllocator *allocator) {
|
|
||||||
ll_destroy(allocator->free_list);
|
|
||||||
free(allocator->free_list);
|
|
||||||
free(allocator->buf);
|
|
||||||
free(allocator);
|
|
||||||
}
|
|
150
src/network.c
150
src/network.c
|
@ -1,150 +0,0 @@
|
||||||
#include <errno.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
#include <sys/wait.h>
|
|
||||||
#include <netdb.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <pthread.h>
|
|
||||||
|
|
||||||
#include "lfnetwork.h"
|
|
||||||
|
|
||||||
static void sighandler(int s) {
|
|
||||||
int saved_errno = errno;
|
|
||||||
while (waitpid(-1, NULL, WNOHANG) > 0);
|
|
||||||
errno = saved_errno;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *get_in_addr(struct sockaddr *sa)
|
|
||||||
{
|
|
||||||
if (sa->sa_family == AF_INET) {
|
|
||||||
return &(((struct sockaddr_in*)sa)->sin_addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
return &(((struct sockaddr_in6*)sa)->sin6_addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
Server *new_server(ServerType type, const char *port, void(handler)(Server *s)) {
|
|
||||||
Server *s = (Server *)malloc(sizeof(Server));
|
|
||||||
if (s == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
s->server_type = type;
|
|
||||||
s->handler = handler;
|
|
||||||
|
|
||||||
struct addrinfo *addr = NULL;
|
|
||||||
if (getaddrinfo(NULL, port, NULL, &addr) != 0) {
|
|
||||||
free(s);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
s->port = (int)strtol(port, NULL, 10);
|
|
||||||
|
|
||||||
int socktype = 0;
|
|
||||||
switch (type) {
|
|
||||||
case SERVERTYPE_TCP:
|
|
||||||
socktype = SOCK_STREAM;
|
|
||||||
break;
|
|
||||||
case SERVERTYPE_UDP:
|
|
||||||
socktype = SOCK_DGRAM;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct addrinfo *p;
|
|
||||||
for (p = addr; p != NULL; p = p->ai_next) {
|
|
||||||
s->fd = socket(AF_INET, socktype, 0);
|
|
||||||
if (s->fd == -1) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bind(s->fd, p->ai_addr, p->ai_addrlen) != 0) {
|
|
||||||
close(s->fd);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p == NULL) {
|
|
||||||
fprintf(stderr, "Failed to bind\n");
|
|
||||||
free(s);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
freeaddrinfo(addr);
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
void delete_server(Server *s) {
|
|
||||||
free(s);
|
|
||||||
s = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
int serve(Server *s, int backlog_size) {
|
|
||||||
if (backlog_size == 0) {
|
|
||||||
backlog_size = DEFAULT_BACKLOG;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (listen(s->fd, backlog_size) != 0) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Linux doesn't handle SA_RESTART properly, and I don't know about Windows (nor do I care)
|
|
||||||
// This is just for macOS and BSDs
|
|
||||||
#if !defined(__linux__) && !defined(_WIN32)
|
|
||||||
struct sigaction sa;
|
|
||||||
sa.sa_handler = sighandler;
|
|
||||||
sa.sa_flags = SA_RESTART;
|
|
||||||
if (sigaction(SIGCHLD, &sa, NULL) == -1) {
|
|
||||||
fprintf(stderr, "Failed to set sigaction\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
s->handler(s);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void *tcp_echo_thread(void *vargp) {
|
|
||||||
while (1) {
|
|
||||||
char recv_buf[256];
|
|
||||||
int fd = *(int *) vargp;
|
|
||||||
|
|
||||||
int r = (int)recv(fd, recv_buf, 256, 0);
|
|
||||||
if (r < 1) {
|
|
||||||
if (r == -1) {
|
|
||||||
fprintf(stderr, "Failed to recv. Errno: %d\n", errno);
|
|
||||||
}
|
|
||||||
close(fd);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (send(fd, recv_buf, strlen(recv_buf), 0) == -1) {
|
|
||||||
fprintf(stderr, "Failed to send echo. Errno: %d\n", errno);
|
|
||||||
close(fd);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void handler_tcp_echo(Server *s) {
|
|
||||||
while (1) {
|
|
||||||
struct sockaddr_storage client_addr;
|
|
||||||
socklen_t client_addr_sz = sizeof(client_addr);
|
|
||||||
int new_fd = accept(s->fd, (struct sockaddr *)&client_addr, &client_addr_sz);
|
|
||||||
if (new_fd == -1) {
|
|
||||||
fprintf(stderr, "failed to accept. Errno: %d\n", errno);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
pthread_t srv_tid;
|
|
||||||
pthread_attr_t attr;
|
|
||||||
pthread_attr_init(&attr);
|
|
||||||
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
|
||||||
pthread_create(&srv_tid, &attr, tcp_echo_thread, &new_fd);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -26,4 +26,3 @@ int simple_english_scoring(const char *s) {
|
||||||
}
|
}
|
||||||
return score;
|
return score;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@ int find_substrings(const char* haystack, const char* needle, size_t *num_substr
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* substr(const char* str, size_t idx, size_t len) {
|
const char* substr(const char* str, size_t idx, size_t len) {
|
||||||
size_t sz_str = strlen(str);
|
size_t sz_str = strlen(str);
|
||||||
if (sz_str < len || idx + len > sz_str) {
|
if (sz_str < len || idx + len > sz_str) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
41
src/vector.c
41
src/vector.c
|
@ -35,9 +35,7 @@ int vec_init_with_capacity(Vector *vec, void (*destroy)(void *data), size_t capa
|
||||||
|
|
||||||
static int vec_grow(Vector *const vec) {
|
static int vec_grow(Vector *const vec) {
|
||||||
vec->capacity *= 2;
|
vec->capacity *= 2;
|
||||||
|
|
||||||
vec->elements = reallocarray(vec->elements, vec->capacity, sizeof(void *));
|
vec->elements = reallocarray(vec->elements, vec->capacity, sizeof(void *));
|
||||||
|
|
||||||
if (vec->elements == NULL) {
|
if (vec->elements == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -81,10 +79,7 @@ int vec_insert(Vector *vec, void *data, size_t index) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int vec_push(Vector *vec, void *data, size_t *index) {
|
int vec_push(Vector *vec, void *data) {
|
||||||
if (index != NULL) {
|
|
||||||
*index = vec_len(vec);
|
|
||||||
}
|
|
||||||
return vec_insert(vec, data, vec_len(vec));
|
return vec_insert(vec, data, vec_len(vec));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,19 +108,11 @@ int vec_shrink(Vector *vec) {
|
||||||
if (vec_len(vec) == vec_cap(vec)) {
|
if (vec_len(vec) == vec_cap(vec)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
vec->capacity = vec_len(vec);
|
vec->capacity = vec_len(vec);
|
||||||
|
|
||||||
#if !defined(__OpenBSD__)
|
|
||||||
vec->elements = reallocf(vec->elements, sizeof(void *) * vec->capacity);
|
|
||||||
#else
|
|
||||||
vec->elements = reallocarray(vec->elements, vec->capacity, sizeof(void *));
|
vec->elements = reallocarray(vec->elements, vec->capacity, sizeof(void *));
|
||||||
#endif
|
|
||||||
|
|
||||||
if (vec->elements == NULL) {
|
if (vec->elements == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,28 +136,10 @@ const void *vec_max(const Vector *vec, int(*cmp)(const void *a, const void *b))
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
int vec_cmp_int(const void *a, const void *b) {
|
int vec_sort(Vector *vec, int(*cmp)(const void *a, const void *b)) {
|
||||||
const int x = *(int*)a;
|
if (vec_len(vec) == 0) {
|
||||||
const int y = *(int*)b;
|
|
||||||
|
|
||||||
if (x > y) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (x < y) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
qsort(vec->elements, vec->length, sizeof(void *), cmp);
|
||||||
int vec_cmp_char(const void *a, const void *b) {
|
|
||||||
const char x = *(int*)a;
|
|
||||||
const char y = *(int*)b;
|
|
||||||
|
|
||||||
if (x > y) {
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
|
||||||
if (x < y) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
#include "lfnetwork.h"
|
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
|
||||||
Server *server = new_server(SERVERTYPE_TCP, "18632", handler_tcp_echo);
|
|
||||||
serve(server, DEFAULT_BACKLOG);
|
|
||||||
delete_server(server);
|
|
||||||
}
|
|
173
tests/tests.c
173
tests/tests.c
|
@ -2,12 +2,8 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <arpa/inet.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <pthread.h>
|
|
||||||
|
|
||||||
#include "lflinkedlist.h"
|
#include "lflinkedlist.h"
|
||||||
#include "lfnetwork.h"
|
|
||||||
#include "lfset.h"
|
#include "lfset.h"
|
||||||
#include "lfstack.h"
|
#include "lfstack.h"
|
||||||
#include "lfbinarytree.h"
|
#include "lfbinarytree.h"
|
||||||
|
@ -16,8 +12,6 @@
|
||||||
#include "lfstring.h"
|
#include "lfstring.h"
|
||||||
#include "lfcrypto.h"
|
#include "lfcrypto.h"
|
||||||
#include "lfparsing.h"
|
#include "lfparsing.h"
|
||||||
#include "lfinput.h"
|
|
||||||
#include "lfmemory.h"
|
|
||||||
|
|
||||||
#if defined(__APPLE__) || defined(__MACH__)
|
#if defined(__APPLE__) || defined(__MACH__)
|
||||||
#include "lfmacos.h"
|
#include "lfmacos.h"
|
||||||
|
@ -71,9 +65,9 @@ void test_set() {
|
||||||
int j = 2;
|
int j = 2;
|
||||||
int k = 2;
|
int k = 2;
|
||||||
|
|
||||||
set_insert(set, &i);
|
set_insert(set, (void *) &i);
|
||||||
set_insert(set, &j);
|
set_insert(set, (void *) &j);
|
||||||
set_insert(set, &k);
|
set_insert(set, (void *) &k);
|
||||||
|
|
||||||
int i2 = 1;
|
int i2 = 1;
|
||||||
int j2 = 4;
|
int j2 = 4;
|
||||||
|
@ -81,8 +75,8 @@ void test_set() {
|
||||||
Set *set2 = malloc(sizeof(Set));
|
Set *set2 = malloc(sizeof(Set));
|
||||||
set_init(set2, int_match, NULL);
|
set_init(set2, int_match, NULL);
|
||||||
|
|
||||||
set_insert(set2, &i2);
|
set_insert(set2, (void *) &i2);
|
||||||
set_insert(set2, &j2);
|
set_insert(set2, (void *) &j2);
|
||||||
|
|
||||||
printf("Set 1:");
|
printf("Set 1:");
|
||||||
print_ll(set);
|
print_ll(set);
|
||||||
|
@ -203,7 +197,7 @@ void test_math() {
|
||||||
|
|
||||||
void print_vector(Vector *vec) {
|
void print_vector(Vector *vec) {
|
||||||
for (size_t i = 0; i < vec->length; ++i) {
|
for (size_t i = 0; i < vec->length; ++i) {
|
||||||
int t = *(int *) vec_at(vec, i);
|
int t = *(int*)vec_at(vec, i);
|
||||||
printf("%d ", t);
|
printf("%d ", t);
|
||||||
}
|
}
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
@ -220,47 +214,45 @@ void test_vector() {
|
||||||
int e3 = 3;
|
int e3 = 3;
|
||||||
int e4 = 4;
|
int e4 = 4;
|
||||||
|
|
||||||
size_t idx = 0;
|
vec_push(v, &e0);
|
||||||
vec_push(v, &e0, &idx);
|
|
||||||
assert(idx == 0);
|
|
||||||
assert(v->length == 1);
|
assert(v->length == 1);
|
||||||
int *t = (int *) vec_at(v, 0);
|
int *t = (int*)vec_at(v, 0);
|
||||||
assert(*t == 0);
|
assert(*t == 0);
|
||||||
|
|
||||||
vec_push(v, &e1, NULL);
|
vec_push(v, &e1);
|
||||||
vec_push(v, &e2, NULL);
|
vec_push(v, &e2);
|
||||||
assert(v->length == 3);
|
assert(v->length == 3);
|
||||||
|
|
||||||
// test access outside bounds
|
// test access outside bounds
|
||||||
t = (int *) vec_safe_at(v, 3);
|
t = (int*)vec_safe_at(v, 3);
|
||||||
assert(t == NULL);
|
assert(t == NULL);
|
||||||
|
|
||||||
printf("Before insert: ");
|
printf("Before insert: ");
|
||||||
print_vector(v);
|
print_vector(v);
|
||||||
vec_push(v, &e4, NULL);
|
vec_push(v, &e4);
|
||||||
vec_insert(v, &e3, 3);
|
vec_insert(v, &e3, 3);
|
||||||
printf("After insert: ");
|
printf("After insert: ");
|
||||||
print_vector(v);
|
print_vector(v);
|
||||||
|
|
||||||
t = (int *) vec_at(v, 3);
|
t = (int*)vec_at(v, 3);
|
||||||
assert(*t == e3);
|
assert(*t == e3);
|
||||||
t = (int *) vec_at(v, 4);
|
t = (int*)vec_at(v, 4);
|
||||||
assert(*t == e4);
|
assert(*t == e4);
|
||||||
|
|
||||||
const int *min = vec_min(v, vec_cmp_int);
|
const int *min = vec_min(v, compar_int);
|
||||||
const int *max = vec_max(v, vec_cmp_int);
|
const int *max = vec_max(v, compar_int);
|
||||||
printf("min: %d\n", *min);
|
printf("min: %d\n", *min);
|
||||||
printf("max: %d\n", *max);
|
printf("max: %d\n", *max);
|
||||||
assert(*min == e0);
|
assert(*min == e0);
|
||||||
assert(*max == e4);
|
assert(*max == e4);
|
||||||
|
|
||||||
t = (int *) vec_remove(v, 1);
|
t = (int*)vec_remove(v, 1);
|
||||||
assert(t != NULL);
|
assert(t != NULL);
|
||||||
assert(*t == 1);
|
assert(*t == 1);
|
||||||
printf("After removal: ");
|
printf("After removal: ");
|
||||||
print_vector(v);
|
print_vector(v);
|
||||||
|
|
||||||
t = (int *) vec_remove(v, 10);
|
t = (int*)vec_remove(v, 10);
|
||||||
assert(t == NULL);
|
assert(t == NULL);
|
||||||
|
|
||||||
printf("\ncap before shrink: %zu\n", vec_cap(v));
|
printf("\ncap before shrink: %zu\n", vec_cap(v));
|
||||||
|
@ -268,15 +260,26 @@ void test_vector() {
|
||||||
assert(vec_len(v) == vec_cap(v));
|
assert(vec_len(v) == vec_cap(v));
|
||||||
printf("cap after shrink: %zu\n", vec_cap(v));
|
printf("cap after shrink: %zu\n", vec_cap(v));
|
||||||
|
|
||||||
|
int s1 = 10;
|
||||||
|
int s2 = 2;
|
||||||
|
int s3 = 1;
|
||||||
|
vec_push(v, &s1);
|
||||||
|
vec_push(v, &s2);
|
||||||
|
vec_push(v, &s3);
|
||||||
|
|
||||||
|
printf("Before sort: ");
|
||||||
|
print_vector(v);
|
||||||
|
vec_sort(v, compar_int);
|
||||||
|
printf("After sort: ");
|
||||||
|
print_vector(v);
|
||||||
|
|
||||||
vec_destroy(v);
|
vec_destroy(v);
|
||||||
free(v);
|
free(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_string() {
|
void test_string() {
|
||||||
printf("\n--- STRING TEST ---\n");
|
printf("\n--- STRING TEST ---\n");
|
||||||
const char *haystack =
|
const char* haystack = "Test one two one and also maybe two but not Gabe's least favorite number, which is not one.";
|
||||||
"Test one two one and also maybe two but not Gabe's least favorite number, which is not one.";
|
const char* needles[] = {
|
||||||
const char *needles[] = {
|
|
||||||
"one",
|
"one",
|
||||||
"two",
|
"two",
|
||||||
"Gabe"
|
"Gabe"
|
||||||
|
@ -291,7 +294,7 @@ void test_string() {
|
||||||
assert(subs[1] == 13);
|
assert(subs[1] == 13);
|
||||||
assert(subs[2] == 87);
|
assert(subs[2] == 87);
|
||||||
|
|
||||||
char *s = substr(haystack, subs[0], strlen(needles[0]));
|
const char *s = substr(haystack, subs[0], strlen(needles[0]));
|
||||||
assert(strcmp(s, needles[0]) == 0);
|
assert(strcmp(s, needles[0]) == 0);
|
||||||
|
|
||||||
free(s);
|
free(s);
|
||||||
|
@ -335,7 +338,7 @@ void test_crypto() {
|
||||||
|
|
||||||
char *out2 = "YSBsb25nZXIgYmFzZTY0IHRlc3QsIGFwcGFyZW50bHk=";
|
char *out2 = "YSBsb25nZXIgYmFzZTY0IHRlc3QsIGFwcGFyZW50bHk=";
|
||||||
size_t s_sz = 0;
|
size_t s_sz = 0;
|
||||||
s = (char *) b64_decode(out2, strlen(out2), &s_sz);
|
s = (char *)b64_decode(out2, strlen(out2), &s_sz);
|
||||||
assert(strcmp(s, "a longer base64 test, apparently") == 0);
|
assert(strcmp(s, "a longer base64 test, apparently") == 0);
|
||||||
assert(strlen(s) == s_sz);
|
assert(strlen(s) == s_sz);
|
||||||
free(s);
|
free(s);
|
||||||
|
@ -379,13 +382,13 @@ void test_crypto() {
|
||||||
free(s);
|
free(s);
|
||||||
|
|
||||||
s = repeating_key_xor_s("TEST", "HI");
|
s = repeating_key_xor_s("TEST", "HI");
|
||||||
char *enc = hex_encode(s, 4);
|
const char *enc = hex_encode(s, 4);
|
||||||
assert(strcmp(enc, "1c0c1b1d") == 0);
|
assert(strcmp(enc, "1c0c1b1d") == 0);
|
||||||
free(enc);
|
free(enc);
|
||||||
free(s);
|
free(s);
|
||||||
|
|
||||||
unsigned char ua[2] = {0x2, 0xF};
|
unsigned char ua[2] = { 0x2, 0xF };
|
||||||
unsigned char ub[2] = {0x4, 0xE};
|
unsigned char ub[2] = { 0x4, 0xE };
|
||||||
unsigned int hamming = hamming_distance(ua, ub, 2);
|
unsigned int hamming = hamming_distance(ua, ub, 2);
|
||||||
assert(hamming == 3);
|
assert(hamming == 3);
|
||||||
|
|
||||||
|
@ -405,60 +408,6 @@ void test_parsing() {
|
||||||
printf("Passes all parsing tests\n");
|
printf("Passes all parsing tests\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
#define NET_MSG "TEST SEND"
|
|
||||||
|
|
||||||
void tcp_test_handler(Server *s) {
|
|
||||||
struct sockaddr_storage client_addr;
|
|
||||||
socklen_t client_addr_sz = sizeof(client_addr);
|
|
||||||
int new_fd = accept(s->fd, (struct sockaddr *) &client_addr, &client_addr_sz);
|
|
||||||
assert(new_fd != -1);
|
|
||||||
assert(send(new_fd, NET_MSG, 10, 0) != -1);
|
|
||||||
close(new_fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
void *tcp_server_thread(void *vargp) {
|
|
||||||
Server *server = new_server(SERVERTYPE_TCP, "18632", tcp_test_handler);
|
|
||||||
serve(server, DEFAULT_BACKLOG);
|
|
||||||
delete_server(server);
|
|
||||||
}
|
|
||||||
|
|
||||||
void udp_test_handler(Server *s) {
|
|
||||||
struct sockaddr_storage client_addr;
|
|
||||||
socklen_t client_addr_sz = sizeof(client_addr);
|
|
||||||
char recv_buf[128];
|
|
||||||
|
|
||||||
int r = (int) recvfrom(s->fd, recv_buf, 128, 0, (struct sockaddr *) &client_addr, &client_addr_sz);
|
|
||||||
assert(r > 0);
|
|
||||||
assert(strcmp(recv_buf, NET_MSG) == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void *udp_server_thread(void *vargp) {
|
|
||||||
Server *server = new_server(SERVERTYPE_UDP, "18633", udp_test_handler);
|
|
||||||
serve(server, DEFAULT_BACKLOG);
|
|
||||||
delete_server(server);
|
|
||||||
}
|
|
||||||
|
|
||||||
void test_network() {
|
|
||||||
printf("\n--- NETWORK TEST ---\n");
|
|
||||||
pthread_t srv_tid;
|
|
||||||
pthread_create(&srv_tid, NULL, tcp_server_thread, NULL);
|
|
||||||
|
|
||||||
sleep(1);
|
|
||||||
const char *s = capture_system("echo hello | nc localhost 18632", 0);
|
|
||||||
assert(strcmp(s, NET_MSG) == 0);
|
|
||||||
free((char *) s);
|
|
||||||
|
|
||||||
pthread_join(srv_tid, NULL);
|
|
||||||
printf("Passed TCP test\n");
|
|
||||||
|
|
||||||
pthread_create(&srv_tid, NULL, udp_server_thread, NULL);
|
|
||||||
sleep(1);
|
|
||||||
system("echo hello | nc localhost 18633");
|
|
||||||
|
|
||||||
pthread_join(srv_tid, NULL);
|
|
||||||
printf("Passed UDP test\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(__APPLE__) || defined(__MACH__)
|
#if defined(__APPLE__) || defined(__MACH__)
|
||||||
void test_macos() {
|
void test_macos() {
|
||||||
printf("\n--- macOS TEST ---\n");
|
printf("\n--- macOS TEST ---\n");
|
||||||
|
@ -474,50 +423,6 @@ void test_macos() {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void test_memory() {
|
|
||||||
printf("\n--- MEMORY TEST ---\n");
|
|
||||||
ArenaAllocator *arena = malloc(sizeof(ArenaAllocator));
|
|
||||||
arena_init(arena, 1024);
|
|
||||||
|
|
||||||
int *i1 = arena_malloc(arena, sizeof(int));
|
|
||||||
int *i2 = arena_malloc(arena, sizeof(int));
|
|
||||||
|
|
||||||
*i1 = 1;
|
|
||||||
*i2 = 2;
|
|
||||||
|
|
||||||
assert(i1 < i2);
|
|
||||||
assert(*i1 < *i2);
|
|
||||||
|
|
||||||
long *l = arena_resize(arena, i1, sizeof(int), sizeof(long));
|
|
||||||
assert(*l == 1);
|
|
||||||
|
|
||||||
unsigned char *char_test = arena_resize(arena, i2, sizeof(int), sizeof(unsigned char));
|
|
||||||
assert(*char_test == 2);
|
|
||||||
|
|
||||||
arena_free(arena);
|
|
||||||
arena = NULL;
|
|
||||||
|
|
||||||
PoolAllocator *pool = malloc(sizeof(PoolAllocator));
|
|
||||||
pool_init(pool, 64, 16, LF_DEFAULT_ALIGNMENT);
|
|
||||||
void *a = pool_alloc(pool);
|
|
||||||
void *b = pool_alloc(pool);
|
|
||||||
void *c = pool_alloc(pool);
|
|
||||||
void *d = pool_alloc(pool);
|
|
||||||
|
|
||||||
assert(a != NULL);
|
|
||||||
assert(b != NULL);
|
|
||||||
assert(c != NULL);
|
|
||||||
assert(d != NULL);
|
|
||||||
|
|
||||||
assert(pool_count_available(pool) == 0);
|
|
||||||
pool_free(pool, d);
|
|
||||||
d = NULL;
|
|
||||||
assert(pool_count_available(pool) == 1);
|
|
||||||
|
|
||||||
pool_destroy(pool);
|
|
||||||
printf("Passes all memory tests\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
test_ll();
|
test_ll();
|
||||||
test_set();
|
test_set();
|
||||||
|
@ -528,8 +433,6 @@ int main() {
|
||||||
test_string();
|
test_string();
|
||||||
test_crypto();
|
test_crypto();
|
||||||
test_parsing();
|
test_parsing();
|
||||||
test_network();
|
|
||||||
test_memory();
|
|
||||||
|
|
||||||
#if defined(__APPLE__) || defined(__MACH__)
|
#if defined(__APPLE__) || defined(__MACH__)
|
||||||
test_macos();
|
test_macos();
|
||||||
|
|
Loading…
Reference in New Issue