1
1
mirror of https://github.com/theoludwig/libcproject.git synced 2025-05-21 23:21:15 +02:00

46 Commits

Author SHA1 Message Date
be8a63ca8a chore(release): 3.0.0 [skip ci] 2023-08-05 13:40:47 +00:00
693cab7a34 chore: only use sanitizer flags in test 2023-08-05 15:33:19 +02:00
3220c0e26b chore: update @since version 2023-08-05 15:03:53 +02:00
06b34b115b feat: support giving a custom character for string_trim, string_trim_start, string_trim_end
BREAKING CHANGE: Functions signatures changed.
If you want to preserve the same behavior, you should pass explictly the space character to trim:
Example: `string_trim(" Hello ")` => `string_trim(" Hello ", ' ')`
2023-08-05 14:19:44 +02:00
316dfa10e7 chore: improve Makefile to use -fsanitize=address -fsanitize=undefined gcc flags
Fixes #5
2023-08-04 19:58:41 +02:00
145dfcf546 fix: more memory issues thanks to -fsanitize=address flag
Work In Progress #5
2023-08-04 19:20:00 +02:00
d345c90ba3 style: fix linting 2023-08-04 00:02:35 +02:00
209440588d fix: more memory issues thanks to -fsanitize=address flag
Work In Progress #5
2023-08-03 23:55:14 +02:00
a0a1310f53 feat: add hash_map_free 2023-08-03 23:17:54 +02:00
8b6f06dc6e feat: add stack_free 2023-08-03 23:01:19 +02:00
1e475a59b1 feat: add queue_free 2023-08-03 22:57:32 +02:00
6a40df3ad1 feat: add linked_list_free 2023-08-03 19:48:02 +02:00
d231a0f055 feat: add array_list_free 2023-08-03 19:42:50 +02:00
2796dec0c7 fix: memory issues thanks to -fsanitize=address flag
Work In Progress #5
2023-08-03 19:35:44 +02:00
9717cff35a feat: add terminal_print_array_list 2023-07-31 23:51:37 +02:00
368c07c57a fix: char* issues with memory allocation
Work In progress #5
2023-06-26 22:32:26 +02:00
d774ef6ad4 chore(release): 2.0.0 [skip ci] 2023-06-25 19:42:33 +00:00
e7726b8cc7 ci: install documentation tools 2023-06-25 21:39:53 +02:00
c168a7179d ci: check all possible Makefile paths 2023-06-25 21:37:56 +02:00
c5a7bbf7c1 fix: set_version typings 2023-06-25 21:35:24 +02:00
074d9e0acb docs: fix doxygen warnings 2023-06-25 21:32:16 +02:00
0c93355e60 chore: remove .exe file extension to be more "linux way" 2023-06-25 20:17:28 +02:00
016bfeb47f perf: use SipHash 1-3 algorithm for hash_map 2023-06-25 20:09:07 +02:00
baea00fdac feat!: remove dictionary data structure
Replaced by `hash_map`
2023-06-25 20:09:07 +02:00
256e9cb690 refactor: usage of hash_map instead of dictionary 2023-06-25 20:09:07 +02:00
4a11a096fa feat: add hash_map data structure
fixes #3
2023-06-25 20:09:07 +02:00
931a0b69ce chore: replace missing string_t 2023-06-25 20:09:07 +02:00
682997c0a5 chore: prefix all #define for includes with LIBCPROJECT 2023-06-25 20:09:07 +02:00
5f60abc759 chore: remove useless @return 2023-06-25 20:09:07 +02:00
a0140a6716 feat: add types.h 2023-06-25 20:09:07 +02:00
1ded37b106 feat!: rename types string to string_t and byte to byte_t 2023-06-25 20:08:58 +02:00
8f3ee199e5 feat: add string type 2023-06-25 15:20:38 +02:00
ce088f8ff5 feat: add byte typedef 2023-06-25 15:20:38 +02:00
eb798a619a fix: update filesystem_read and filesystem_write signatures
BREAKING CHANGE: take a `uint8_t` for file_content instead of `char`

It makes more sense to treat files as array of "bytes", not only characters/text files.
2023-06-25 15:20:07 +02:00
b9f573bfb2 feat: support more mimetypes for filesystem_get_mimetype 2023-06-24 21:15:55 +02:00
b665e3629d fix: handle filesystem read and write errors 2023-06-24 21:13:00 +02:00
d42ec38e36 ci: add gcc --version 2023-06-24 21:09:19 +02:00
d1b93d1da0 docs: add @since to know when a structure/function was added 2023-06-24 21:06:45 +02:00
071b645cb4 build(deps): update doxygen-awesome-css to v2.2.1 2023-06-24 20:44:48 +02:00
e5d07d73cd ci: set dependencies version explicitly 2023-06-24 20:39:14 +02:00
d850f04069 perf: compile with -O3 gcc flag 2023-06-24 20:30:34 +02:00
20d31ba2e3 fix: update author - Théo LUDWIG 2023-06-24 20:29:30 +02:00
f1a729c418 chore(release): 1.2.0 [skip ci] 2023-01-07 18:43:17 +00:00
bd85171e2d refactor: include only in header files 2023-01-07 19:41:04 +01:00
886038a0ac feat: add array_list data structure
fixes #2
2023-01-07 19:40:16 +01:00
821c27c6a9 chore: minor improvements 2023-01-07 18:57:14 +01:00
64 changed files with 1681 additions and 694 deletions

View File

@ -1,6 +1,6 @@
<!-- Please first discuss the change you wish to make via issue before making a change. It might avoid a waste of your time. --> <!-- Please first discuss the change you wish to make via issue before making a change. It might avoid a waste of your time. -->
## What changes this PR introduce? # What changes this PR introduce?
## List any relevant issue numbers ## List any relevant issue numbers

View File

@ -10,22 +10,31 @@ jobs:
ci: ci:
runs-on: 'ubuntu-latest' runs-on: 'ubuntu-latest'
steps: steps:
- uses: 'actions/checkout@v3.0.0' - uses: 'actions/checkout@v3.5.3'
- run: 'sudo apt update'
- name: 'Install Build Tools' - name: 'Install Build Tools'
run: 'sudo apt-get install --yes build-essential gcc make clang-format' run: 'sudo apt-get install --yes build-essential gcc make clang-format'
- name: 'Install Documentation Tools'
run: 'sudo apt-get install --yes doxygen doxygen-gui doxygen-doc graphviz'
- run: 'gcc --version'
- run: 'make' - run: 'make'
- run: 'make run' - run: 'make run'
- run: 'make test' - run: 'make test'
- run: 'make lint' - run: 'make lint'
- run: 'make documentation'
- run: 'make set_version'
- run: 'make clean' - run: 'make clean'
lint-commit: lint-commit:
runs-on: 'ubuntu-latest' runs-on: 'ubuntu-latest'
steps: steps:
- uses: 'actions/checkout@v3.0.0' - uses: 'actions/checkout@v3.5.3'
with: with:
fetch-depth: 0 fetch-depth: 0
- uses: 'wagoid/commitlint-github-action@v5.3.0' - uses: 'wagoid/commitlint-github-action@v5.4.1'

View File

@ -8,31 +8,36 @@ jobs:
release: release:
runs-on: 'ubuntu-latest' runs-on: 'ubuntu-latest'
steps: steps:
- uses: 'actions/checkout@v3.1.0' - uses: 'actions/checkout@v3.5.3'
with: with:
fetch-depth: 0 fetch-depth: 0
persist-credentials: false persist-credentials: false
submodules: recursive submodules: recursive
- name: 'Import GPG key' - name: 'Import GPG key'
uses: 'crazy-max/ghaction-import-gpg@v4' uses: 'crazy-max/ghaction-import-gpg@v5.3.0'
with: with:
gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }} gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }}
git_user_signingkey: true git_user_signingkey: true
git_commit_gpgsign: true git_commit_gpgsign: true
- run: 'sudo apt update'
- name: 'Install Build Tools' - name: 'Install Build Tools'
run: 'sudo apt-get install --yes build-essential gcc make clang-format doxygen doxygen-gui doxygen-doc graphviz' run: 'sudo apt-get install --yes build-essential gcc make clang-format'
- name: 'Install Documentation Tools'
run: 'sudo apt-get install --yes doxygen doxygen-gui doxygen-doc graphviz'
- run: 'make set_version' - run: 'make set_version'
- name: 'Use Node.js' - name: 'Use Node.js'
uses: 'actions/setup-node@v3.1.0' uses: 'actions/setup-node@v3.7.0'
with: with:
node-version: 'lts/*' node-version: '18.17.0'
- name: 'Install Release Tools' - name: 'Install Release Tools'
run: 'npm install --save-dev semantic-release @commitlint/cli @commitlint/config-conventional @semantic-release/git @semantic-release/exec @saithodev/semantic-release-backmerge vercel' run: 'npm install --save-dev semantic-release@21.0.7 @commitlint/cli@17.6.7 @commitlint/config-conventional@17.6.7 @semantic-release/git@10.0.1 @semantic-release/exec@6.0.3 @saithodev/semantic-release-backmerge@3.2.0 vercel@31.2.2'
- run: 'rm --force package.json package-lock.json' - run: 'rm --force package.json package-lock.json'

3
.gitignore vendored
View File

@ -4,6 +4,7 @@ documentation
.vscode .vscode
*.out *.out
*.o *.o
*.exe
*.a *.a
node_modules node_modules
package.json
package-lock.json

View File

@ -16,7 +16,7 @@
[ [
"@semantic-release/exec", "@semantic-release/exec",
{ {
"prepareCmd": "make set_version && ./bin/set_version.exe ${nextRelease.version}" "prepareCmd": "make set_version && ./bin/set_version ${nextRelease.version}"
} }
], ],
[ [

View File

@ -60,7 +60,7 @@ representative at an online or offline event.
Instances of abusive, harassing, or otherwise unacceptable behavior may be Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at reported to the community leaders responsible for enforcement at
contact@divlo.fr. <contact@theoludwig.fr>.
All complaints will be reviewed and investigated promptly and fairly. All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the All community leaders are obligated to respect the privacy and security of the

View File

@ -2,6 +2,14 @@
Thanks a lot for your interest in contributing to **libcproject**! 🎉 Thanks a lot for your interest in contributing to **libcproject**! 🎉
## Code of Conduct
**libcproject** adopted the [Contributor Covenant](https://www.contributor-covenant.org/) as its Code of Conduct, and we expect project participants to adhere to it. Please read [the full text](./CODE_OF_CONDUCT.md) so that you can understand what actions will and will not be tolerated.
## Open Development
All work on **libcproject** happens directly on this repository. Both core team members and external contributors send pull requests which go through the same review process.
## Types of contributions ## Types of contributions
- Reporting a bug. - Reporting a bug.
@ -11,7 +19,7 @@ Thanks a lot for your interest in contributing to **libcproject**! 🎉
## Pull Requests ## Pull Requests
- **Please first discuss** the change you wish to make via [issue](https://github.com/Divlo/libcproject/issues) before making a change. It might avoid a waste of your time. - **Please first discuss** the change you wish to make via [issue](https://github.com/theoludwig/libcproject/issues) before making a change. It might avoid a waste of your time.
- Ensure your code respect linting. - Ensure your code respect linting.
@ -21,26 +29,4 @@ If you're adding new features to **libcproject**, please include tests.
## Commits ## Commits
The commit message guidelines respect [@commitlint/config-conventional](https://github.com/conventional-changelog/commitlint/tree/master/%40commitlint/config-conventional) and [Semantic Versioning](https://semver.org/) for releases. The commit message guidelines adheres to [Conventional Commits](https://www.conventionalcommits.org/) and [Semantic Versioning](https://semver.org/) for releases.
### Types
Types define which kind of changes you made to the project.
| Types | Description |
| -------- | ------------------------------------------------------------------------------------------------------------ |
| feat | A new feature. |
| fix | A bug fix. |
| docs | Documentation only changes. |
| style | Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc). |
| refactor | A code change that neither fixes a bug nor adds a feature. |
| perf | A code change that improves performance. |
| test | Adding missing tests or correcting existing tests. |
| build | Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm). |
| ci | Changes to our CI configuration files and scripts (example scopes: Travis, Circle, BrowserStack, SauceLabs). |
| chore | Other changes that don't modify src or test files. |
| revert | Reverts a previous commit. |
### Scopes
Scopes define what part of the code changed.

View File

@ -1,6 +1,6 @@
DOXYFILE_ENCODING = UTF-8 DOXYFILE_ENCODING = UTF-8
PROJECT_NAME = libcproject PROJECT_NAME = libcproject
PROJECT_BRIEF = "C static library easier to use than $(libc) (C standard library)." PROJECT_BRIEF = "C static library easier to use than libc (C standard library)."
OUTPUT_DIRECTORY = documentation OUTPUT_DIRECTORY = documentation
OUTPUT_LANGUAGE = English OUTPUT_LANGUAGE = English
OPTIMIZE_OUTPUT_FOR_C = YES OPTIMIZE_OUTPUT_FOR_C = YES
@ -8,7 +8,10 @@ INPUT = ./
INPUT_ENCODING = UTF-8 INPUT_ENCODING = UTF-8
USE_MDFILE_AS_MAINPAGE = README.md USE_MDFILE_AS_MAINPAGE = README.md
FILE_PATTERNS = *.h \ FILE_PATTERNS = *.h \
README.md README.md \
CODE_OF_CONDUCT.md \
CONTRIBUTING.md \
LICENSE
HTML_EXTRA_STYLESHEET = doxygen-awesome-css/doxygen-awesome.css HTML_EXTRA_STYLESHEET = doxygen-awesome-css/doxygen-awesome.css
RECURSIVE = YES RECURSIVE = YES

View File

@ -1,6 +1,6 @@
MIT License MIT License
Copyright (c) Divlo Copyright (c) Théo LUDWIG
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

View File

@ -1,6 +1,7 @@
LIBRARY_NAME = libcproject LIBRARY_NAME = libcproject
CC = gcc CC = gcc
CC_FLAGS = -Wall -Wextra -Wfloat-equal -Wundef -Werror -std=c17 -pedantic -pedantic-errors -I./ CC_FLAGS = -Wall -Wextra -Wfloat-equal -Wundef -Werror -std=c17 -pedantic -pedantic-errors -O3 -I./
CC_SANITIZER_FLAGS = -fsanitize=address -fsanitize=undefined
LIB = ./build/${LIBRARY_NAME}.a LIB = ./build/${LIBRARY_NAME}.a
LIB_CC_FLAGS = -L. -l:${LIB} LIB_CC_FLAGS = -L. -l:${LIB}
LIB_SOURCES = $(wildcard lib/*.c) LIB_SOURCES = $(wildcard lib/*.c)
@ -8,18 +9,26 @@ LIB_OBJECTS = $(patsubst %.c, %.o, $(LIB_SOURCES))
TEST_SOURCES = $(wildcard test/*.c) TEST_SOURCES = $(wildcard test/*.c)
TEST_OBJECTS = $(patsubst %.c, %.o, $(TEST_SOURCES)) TEST_OBJECTS = $(patsubst %.c, %.o, $(TEST_SOURCES))
HEADER_FILES = $(wildcard lib/*.h) $(wildcard test/*.h) ./${LIBRARY_NAME}.h HEADER_FILES = $(wildcard lib/*.h) $(wildcard test/*.h) ./${LIBRARY_NAME}.h
MAIN_EXECUTABLE = bin/main.exe MAIN_EXECUTABLE = bin/main
SET_VERSION_EXECUTABLE = bin/set_version.exe SET_VERSION_EXECUTABLE = bin/set_version
TEST_EXECUTABLE = bin/test.exe TEST_EXECUTABLE = bin/test
build/%.o: %.c
mkdir --parents ./build/lib ./build/test
${CC} ${CC_FLAGS} -c $< -o $@
${LIB}: $(addprefix build/, ${LIB_OBJECTS}) ${LIB}: $(addprefix build/, ${LIB_OBJECTS})
rm --force ${LIB} rm --force ${LIB}
ar -rcs ${LIB} $(addprefix build/, ${LIB_OBJECTS}) ar -rcs ${LIB} $(addprefix build/, ${LIB_OBJECTS})
build/lib:
mkdir --parents ./build/lib
build/test:
mkdir --parents ./build/test
build/lib/%.o: lib/%.c ${HEADER_FILES} | build/lib
${CC} ${CC_FLAGS} -c $< -o $@
build/test/%.o: test/%.c ${HEADER_FILES} | build/test
${CC} ${CC_FLAGS} -c $< -o $@
.PHONY: run .PHONY: run
run: ${LIB} ./main.c run: ${LIB} ./main.c
mkdir --parents ./bin mkdir --parents ./bin
@ -34,8 +43,8 @@ set_version: ${LIB} ./set_version.c
.PHONY: test .PHONY: test
test: ${LIB} $(addprefix build/, ${TEST_OBJECTS}) test: ${LIB} $(addprefix build/, ${TEST_OBJECTS})
mkdir --parents ./bin mkdir --parents ./bin
${CC} ${CC_FLAGS} -o ${TEST_EXECUTABLE} $(addprefix build/, ${TEST_OBJECTS}) ${LIB_CC_FLAGS} ${CC} ${CC_FLAGS} ${CC_SANITIZER_FLAGS} -o ${TEST_EXECUTABLE} $(addprefix build/, ${TEST_OBJECTS}) ${LIB_CC_FLAGS}
./${TEST_EXECUTABLE} ./${TEST_EXECUTABLE} ${ARGS}
.PHONY: lint .PHONY: lint
lint: lint:

View File

@ -9,7 +9,7 @@
<a href="./LICENSE"><img src="https://img.shields.io/badge/licence-MIT-blue.svg" alt="Licence MIT"/></a> <a href="./LICENSE"><img src="https://img.shields.io/badge/licence-MIT-blue.svg" alt="Licence MIT"/></a>
<a href="./CODE_OF_CONDUCT.md"><img src="https://img.shields.io/badge/Contributor%20Covenant-v2.0%20adopted-ff69b4.svg" alt="Contributor Covenant" /></a> <a href="./CODE_OF_CONDUCT.md"><img src="https://img.shields.io/badge/Contributor%20Covenant-v2.0%20adopted-ff69b4.svg" alt="Contributor Covenant" /></a>
<br /> <br />
<a href="https://github.com/Divlo/libcproject/actions/workflows/ci.yml"><img src="https://github.com/Divlo/libcproject/actions/workflows/ci.yml/badge.svg?branch=develop" /></a> <a href="https://github.com/theoludwig/libcproject/actions/workflows/ci.yml"><img src="https://github.com/theoludwig/libcproject/actions/workflows/ci.yml/badge.svg?branch=develop" /></a>
<a href="https://conventionalcommits.org"><img src="https://img.shields.io/badge/Conventional%20Commits-1.0.0-yellow.svg" alt="Conventional Commits" /></a> <a href="https://conventionalcommits.org"><img src="https://img.shields.io/badge/Conventional%20Commits-1.0.0-yellow.svg" alt="Conventional Commits" /></a>
<a href="https://github.com/semantic-release/semantic-release"><img src="https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg" alt="semantic-release" /></a> <a href="https://github.com/semantic-release/semantic-release"><img src="https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg" alt="semantic-release" /></a>
</p> </p>
@ -20,7 +20,7 @@
C is a low-level programming language and we often end up reinventing the wheel as the C standard library (`libc`) is quite small and in my humble opinion, not well designed. C is a low-level programming language and we often end up reinventing the wheel as the C standard library (`libc`) is quite small and in my humble opinion, not well designed.
**libcproject** solve this by providing common functions or data structures (`dictionary`, `linked_list`, `queue`, `stack`, etc.) we might need in our C projects. **libcproject** solve this by providing common functions or data structures (`hash_map`, `array_list`, `linked_list`, `queue`, `stack`, etc.) we might need in our C projects.
[Online documentation](https://libcproject.vercel.app/). [Online documentation](https://libcproject.vercel.app/).
@ -55,9 +55,16 @@ nm ./build/libcproject.a # to see the symbols
Steps to create a new C project that uses `libcproject`: Steps to create a new C project that uses `libcproject`:
### Step 1: Compile `libcproject` ### Step 1: Install and Compile `libcproject`
```sh ```sh
# Clone the repository
git clone git@github.com:theoludwig/libcproject.git
# Go to libcproject directory
cd libcproject
# Compile the library
make make
``` ```
@ -90,9 +97,9 @@ touch main.c
#include "libcproject/libcproject.h" #include "libcproject/libcproject.h"
int main() { int main() {
char* string = "Hello, world!"; string_t string_value = "Hello, world!"; // `string_t` is a typedef from `libcproject`
printf("%s\n", string); printf("%s\n", string_value);
printf("string_length = %ld\n", string_get_length(string)); // `string_get_length` is a function from `libcproject` printf("string_length = %ld\n", string_get_length(string_value)); // `string_get_length` is a function from `libcproject`
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
``` ```
@ -100,7 +107,7 @@ int main() {
### Step 5: Compile your project and link it with the library ### Step 5: Compile your project and link it with the library
```sh ```sh
gcc -o ./main.exe ./main.c -L. -l:./libcproject/build/libcproject.a gcc -o ./main ./main.c -L. -l:./libcproject/build/libcproject.a
``` ```
## 💡 Contributing ## 💡 Contributing

44
lib/array_list.c Normal file
View File

@ -0,0 +1,44 @@
#include "array_list.h"
struct array_list* array_list_initialization() {
struct array_list* list = malloc(sizeof(struct array_list));
list->data = malloc(sizeof(void*) * ARRAY_LIST_INITIAL_CAPACITY);
list->size = 0;
list->capacity = ARRAY_LIST_INITIAL_CAPACITY;
return list;
}
void array_list_add(struct array_list* list, void* element) {
if (list->size >= list->capacity) {
size_t previous_capacity = list->capacity;
list->capacity += ARRAY_LIST_INITIAL_CAPACITY;
list->data = realloc(list->data, sizeof(void*) * list->capacity);
for (size_t index = previous_capacity; index < list->capacity; index++) {
list->data[index] = NULL;
}
}
list->data[list->size] = element;
list->size++;
}
void array_list_remove(struct array_list* list, size_t index) {
if (index >= list->size) {
return;
}
for (size_t i = index + 1; i < list->size - 1; i++) {
list->data[i - 1] = list->data[i];
}
list->size--;
}
void* array_list_get(struct array_list* list, size_t index) {
if (index >= list->size) {
return NULL;
}
return list->data[index];
}
void array_list_free(struct array_list* list) {
free(list->data);
free(list);
}

51
lib/array_list.h Normal file
View File

@ -0,0 +1,51 @@
#ifndef __LIBCPROJECT_ARRAY_LIST__
#define __LIBCPROJECT_ARRAY_LIST__
#include <stdbool.h>
#include <stdlib.h>
#include "types.h"
#define ARRAY_LIST_INITIAL_CAPACITY 10
/**
* @brief A dynamic array implementation.
* @since v1.2.0
*/
struct array_list {
void** data;
size_t size;
size_t capacity;
};
/**
* @brief Initializes a new array list.
* @since v1.2.0
*/
struct array_list* array_list_initialization();
/**
* @brief Adds an element to the end of the array list.
* @since v1.2.0
*/
void array_list_add(struct array_list* list, void* element);
/**
* @brief Removes an element from the array list.
* @since v1.2.0
*/
void array_list_remove(struct array_list* list, size_t index);
/**
* @brief Gets an element from the array list.
* @since v1.2.0
*/
void* array_list_get(struct array_list* list, size_t index);
/**
* @brief Frees the array list.
* @since v3.0.0
*/
void array_list_free(struct array_list* list);
#endif

View File

@ -1,22 +1,17 @@
#include "character.h" #include "character.h"
#include <stdbool.h> void character_append(string_t string_value, const char character) {
#include <stdlib.h> size_t length = string_get_length(string_value);
character_append_at(string_value, character, length);
#include "string.h"
void character_append(char* string, const char character) {
size_t length = string_get_length(string);
character_append_at(string, character, length);
} }
void character_append_at(char* string, const char character, const size_t index) { void character_append_at(string_t string_value, const char character, const size_t index) {
size_t length = string_get_length(string); size_t length = string_get_length(string_value);
for (size_t index_string = length; index_string > index; index_string--) { for (size_t index_string = length; index_string > index; index_string--) {
string[index_string] = string[index_string - 1]; string_value[index_string] = string_value[index_string - 1];
} }
string[index] = character; string_value[index] = character;
string[length + 1] = '\0'; string_value[length + 1] = '\0';
} }
char character_to_upper(const char character) { char character_to_upper(const char character) {

View File

@ -1,32 +1,37 @@
#ifndef __CHARACTER__ #ifndef __LIBCPROJECT_CHARACTER__
#define __CHARACTER__ #define __LIBCPROJECT_CHARACTER__
#include <stdbool.h> #include <stdbool.h>
#include <stdlib.h> #include <stdlib.h>
#include "string.h"
#include "types.h"
/** /**
* @brief Append a character to a string, assuming string points to an array * @brief Append a character to a string, assuming string points to an array
* with enough space. * with enough space.
* *
* @param string * @param string_value
* @param character * @param character
* @since v1.0.0
*/ */
void character_append(char* string, char character); void character_append(string_t string_value, char character);
/** /**
* @brief Append a character to a string at a specific index, assuming string points to an array with enough space. * @brief Append a character to a string at a specific index, assuming string points to an array with enough space.
* *
* @param string * @param string_value
* @param character * @param character
* @param index * @param index
* @since v1.0.0
*/ */
void character_append_at(char* string, const char character, const size_t index); void character_append_at(string_t string_value, const char character, const size_t index);
/** /**
* @brief Converts the character to uppercase. * @brief Converts the character to uppercase.
* *
* @param character * @param character
* @return const char * @since v1.0.0
*/ */
char character_to_upper(const char character); char character_to_upper(const char character);
@ -34,16 +39,15 @@ char character_to_upper(const char character);
* @brief Converts the character to lowercase. * @brief Converts the character to lowercase.
* *
* @param character * @param character
* @return const char * @since v1.0.0
*/ */
char character_to_lower(const char character); char character_to_lower(const char character);
/** /**
* @brief Check if the character is a digit ('0', '1', '2', '3', '4', '5', '6', '7, '8' or '9'). * @brief Check if the character is a digit ('0', '1', '2', '3', '4', '5', '6', '7, '8' or '9').
* *
* @param string1
* @param string2
* @return true if the character is a digit, false otherwise * @return true if the character is a digit, false otherwise
* @since v1.0.0
*/ */
bool character_get_is_digit(const char character); bool character_get_is_digit(const char character);
@ -52,7 +56,7 @@ bool character_get_is_digit(const char character);
* Return 0 if the character is not a letter. * Return 0 if the character is not a letter.
* *
* @param character * @param character
* @return char * @since v1.0.0
*/ */
unsigned char character_get_alphabet_position(const char character); unsigned char character_get_alphabet_position(const char character);

View File

@ -1,19 +1,12 @@
#include "convert.h" #include "convert.h"
#include <stdio.h> string_t convert_character_to_string(const char character) {
#include <stdlib.h> string_t string = malloc(sizeof(char) * 2);
#include "character.h"
#include "mathematics.h"
#include "stdbool.h"
#include "string.h"
char* convert_character_to_string(const char character) {
char* string = malloc(sizeof(char*) * 2);
if (string == NULL) { if (string == NULL) {
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
character_append(string, character); string[0] = character;
string[1] = '\0';
return string; return string;
} }
@ -25,42 +18,50 @@ char convert_digit_to_character(const char digit) {
return digit + '0'; return digit + '0';
} }
long long convert_string_to_number(const char* string) { long long convert_string_to_number(const string_t string_value) {
bool is_negative = string[0] == '-'; bool is_negative = string_value[0] == '-';
long long integer = 0; long long integer = 0;
size_t length = string_get_length(string); size_t length = string_get_length(string_value);
for (size_t index = is_negative ? 1 : 0; index < length; index++) { for (size_t index = is_negative ? 1 : 0; index < length; index++) {
integer = integer * 10 + convert_character_to_digit(string[index]); integer = integer * 10 + convert_character_to_digit(string_value[index]);
} }
return is_negative ? integer * -1 : integer; return is_negative ? integer * -1 : integer;
} }
char* convert_number_to_string(const long long integer) { string_t convert_number_to_string(const long long integer) {
if (integer == 0) { if (integer == 0) {
return convert_character_to_string('0'); return convert_character_to_string('0');
} }
bool is_negative = integer < 0; bool is_negative = integer < 0;
size_t length = 1; size_t length = 1;
char* string = malloc(sizeof(char*) * length);
if (string == NULL) {
exit(EXIT_FAILURE);
}
long long current = mathematics_absolute_value(integer); long long current = mathematics_absolute_value(integer);
while (current != 0) { while (current != 0) {
character_append(string, convert_digit_to_character(current % 10));
current = current / 10; current = current / 10;
length++; length++;
string = realloc(string, sizeof(char*) * length);
} }
if (is_negative) { if (is_negative) {
character_append(string, '-');
length++; length++;
string = realloc(string, sizeof(char*) * length);
} }
return string_reverse(string); string_t string_value = malloc(sizeof(char) * length);
if (string_value == NULL) {
exit(EXIT_FAILURE);
}
current = mathematics_absolute_value(integer);
size_t index = 0;
while (current != 0) {
string_value[index++] = convert_digit_to_character(current % 10);
current = current / 10;
}
if (is_negative) {
string_value[index++] = '-';
}
string_value[index] = '\0';
char* result = string_reverse(string_value);
free(string_value);
return result;
} }
char* convert_number_from_base_10_to_base(unsigned long long number, unsigned int base) { string_t convert_number_from_base_10_to_base(unsigned long long number, unsigned int base) {
if (number == 0) { if (number == 0) {
return "0"; return "0";
} }
@ -71,7 +72,7 @@ char* convert_number_from_base_10_to_base(unsigned long long number, unsigned in
number = number / base; number = number / base;
index++; index++;
} }
char* result = malloc(sizeof(char) * (index + 1)); string_t result = malloc(sizeof(char) * (index + 1));
int index_result = 0; int index_result = 0;
for (int iteration = index - 1; iteration >= 0; iteration--) { for (int iteration = index - 1; iteration >= 0; iteration--) {
int remainder = remainders[iteration]; int remainder = remainders[iteration];
@ -82,10 +83,11 @@ char* convert_number_from_base_10_to_base(unsigned long long number, unsigned in
} }
index_result++; index_result++;
} }
result[index_result] = '\0';
return result; return result;
} }
int convert_number_from_base_to_base_10(char* number, unsigned int base) { int convert_number_from_base_to_base_10(string_t number, unsigned int base) {
int length = string_get_length(number); int length = string_get_length(number);
int exponent = length - 1; int exponent = length - 1;
int result = 0; int result = 0;
@ -104,6 +106,6 @@ int convert_number_from_base_to_base_10(char* number, unsigned int base) {
return result; return result;
} }
char* convert_number_from_base_to_another(char* number, int base_from, int base_target) { string_t convert_number_from_base_to_another(string_t number, int base_from, int base_target) {
return convert_number_from_base_10_to_base(convert_number_from_base_to_base_10(number, base_from), base_target); return convert_number_from_base_10_to_base(convert_number_from_base_to_base_10(number, base_from), base_target);
} }

View File

@ -1,20 +1,81 @@
#ifndef __CONVERT__ #ifndef __LIBCPROJECT_CONVERT__
#define __CONVERT__ #define __LIBCPROJECT_CONVERT__
char* convert_character_to_string(const char character); #include <stdio.h>
#include <stdlib.h>
#include "character.h"
#include "mathematics.h"
#include "stdbool.h"
#include "string.h"
#include "types.h"
/**
* @brief Convert a character to a string.
*
* @param character
* @since v1.0.0
*/
string_t convert_character_to_string(const char character);
/**
* @brief Convert a character to a digit.
*
* @param character
* @since v1.0.0
*/
char convert_character_to_digit(const char character); char convert_character_to_digit(const char character);
/**
* @brief Convert a digit to a character.
*
* @param digit
* @since v1.0.0
*/
char convert_digit_to_character(const char digit); char convert_digit_to_character(const char digit);
long long convert_string_to_number(const char* string); /**
* @brief Convert a string to a number.
*
* @param string_value
* @since v1.0.0
*/
long long convert_string_to_number(const string_t string_value);
char* convert_number_to_string(const long long integer); /**
* @brief Convert a number to a string.
*
* @param integer
* @since v1.0.0
*/
string_t convert_number_to_string(const long long integer);
char* convert_number_from_base_10_to_base(unsigned long long number, unsigned int base); /**
* @brief Convert a number (base 10) to a string with a specific base.
*
* @param number
* @param base
* @since v1.0.0
*/
string_t convert_number_from_base_10_to_base(unsigned long long number, unsigned int base);
int convert_number_from_base_to_base_10(char* number, unsigned int base); /**
* @brief Convert a number with a specific base to a number base 10.
*
* @param number
* @param base
* @since v1.0.0
*/
int convert_number_from_base_to_base_10(string_t number, unsigned int base);
char* convert_number_from_base_to_another(char* number, int base_from, int base_target); /**
* @brief Convert a number with a specific base to a number of specific base.
*
* @param number
* @param base_from
* @param base_target
* @since v1.0.0
*/
string_t convert_number_from_base_to_another(string_t number, int base_from, int base_target);
#endif #endif

View File

@ -1,68 +0,0 @@
#include "dictionary.h"
#include <stdlib.h>
#include "string.h"
struct dictionary *dictionary_initialization() {
struct dictionary *dictionary = malloc(sizeof(struct dictionary));
dictionary->items = malloc(sizeof(struct dictionary_item *) * DICTIONARY_INITIAL_CAPACITY);
dictionary->length = 0;
dictionary->capacity = DICTIONARY_INITIAL_CAPACITY;
for (size_t index = 0; index < dictionary->capacity; index++) {
dictionary->items[index] = NULL;
}
return dictionary;
}
void dictionary_add(struct dictionary *dictionary, char *key, void *data) {
if (dictionary->length == dictionary->capacity) {
size_t previous_capacity = dictionary->capacity;
dictionary->capacity += DICTIONARY_INITIAL_CAPACITY;
dictionary->items = realloc(dictionary->items, sizeof(struct dictionary_item *) * dictionary->capacity);
for (size_t index = previous_capacity; index < dictionary->capacity; index++) {
dictionary->items[index] = NULL;
}
}
struct dictionary_item *item = NULL;
for (size_t index = 0; index < dictionary->length && item == NULL; index++) {
if (string_equals(key, dictionary->items[index]->key)) {
item = dictionary->items[index];
}
}
if (item == NULL) {
item = malloc(sizeof(struct dictionary_item));
item->key = key;
item->data = data;
dictionary->items[dictionary->length] = item;
dictionary->length++;
} else {
item->data = data;
}
}
void dictionary_remove(struct dictionary *dictionary, char *key) {
bool found = false;
for (size_t index = 0; index < dictionary->length && !found; index++) {
if (string_equals(key, dictionary->items[index]->key)) {
free(dictionary->items[index]);
dictionary->items[index] = dictionary->items[dictionary->length - 1];
dictionary->length--;
found = true;
}
}
}
struct dictionary_item *dictionary_get(struct dictionary *dictionary, char *key) {
for (size_t index = 0; index < dictionary->length; index++) {
struct dictionary_item *item = dictionary->items[index];
if (string_equals(key, item->key)) {
return item;
}
}
return NULL;
}
bool dictionary_contains_key(struct dictionary *dictionary, char *key) {
return dictionary_get(dictionary, key) != NULL;
}

View File

@ -1,34 +0,0 @@
#ifndef __DICTIONARY__
#define __DICTIONARY__
#include <stdbool.h>
#include <stdlib.h>
#include "linked_list.h"
#define DICTIONARY_INITIAL_CAPACITY 10
// Dictionary implementation with O(n) lookup complexity.
struct dictionary {
struct dictionary_item **items;
size_t length;
size_t capacity;
};
struct dictionary_item {
void *data;
char *key;
};
struct dictionary *dictionary_initialization();
void dictionary_add(struct dictionary *dictionary, char *key, void *data);
void dictionary_remove(struct dictionary *dictionary, char *key);
struct dictionary_item *dictionary_get(struct dictionary *dictionary, char *key);
bool dictionary_contains_key(struct dictionary *dictionary, char *key);
#endif

View File

@ -1,17 +1,6 @@
#include "filesystem.h" #include "filesystem.h"
#include <dirent.h> int filesystem_read(string_t path, byte_t **file_content, off_t *file_size) {
#include <errno.h>
#include <fcntl.h>
#include <pwd.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "string.h"
int filesystem_read(char *path, char **file_content, off_t *file_size) {
int file_descriptor = open(path, O_RDONLY); int file_descriptor = open(path, O_RDONLY);
if (file_descriptor == -1) { if (file_descriptor == -1) {
return -1; return -1;
@ -19,22 +8,26 @@ int filesystem_read(char *path, char **file_content, off_t *file_size) {
(*file_size) = lseek(file_descriptor, 0, SEEK_END); (*file_size) = lseek(file_descriptor, 0, SEEK_END);
lseek(file_descriptor, 0, SEEK_SET); lseek(file_descriptor, 0, SEEK_SET);
(*file_content) = malloc(*file_size); (*file_content) = malloc(*file_size);
read(file_descriptor, *file_content, *file_size); if (read(file_descriptor, *file_content, *file_size) == -1) {
return -1;
}
close(file_descriptor); close(file_descriptor);
return 0; return 0;
} }
int filesystem_write(char *path, char *file_content, off_t file_size) { int filesystem_write(string_t path, byte_t *file_content, off_t file_size) {
int file_descriptor = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644); int file_descriptor = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (file_descriptor == -1) { if (file_descriptor == -1) {
return -1; return -1;
} }
write(file_descriptor, file_content, file_size); if (write(file_descriptor, file_content, file_size) == -1) {
return -1;
}
close(file_descriptor); close(file_descriptor);
return 0; return 0;
} }
char *filesystem_get_mimetype(char *path) { string_t filesystem_get_mimetype(string_t path) {
if (string_ends_with(path, ".html")) { if (string_ends_with(path, ".html")) {
return "text/html"; return "text/html";
} }
@ -53,5 +46,44 @@ char *filesystem_get_mimetype(char *path) {
if (string_ends_with(path, ".gif")) { if (string_ends_with(path, ".gif")) {
return "image/gif"; return "image/gif";
} }
if (string_ends_with(path, ".ico")) {
return "image/x-icon";
}
if (string_ends_with(path, ".svg")) {
return "image/svg+xml";
}
if (string_ends_with(path, ".json")) {
return "application/json";
}
if (string_ends_with(path, ".pdf")) {
return "application/pdf";
}
if (string_ends_with(path, ".xml")) {
return "application/xml";
}
if (string_ends_with(path, ".csv")) {
return "text/csv";
}
if (string_ends_with(path, ".zip")) {
return "application/zip";
}
if (string_ends_with(path, ".tar")) {
return "application/x-tar";
}
if (string_ends_with(path, ".gz")) {
return "application/x-gzip";
}
if (string_ends_with(path, ".mp3")) {
return "audio/mpeg";
}
if (string_ends_with(path, ".wav")) {
return "audio/wav";
}
if (string_ends_with(path, ".mp4")) {
return "video/mp4";
}
if (string_ends_with(path, ".bin")) {
return "application/octet-stream";
}
return "text/plain"; return "text/plain";
} }

View File

@ -1,7 +1,17 @@
#ifndef __FILESYSTEM__ #ifndef __LIBCPROJECT_FILESYSTEM__
#define __FILESYSTEM__ #define __LIBCPROJECT_FILESYSTEM__
#include <dirent.h>
#include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <pwd.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "string.h"
#include "types.h"
/** /**
* @brief Read the content of a file. * @brief Read the content of a file.
@ -9,11 +19,11 @@
* @param path * @param path
* @param file_content * @param file_content
* @param file_size * @param file_size
* @return int * @retval -1 if the file does not exist or if there is an error.
* @retval -1 if the file does not exist * @retval 0 for success.
* @retval 0 for success * @since v1.0.0
*/ */
int filesystem_read(char *path, char **file_content, off_t *file_size); int filesystem_read(string_t path, byte_t **file_content, off_t *file_size);
/** /**
* @brief Write the content to a file. * @brief Write the content to a file.
@ -21,18 +31,18 @@ int filesystem_read(char *path, char **file_content, off_t *file_size);
* @param path * @param path
* @param file_content * @param file_content
* @param file_size * @param file_size
* @return int * @retval -1 if there is an error.
* @retval -1 if errors * @retval 0 for success.
* @retval 0 for success * @since v1.0.0
*/ */
int filesystem_write(char *path, char *file_content, off_t file_size); int filesystem_write(string_t path, byte_t *file_content, off_t file_size);
/** /**
* @brief Get the mimetype of a file. * @brief Get the mimetype of a file.
* *
* @param path * @param path
* @return char* * @since v1.0.0
*/ */
char *filesystem_get_mimetype(char *path); string_t filesystem_get_mimetype(string_t path);
#endif #endif

244
lib/hash_map.c Normal file
View File

@ -0,0 +1,244 @@
#include "hash_map.h"
#define ROTATE_LEFT(x, b) (((x) << (b)) | ((x) >> (64 - (b))))
uint64_t sip_round(uint64_t v0, uint64_t v1, uint64_t v2, uint64_t v3) {
v0 += v1;
v2 += v3;
v1 = ROTATE_LEFT(v1, 13);
v3 = ROTATE_LEFT(v3, 16);
v1 ^= v0;
v3 ^= v2;
v0 = ROTATE_LEFT(v0, 32);
v2 += v1;
v0 += v3;
v1 = ROTATE_LEFT(v1, 17);
v3 = ROTATE_LEFT(v3, 21);
v1 ^= v2;
v3 ^= v0;
v2 = ROTATE_LEFT(v2, 32);
return v0;
}
uint64_t hash(string_t key, size_t capacity) {
size_t key_length = string_get_length(key);
const uint64_t c = 0x736f6d6570736575;
uint64_t v0 = c ^ 0x736f6d6570736575;
uint64_t v1 = c ^ 0x646f72616e646f6d;
uint64_t v2 = c ^ 0x6c7967656e657261;
uint64_t v3 = c ^ 0x7465646279746573;
uint64_t m;
uint64_t hash;
uint8_t *message = (uint8_t *)key;
size_t remaining = key_length;
size_t offset = 0;
while (remaining >= 8) {
memcpy(&m, message + offset, sizeof(uint64_t));
v3 ^= m;
for (int i = 0; i < 2; i++) {
v0 = sip_round(v0, v1, v2, v3);
v1 = ROTATE_LEFT(v1, 13);
v2 = ROTATE_LEFT(v2, 16);
v3 = ROTATE_LEFT(v3, 32);
v0 ^= m;
}
v2 ^= 0xff;
for (int i = 0; i < 4; i++) {
v0 = sip_round(v0, v1, v2, v3);
v1 = ROTATE_LEFT(v1, 13);
v2 = ROTATE_LEFT(v2, 16);
v3 = ROTATE_LEFT(v3, 32);
}
hash = v0 ^ v1 ^ v2 ^ v3;
remaining -= sizeof(uint64_t);
offset += sizeof(uint64_t);
}
m = (uint64_t)remaining << 56;
switch (remaining) {
case 7:
m |= (uint64_t)message[offset + 6] << 48;
break;
case 6:
m |= (uint64_t)message[offset + 5] << 40;
break;
case 5:
m |= (uint64_t)message[offset + 4] << 32;
break;
case 4:
m |= (uint64_t)message[offset + 3] << 24;
break;
case 3:
m |= (uint64_t)message[offset + 2] << 16;
break;
case 2:
m |= (uint64_t)message[offset + 1] << 8;
break;
case 1:
m |= (uint64_t)message[offset];
break;
default:
break;
}
v3 ^= m;
for (int i = 0; i < 2; i++) {
v0 = sip_round(v0, v1, v2, v3);
v1 = ROTATE_LEFT(v1, 13);
v2 = ROTATE_LEFT(v2, 16);
v3 = ROTATE_LEFT(v3, 32);
}
v0 ^= m;
v2 ^= 0xff;
for (int i = 0; i < 4; i++) {
v0 = sip_round(v0, v1, v2, v3);
v1 = ROTATE_LEFT(v1, 13);
v2 = ROTATE_LEFT(v2, 16);
v3 = ROTATE_LEFT(v3, 32);
}
hash = v0 ^ v1 ^ v2 ^ v3;
return hash % capacity;
}
struct hash_map *hash_map_initialization() {
struct hash_map *hash_map = malloc(sizeof(struct hash_map));
hash_map->items = malloc(sizeof(struct linked_list *) * HASH_MAP_INITIAL_CAPACITY);
hash_map->length = 0;
hash_map->capacity = HASH_MAP_INITIAL_CAPACITY;
for (size_t index = 0; index < hash_map->capacity; index++) {
hash_map->items[index] = NULL;
}
return hash_map;
}
void hash_map_add(struct hash_map *hash_map, string_t key_value, void *data) {
if (hash_map->length == hash_map->capacity) {
size_t previous_capacity = hash_map->capacity;
hash_map->capacity += HASH_MAP_INITIAL_CAPACITY;
hash_map->items = realloc(hash_map->items, sizeof(struct linked_list *) * hash_map->capacity);
for (size_t index = previous_capacity; index < hash_map->capacity; index++) {
hash_map->items[index] = NULL;
}
}
string_t key = string_copy(key_value);
uint64_t hash_value = hash(key, hash_map->capacity);
struct linked_list *list = hash_map->items[hash_value];
struct hash_map_item *item = malloc(sizeof(struct hash_map_item));
item->key = key;
item->data = data;
if (list == NULL) {
list = linked_list_initialization();
hash_map->items[hash_value] = list;
linked_list_add_in_head(list, (void *)item);
hash_map->length++;
} else {
struct linked_list_node *node = list->head;
bool found = false;
while (node != NULL && !found) {
struct hash_map_item *item = (struct hash_map_item *)node->data;
if (string_equals(key, item->key)) {
item->data = data;
found = true;
}
node = node->next;
}
if (!found) {
linked_list_add_in_head(list, (void *)item);
hash_map->length++;
} else {
free(key);
free(item);
}
}
}
void hash_map_remove(struct hash_map *hash_map, string_t key) {
uint64_t hash_value = hash(key, hash_map->capacity);
struct linked_list *list = hash_map->items[hash_value];
if (list == NULL) {
return;
}
struct linked_list *new_list = linked_list_initialization();
struct linked_list_node *node = list->head;
while (node != NULL) {
struct hash_map_item *item = (struct hash_map_item *)node->data;
if (!string_equals(key, item->key)) {
linked_list_add_in_head(new_list, item);
} else {
free(item->key);
free(item);
}
node = node->next;
}
linked_list_free(list);
hash_map->items[hash_value] = new_list;
hash_map->length--;
}
void *hash_map_get(struct hash_map *hash_map, string_t key) {
uint64_t hash_value = hash(key, hash_map->capacity);
struct linked_list *list = hash_map->items[hash_value];
if (list == NULL) {
return NULL;
}
struct linked_list_node *node = list->head;
while (node != NULL) {
struct hash_map_item *item = (struct hash_map_item *)node->data;
if (string_equals(key, item->key)) {
return item->data;
}
node = node->next;
}
return NULL;
}
bool hash_map_contains_key(struct hash_map *hash_map, string_t key) {
return hash_map_get(hash_map, key) != NULL;
}
string_t *hash_map_get_keys(struct hash_map *hash_map) {
string_t *keys = malloc(sizeof(string_t) * hash_map->length);
size_t index = 0;
for (size_t hash_value = 0; hash_value < hash_map->capacity; hash_value++) {
struct linked_list *list = hash_map->items[hash_value];
if (list != NULL) {
struct linked_list_node *node = list->head;
while (node != NULL) {
struct hash_map_item *item = (struct hash_map_item *)node->data;
keys[index++] = item->key;
node = node->next;
}
}
}
return keys;
}
void hash_map_free(struct hash_map *hash_map) {
for (size_t index = 0; index < hash_map->capacity; index++) {
struct linked_list *list = hash_map->items[index];
if (list != NULL) {
struct linked_list_node *node = list->head;
while (node != NULL) {
struct hash_map_item *item = (struct hash_map_item *)node->data;
free(item->key);
free(item);
node = node->next;
}
linked_list_free(list);
}
}
free(hash_map->items);
free(hash_map);
}

98
lib/hash_map.h Normal file
View File

@ -0,0 +1,98 @@
#ifndef __LIBCPROJECT_HASH_MAP__
#define __LIBCPROJECT_HASH_MAP__
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "linked_list.h"
#include "string.h"
#include "types.h"
#define HASH_MAP_INITIAL_CAPACITY 10
/**
* @brief Hash map data structure.
* @since v2.0.0
*/
struct hash_map {
struct linked_list **items;
size_t length;
size_t capacity;
};
/**
* @brief Hash map item data structure.
* @since v2.0.0
*/
struct hash_map_item {
void *data;
string_t key;
};
/**
* @brief Hash function (using SipHash 1-3 algorithm).
* @param key
* @param capacity
* @see https://en.wikipedia.org/wiki/SipHash
* @see https://github.com/veorq/SipHash
* @since v2.0.0
*/
uint64_t hash(string_t key, size_t capacity);
/**
* @brief Hash map initialization.
* @since v2.0.0
*/
struct hash_map *hash_map_initialization();
/**
* @brief Add an item to the hash map.
* @param hash_map
* @param key
* @param data
* @since v2.0.0
*/
void hash_map_add(struct hash_map *hash_map, string_t key, void *data);
/**
* @brief Remove an item from the hash map.
* @param hash_map
* @param key
* @since v2.0.0
*/
void hash_map_remove(struct hash_map *hash_map, string_t key);
/**
* @brief Get an item from the hash map.
* @param hash_map
* @param key
* @since v2.0.0
*/
void *hash_map_get(struct hash_map *hash_map, string_t key);
/**
* @brief Check if the hash map contains a key.
* @param hash_map
* @param key
* @since v2.0.0
*/
bool hash_map_contains_key(struct hash_map *hash_map, string_t key);
/**
* @brief Get the hash map keys.
*
* @param hash_map
* @since v2.0.0
*/
string_t *hash_map_get_keys(struct hash_map *hash_map);
/**
* @brief Frees the hash map.
* @since v3.0.0
*/
void hash_map_free(struct hash_map *hash_map);
#endif

View File

@ -1,10 +1,5 @@
#include "linked_list.h" #include "linked_list.h"
#include <stdbool.h>
#include <stdlib.h>
#include "stack.h"
struct linked_list *linked_list_initialization() { struct linked_list *linked_list_initialization() {
struct linked_list *list = malloc(sizeof(*list)); struct linked_list *list = malloc(sizeof(*list));
if (list == NULL) { if (list == NULL) {
@ -73,6 +68,7 @@ struct linked_list *linked_list_reverse(struct linked_list *list) {
linked_list_add_after_last(linked_list_reversed, stack_node_current->data); linked_list_add_after_last(linked_list_reversed, stack_node_current->data);
stack_node_current = stack_node_current->next; stack_node_current = stack_node_current->next;
} }
stack_free(stack);
return linked_list_reversed; return linked_list_reversed;
} }
@ -89,3 +85,14 @@ void linked_list_reverse_mutate(struct linked_list *list) {
(*current) = temporary_current; (*current) = temporary_current;
} }
} }
void linked_list_free(struct linked_list *list) {
struct linked_list_node *node_current = list->head;
while (node_current != NULL) {
struct linked_list_node *node_to_remove = node_current;
node_current = node_current->next;
free(node_to_remove);
}
list->head = NULL;
free(list);
}

View File

@ -1,30 +1,71 @@
#ifndef __LINKED_LIST__ #ifndef __LIBCPROJECT_LINKED_LIST__
#define __LINKED_LIST__ #define __LIBCPROJECT_LINKED_LIST__
#include <stdbool.h>
#include <stdlib.h> #include <stdlib.h>
#include "stack.h"
#include "types.h"
/**
* @brief Linked list data structure.
* @since v1.0.0
*/
struct linked_list { struct linked_list {
// first node of the list
struct linked_list_node *head; struct linked_list_node *head;
size_t length; size_t length;
}; };
/**
* @brief Linked list node data structure.
* @since v1.0.0
*/
struct linked_list_node { struct linked_list_node {
void *data; void *data;
struct linked_list_node *next; struct linked_list_node *next;
}; };
/**
* @brief Linked list initialization.
* @since v1.0.0
*/
struct linked_list *linked_list_initialization(); struct linked_list *linked_list_initialization();
/**
* @brief Add a new node in the head of the linked list.
* @since v1.0.0
*/
struct linked_list_node *linked_list_add_in_head(struct linked_list *list, void *new_value); struct linked_list_node *linked_list_add_in_head(struct linked_list *list, void *new_value);
/**
* @brief Delete node in the head of the linked list.
* @since v1.0.0
*/
void linked_list_delete_in_head(struct linked_list *list); void linked_list_delete_in_head(struct linked_list *list);
/**
* @brief Add a new node in the tail of the linked list.
* @since v1.0.0
*/
struct linked_list_node *linked_list_add_after_last(struct linked_list *list, void *new_data); struct linked_list_node *linked_list_add_after_last(struct linked_list *list, void *new_data);
/**
* @brief Reverse the linked list by creating a new one.
* @since v1.0.0
*/
struct linked_list *linked_list_reverse(struct linked_list *list); struct linked_list *linked_list_reverse(struct linked_list *list);
/**
* @brief Reverse the linked list by mutating it.
* @since v1.0.0
*/
void linked_list_reverse_mutate(struct linked_list *list); void linked_list_reverse_mutate(struct linked_list *list);
/**
* @brief Frees the linked list.
* @since v3.0.0
*/
void linked_list_free(struct linked_list *list);
#endif #endif

View File

@ -1,7 +1,5 @@
#include "mathematics.h" #include "mathematics.h"
#include <stdbool.h>
bool mathematics_equals(const float number1, const float number2) { bool mathematics_equals(const float number1, const float number2) {
return (number1 - number2) < MATHEMATICS_FLOAT_PRECISION; return (number1 - number2) < MATHEMATICS_FLOAT_PRECISION;
} }

View File

@ -1,14 +1,36 @@
#ifndef __MATHEMATICS__ #ifndef __LIBCPROJECT_MATHEMATICS__
#define __MATHEMATICS__ #define __LIBCPROJECT_MATHEMATICS__
#define MATHEMATICS_FLOAT_PRECISION 0.00000001 #define MATHEMATICS_FLOAT_PRECISION 0.00000001
#include <stdbool.h> #include <stdbool.h>
#include "types.h"
/**
* @brief Verify that 2 numbers are equal.
*
* @param number1
* @param number2
* @since v1.0.0
*/
bool mathematics_equals(const float number1, const float number2); bool mathematics_equals(const float number1, const float number2);
/**
* @brief Get the absolute value of a number.
*
* @param number
* @since v1.0.0
*/
unsigned long long mathematics_absolute_value(const long long number); unsigned long long mathematics_absolute_value(const long long number);
/**
* @brief Calculates the power of a number.
*
* @param base
* @param exponent
* @since v1.0.0
*/
unsigned long long mathematics_pow(unsigned long long base, unsigned long long exponent); unsigned long long mathematics_pow(unsigned long long base, unsigned long long exponent);
/** /**
@ -16,12 +38,24 @@ unsigned long long mathematics_pow(unsigned long long base, unsigned long long e
* *
* @param number * @param number
* @param nth_root * @param nth_root
* @return float * @since v1.0.0
*/ */
float mathematics_root(float number, unsigned int nth_root); float mathematics_root(float number, unsigned int nth_root);
/**
* @brief Calculates the square root of a number using Heron's method.
*
* @param number
* @since v1.0.0
*/
float mathematics_square_root(float number); float mathematics_square_root(float number);
/**
* @brief Calculates the factorial of a number.
*
* @param number
* @since v1.0.0
*/
unsigned long long mathematics_factorial(unsigned long long number); unsigned long long mathematics_factorial(unsigned long long number);
#endif #endif

View File

@ -1,8 +1,5 @@
#include "queue.h" #include "queue.h"
#include <stdio.h>
#include <stdlib.h>
struct queue *queue_initialization() { struct queue *queue_initialization() {
struct queue *queue = malloc(sizeof(*queue)); struct queue *queue = malloc(sizeof(*queue));
if (queue == NULL) { if (queue == NULL) {
@ -46,3 +43,16 @@ void *queue_pop(struct queue *queue) {
queue->length = queue->length - 1; queue->length = queue->length - 1;
return data; return data;
} }
void queue_free(struct queue *queue) {
if (queue == NULL) {
exit(EXIT_FAILURE);
}
struct queue_node *node = queue->first;
while (node != NULL) {
struct queue_node *node_next = node->next;
free(node);
node = node_next;
}
free(queue);
}

View File

@ -1,23 +1,51 @@
#ifndef __QUEUE__ #ifndef __LIBCPROJECT_QUEUE__
#define __QUEUE__ #define __LIBCPROJECT_QUEUE__
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
// FIFO = First In First Out #include "types.h"
/**
* @brief Queue structure => FIFO (First In First Out).
* @since v1.0.0
*/
struct queue { struct queue {
struct queue_node *first; struct queue_node *first;
size_t length; size_t length;
}; };
/**
* @brief Queue node structure.
* @since v1.0.0
*/
struct queue_node { struct queue_node {
void *data; void *data;
struct queue_node *next; struct queue_node *next;
}; };
/**
* @brief Queue initialization.
* @since v1.0.0
*/
struct queue *queue_initialization(); struct queue *queue_initialization();
/**
* @brief Push data to queue.
* @since v1.0.0
*/
void queue_push(struct queue *queue, void *data); void queue_push(struct queue *queue, void *data);
/**
* @brief Pop data from queue.
* @since v1.0.0
*/
void *queue_pop(struct queue *queue); void *queue_pop(struct queue *queue);
/**
* @brief Frees the queue.
* @since v3.0.0
*/
void queue_free(struct queue *queue);
#endif #endif

View File

@ -1,8 +1,5 @@
#include "stack.h" #include "stack.h"
#include <stdio.h>
#include <stdlib.h>
struct stack *stack_initialization() { struct stack *stack_initialization() {
struct stack *stack = malloc(sizeof(*stack)); struct stack *stack = malloc(sizeof(*stack));
if (stack == NULL) { if (stack == NULL) {
@ -38,3 +35,16 @@ void *stack_pop(struct stack *stack) {
stack->length = stack->length - 1; stack->length = stack->length - 1;
return data; return data;
} }
void stack_free(struct stack *stack) {
if (stack == NULL) {
exit(EXIT_FAILURE);
}
struct stack_node *node = stack->first;
while (node != NULL) {
struct stack_node *node_next = node->next;
free(node);
node = node_next;
}
free(stack);
}

View File

@ -1,23 +1,51 @@
#ifndef __STACK__ #ifndef __LIBCPROJECT_STACK__
#define __STACK__ #define __LIBCPROJECT_STACK__
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
// LIFO = Last In First Out #include "types.h"
/**
* @brief Stack structure => LIFO (Last In First Out).
* @since v1.0.0
*/
struct stack { struct stack {
struct stack_node *first; struct stack_node *first;
size_t length; size_t length;
}; };
/**
* @brief Stack node structure.
* @since v1.0.0
*/
struct stack_node { struct stack_node {
void *data; void *data;
struct stack_node *next; struct stack_node *next;
}; };
/**
* @brief Stack initialization.
* @since v1.0.0
*/
struct stack *stack_initialization(); struct stack *stack_initialization();
/**
* @brief Push data to stack.
* @since v1.0.0
*/
void stack_push(struct stack *stack, void *data); void stack_push(struct stack *stack, void *data);
/**
* @brief Pop data from stack.
* @since v1.0.0
*/
void *stack_pop(struct stack *stack); void *stack_pop(struct stack *stack);
/**
* @brief Frees the stack.
* @since v3.0.0
*/
void stack_free(struct stack *stack);
#endif #endif

View File

@ -1,126 +1,135 @@
#include "string.h" #include "string.h"
#include <stdbool.h> size_t string_get_length(const string_t string_value) {
#include <stdio.h>
#include <stdlib.h>
#include "character.h"
#include "convert.h"
#include "dictionary.h"
size_t string_get_length(const char* string) {
size_t length = 0; size_t length = 0;
while (string[length] != '\0') { while (string_value[length] != '\0') {
length++; length++;
} }
return length; return length;
} }
char* string_to_uppercase(char* string) { string_t string_to_uppercase(string_t string_value) {
size_t string_length = string_get_length(string); size_t string_length = string_get_length(string_value);
char* result = malloc(sizeof(char*) * string_length); string_t result = malloc(sizeof(char) * (string_length + 1));
if (result == NULL) { if (result == NULL) {
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
for (size_t index = 0; index < string_length; index++) { for (size_t index = 0; index < string_length; index++) {
character_append(result, character_to_upper(string[index])); result[index] = character_to_upper(string_value[index]);
} }
result[string_length] = '\0';
return result; return result;
} }
char* string_to_lowercase(char* string) { string_t string_to_lowercase(string_t string_value) {
size_t string_length = string_get_length(string); size_t string_length = string_get_length(string_value);
char* result = malloc(sizeof(char*) * string_length); string_t result = malloc(sizeof(char) * (string_length + 1));
if (result == NULL) { if (result == NULL) {
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
for (size_t index = 0; index < string_length; index++) { for (size_t index = 0; index < string_length; index++) {
character_append(result, character_to_lower(string[index])); result[index] = character_to_lower(string_value[index]);
} }
result[string_length] = '\0';
return result; return result;
} }
char* string_replace(char* string, char search, char replace) { string_t string_replace(string_t string_value, char search, char replace) {
size_t string_length = string_get_length(string); size_t string_length = string_get_length(string_value);
char* result = malloc(sizeof(char*) * string_length); string_t result = malloc(sizeof(char) * (string_length + 1));
if (result == NULL) { if (result == NULL) {
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
for (size_t index = 0; index < string_length; index++) { for (size_t index = 0; index < string_length; index++) {
bool is_search_value = search == string[index]; bool is_search_value = search == string_value[index];
if (is_search_value) { if (is_search_value) {
character_append(result, replace); result[index] = replace;
} else { } else {
character_append(result, string[index]); result[index] = string_value[index];
} }
} }
result[string_length] = '\0';
return result; return result;
} }
char* string_trim_start(char* string) { string_t string_trim_start(string_t string_value, char character) {
size_t string_length = string_get_length(string); size_t string_length = string_get_length(string_value);
char* result = malloc(sizeof(char*) * string_length); string_t result = malloc(sizeof(char) * (string_length + 1));
if (result == NULL) { if (result == NULL) {
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
size_t index_space = 0; size_t index_space = 0;
while (string[index_space] == ' ') { while (string_value[index_space] == character) {
index_space++; index_space++;
} }
for (size_t index = index_space; index < string_length; index++) { for (size_t index = index_space; index < string_length; index++) {
character_append(result, string[index]); result[index - index_space] = string_value[index];
} }
result[string_length - index_space] = '\0';
return result; return result;
} }
char* string_trim_end(char* string) { string_t string_trim_end(string_t string_value, char character) {
size_t string_length = string_get_length(string); size_t string_length = string_get_length(string_value);
char* result = malloc(sizeof(char*) * string_length); string_t result = malloc(sizeof(char) * (string_length + 1));
if (result == NULL) { if (result == NULL) {
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
size_t index_space = string_length - 1; size_t index_space = string_length - 1;
while (string[index_space] == ' ') { while (string_value[index_space] == character) {
index_space--; index_space--;
} }
for (size_t index = 0; index < index_space + 1; index++) { for (size_t index = 0; index < index_space + 1; index++) {
character_append(result, string[index]); result[index] = string_value[index];
} }
result[index_space + 1] = '\0';
return result; return result;
} }
char* string_trim(char* string) { string_t string_trim(string_t string_value, char character) {
char* result = string_trim_start(string); string_t result_start = string_trim_start(string_value, character);
result = string_trim_end(result); string_t result = string_trim_end(result_start, character);
free(result_start);
return result; return result;
} }
char* string_copy(const char* string) { string_t string_copy(const string_t source) {
return string_substring(string, 0, string_get_length(string)); size_t source_length = string_get_length(source);
string_t copy = malloc(sizeof(char) * (source_length + 1));
if (copy == NULL) {
exit(EXIT_FAILURE);
}
size_t index;
for (index = 0; index < source_length; index++) {
copy[index] = source[index];
}
copy[index] = '\0';
return copy;
} }
char* string_capitalize(char* string) { string_t string_capitalize(string_t string_value) {
size_t string_length = string_get_length(string); size_t string_length = string_get_length(string_value);
char* result = malloc(sizeof(char*) * string_length); string_t result = malloc(sizeof(char) * (string_length + 1));
if (result == NULL) { if (result == NULL) {
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
for (size_t index = 0; index < string_length; index++) { for (size_t index = 0; index < string_length; index++) {
bool is_first_character = index == 0; bool is_first_character = index == 0;
if (is_first_character) { if (is_first_character) {
character_append(result, character_to_upper(string[index])); result[index] = character_to_upper(string_value[index]);
} else { } else {
character_append(result, string[index]); result[index] = string_value[index];
} }
} }
result[string_length] = '\0';
return result; return result;
} }
size_t string_total_occurrences_of_character(char* string, char character) { size_t string_total_occurrences_of_character(string_t string_value, char character) {
size_t result = 0; size_t result = 0;
size_t string_length = string_get_length(string); size_t string_length = string_get_length(string_value);
for (size_t index = 0; index < string_length; index++) { for (size_t index = 0; index < string_length; index++) {
char current_character = string[index]; char current_character = string_value[index];
if (current_character == character) { if (current_character == character) {
result += 1; result += 1;
} }
@ -128,21 +137,24 @@ size_t string_total_occurrences_of_character(char* string, char character) {
return result; return result;
} }
char* string_reverse(const char* string) { string_t string_reverse(const string_t string_value) {
size_t string_length = string_get_length(string); size_t string_length = string_get_length(string_value);
size_t index = 0; size_t index = 0;
char* result = malloc(sizeof(char*) * string_length); string_t result = malloc(sizeof(char) * (string_length + 1));
if (result == NULL) { if (result == NULL) {
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
size_t result_index = 0;
for (index = string_length - 1; index > 0; index--) { for (index = string_length - 1; index > 0; index--) {
character_append(result, string[index]); result[result_index] = string_value[index];
result_index++;
} }
character_append(result, string[index]); result[result_index] = string_value[index];
result[string_length] = '\0';
return result; return result;
} }
bool string_equals(const char* string1, const char* string2) { bool string_equals(const string_t string1, const string_t string2) {
size_t string1_length = string_get_length(string1); size_t string1_length = string_get_length(string1);
size_t string2_length = string_get_length(string2); size_t string2_length = string_get_length(string2);
bool is_equal = string1_length == string2_length; bool is_equal = string1_length == string2_length;
@ -154,11 +166,11 @@ bool string_equals(const char* string1, const char* string2) {
return is_equal; return is_equal;
} }
bool string_get_is_integer(const char* string) { bool string_get_is_integer(const string_t string_value) {
size_t index = 0; size_t index = 0;
size_t string_length = string_get_length(string); size_t string_length = string_get_length(string_value);
bool is_integer = string_length >= 1; bool is_integer = string_length >= 1;
if (is_integer && string[0] == '-') { if (is_integer && string_value[0] == '-') {
if (string_length == 1) { if (string_length == 1) {
is_integer = false; is_integer = false;
} else { } else {
@ -166,7 +178,7 @@ bool string_get_is_integer(const char* string) {
} }
} }
while (index < string_length && is_integer) { while (index < string_length && is_integer) {
if (!character_get_is_digit(string[index])) { if (!character_get_is_digit(string_value[index])) {
is_integer = false; is_integer = false;
} }
index++; index++;
@ -174,113 +186,137 @@ bool string_get_is_integer(const char* string) {
return is_integer; return is_integer;
} }
char** string_split(const char* string, char separator, size_t* result_size) { string_t* string_split(const string_t string_value, char separator, size_t* result_size) {
size_t string_length = string_get_length(string); size_t string_length = string_get_length(string_value);
size_t index_string = 0; size_t index_string = 0;
size_t index_current = 0; size_t index_current = 0;
size_t index_result = 0; size_t index_result = 0;
char* current = malloc(sizeof(char*) * string_length); string_t current = malloc(sizeof(char) * (string_length + 1));
char** result = malloc(sizeof(char**) * index_result); string_t* result = NULL;
if (result == NULL || current == NULL) { if (current == NULL) {
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
while (index_string < string_length) { while (index_string < string_length) {
if (string[index_string] == separator) { if (string_value[index_string] == separator) {
result[index_result] = string_copy(current); current[index_current] = '\0';
index_result++; result = realloc(result, sizeof(string_t) * (index_result + 1));
result = realloc(result, sizeof(char*) * index_result);
if (result == NULL) { if (result == NULL) {
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
result[index_result] = string_copy(current);
index_result++;
index_current = 0; index_current = 0;
current = string_copy("");
} else { } else {
character_append(current, string[index_string]); current[index_current] = string_value[index_string];
index_current++; index_current++;
} }
index_string++; index_string++;
} }
current[index_current] = '\0';
result = realloc(result, sizeof(string_t) * (index_result + 1));
if (result == NULL) {
exit(EXIT_FAILURE);
}
result[index_result] = string_copy(current); result[index_result] = string_copy(current);
free(current); free(current);
*result_size = index_result + 1; *result_size = index_result + 1;
return result; return result;
} }
char* string_join(char** array, const char separator, size_t array_length) { string_t string_join(string_t* array, const char separator, size_t array_length) {
size_t string_length = array_length; size_t total_length = 0;
char* string = malloc(sizeof(char*) * string_length); for (size_t index_array = 0; index_array < array_length; index_array++) {
if (string == NULL) { total_length += string_get_length(array[index_array]);
}
size_t string_length = total_length + (array_length - 1);
string_t string_value = malloc(sizeof(char) * (string_length + 1));
if (string_value == NULL) {
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
size_t current_index = 0;
for (size_t index_array = 0; index_array < array_length; index_array++) { for (size_t index_array = 0; index_array < array_length; index_array++) {
char* substring = array[index_array]; string_t substring = array[index_array];
size_t substring_length = string_get_length(substring); size_t substring_length = string_get_length(substring);
string_length += substring_length;
string = realloc(string, sizeof(char*) * string_length);
if (string == NULL) {
exit(EXIT_FAILURE);
}
for (size_t index_substring = 0; index_substring < substring_length; index_substring++) { for (size_t index_substring = 0; index_substring < substring_length; index_substring++) {
character_append(string, substring[index_substring]); string_value[current_index] = substring[index_substring];
current_index++;
} }
bool is_last_character = index_array == (array_length - 1); bool is_last_character = index_array == (array_length - 1);
if (!is_last_character) { if (!is_last_character) {
character_append(string, separator); string_value[current_index] = separator;
current_index++;
} }
} }
return string; string_value[string_length] = '\0';
return string_value;
} }
char* string_concatenate(char* string1, char* string2) { string_t string_concatenate(string_t string1, string_t string2) {
size_t string1_length = string_get_length(string1); size_t string1_length = string_get_length(string1);
size_t string2_length = string_get_length(string2); size_t string2_length = string_get_length(string2);
size_t result_length = string1_length + string2_length; size_t result_length = string1_length + string2_length;
char* result = malloc(sizeof(char*) * result_length); string_t result = malloc(sizeof(char) * (result_length + 1));
if (result == NULL) { if (result == NULL) {
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
for (size_t index_string1 = 0; index_string1 < string1_length; index_string1++) { size_t index_string1 = 0;
character_append(result, string1[index_string1]); for (; index_string1 < string1_length; index_string1++) {
result[index_string1] = string1[index_string1];
} }
for (size_t index_string2 = 0; index_string2 < string2_length; index_string2++) { for (size_t index_string2 = 0; index_string2 < string2_length; index_string2++) {
character_append(result, string2[index_string2]); result[index_string1 + index_string2] = string2[index_string2];
} }
result[result_length] = '\0';
return result; return result;
} }
bool string_get_has_unique_characters(const char* string) { bool string_get_has_unique_characters(const string_t string_value) {
bool has_unique = true; bool has_unique = true;
size_t string_length = string_get_length(string); size_t string_length = string_get_length(string_value);
struct dictionary* characters_already_seen = dictionary_initialization(); struct hash_map* characters_already_seen = hash_map_initialization();
string_t* keys = malloc(sizeof(string_t) * string_length);
for (size_t index = 0; index < string_length; index++) {
keys[index] = NULL;
}
for (size_t index = 0; index < string_length && has_unique; index++) { for (size_t index = 0; index < string_length && has_unique; index++) {
char character = string[index]; char character = string_value[index];
char* key = convert_character_to_string(character); keys[index] = convert_character_to_string(character);
if (dictionary_contains_key(characters_already_seen, key)) { string_t key = keys[index];
if (hash_map_contains_key(characters_already_seen, key)) {
has_unique = false; has_unique = false;
} else { } else {
dictionary_add(characters_already_seen, key, (void*)true); hash_map_add(characters_already_seen, key, (void*)true);
} }
} }
for (size_t index = 0; index < string_length; index++) {
if (keys[index] != NULL) {
free(keys[index]);
}
}
free(keys);
hash_map_free(characters_already_seen);
return has_unique; return has_unique;
} }
char* string_substring(const char* string, size_t index_start, size_t index_end) { string_t string_substring(const string_t string_value, size_t index_start, size_t index_end) {
size_t string_length = string_get_length(string); size_t substring_length = index_end - index_start + 1;
char* result = malloc(sizeof(char*) * string_length); string_t result = malloc(sizeof(char) * (substring_length + 1));
for (size_t index = index_start; index <= index_end; index++) { for (size_t index = 0; index < substring_length; index++) {
character_append(result, string[index]); result[index] = string_value[index_start + index];
} }
result[substring_length] = '\0';
return result; return result;
} }
bool string_get_is_substring(const char* string, const char* substring) { bool string_get_is_substring(const string_t string_value, const string_t substring) {
bool is_substring = false; bool is_substring = false;
size_t string_length = string_get_length(string); size_t string_length = string_get_length(string_value);
size_t substring_length = string_get_length(substring); size_t substring_length = string_get_length(substring);
for (size_t index_string = 0; index_string < string_length && !is_substring; index_string++) { for (size_t index_string = 0; index_string < string_length && !is_substring; index_string++) {
size_t index_substring = 0; size_t index_substring = 0;
size_t index_considered = index_string; size_t index_considered = index_string;
while (index_substring < substring_length && string[index_considered] == substring[index_substring]) { while (index_substring < substring_length && string_value[index_considered] == substring[index_substring]) {
index_substring++; index_substring++;
index_considered++; index_considered++;
} }
@ -289,73 +325,89 @@ bool string_get_is_substring(const char* string, const char* substring) {
return is_substring; return is_substring;
} }
char* string_get_formatted_number(const long long number, char* separator) { string_t string_get_formatted_number(const long long number, string_t separator) {
char* number_string = convert_number_to_string(number); string_t number_string_temp = convert_number_to_string(number);
bool is_negative = number_string[0] == '-'; string_t number_string = number_string_temp;
bool is_negative = number_string_temp[0] == '-';
if (is_negative) { if (is_negative) {
number_string = string_substring(number_string, 1, string_get_length(number_string)); number_string = string_substring(number_string_temp, 1, string_get_length(number_string_temp));
free(number_string_temp);
} }
size_t number_string_length = string_get_length(number_string); size_t number_string_length = string_get_length(number_string);
char* result = malloc(sizeof(char*) * number_string_length); size_t formatted_length = number_string_length + (number_string_length - 1) / 3;
string_t result = malloc(sizeof(char) * (formatted_length + 1));
if (result == NULL) { if (result == NULL) {
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
size_t count = 0; size_t count = 0;
size_t result_index = 0;
for (size_t index = 0; index < number_string_length; index++) { for (size_t index = 0; index < number_string_length; index++) {
size_t index_reversed = number_string_length - index - 1; size_t index_reversed = number_string_length - index - 1;
result[result_index] = number_string[index_reversed];
count++; count++;
result = string_concatenate(result, convert_character_to_string(number_string[index_reversed])); result_index++;
if (count == 3) { if (count == 3 && index != number_string_length - 1) {
result = string_concatenate(result, separator); for (size_t sep_index = 0; sep_index < string_get_length(separator); sep_index++) {
result[result_index] = separator[sep_index];
result_index++;
}
count = 0; count = 0;
} }
} }
result = string_reverse(result); free(number_string);
size_t result_length = string_get_length(result); result[formatted_length] = '\0';
if (result_length % 4 == 0) { string_t new_result = string_reverse(result);
result = string_substring(result, 1, result_length); free(result);
}
if (is_negative) { if (is_negative) {
result = string_concatenate(convert_character_to_string('-'), result); string_t dash = convert_character_to_string('-');
string_t negative_result = string_concatenate(dash, new_result);
free(new_result);
free(dash);
return negative_result;
} }
return result; return new_result;
} }
char* string_get_last_occurence_of_character(const char* string, char character) { string_t string_get_last_occurence_of_character(const string_t string_value, char character) {
size_t string_length = string_get_length(string); size_t string_length = string_get_length(string_value);
char* result = malloc(sizeof(char*) * string_length); size_t index_last_occurrence = SIZE_MAX;
for (size_t index = 0; index < string_length; index++) {
if (string_value[index] == character) {
index_last_occurrence = index;
}
}
if (index_last_occurrence == SIZE_MAX) {
return "";
}
string_t result = malloc(sizeof(char) * (string_length - index_last_occurrence + 1));
if (result == NULL) { if (result == NULL) {
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
size_t index_result = 0; size_t index_result = 0;
for (size_t index = 0; index < string_length; index++) { for (size_t index = index_last_occurrence; index < string_length; index++) {
if (string[index] == character) { result[index_result++] = string_value[index];
index_result = 0;
result = string_copy("");
}
character_append(result, string[index]);
index_result++;
} }
result[index_result] = '\0';
return result; return result;
} }
bool string_starts_with(const char* string, const char* prefix) { bool string_starts_with(const string_t string_value, const string_t prefix) {
bool starts_with = true; bool starts_with = true;
size_t prefix_length = string_get_length(prefix); size_t prefix_length = string_get_length(prefix);
for (size_t index = 0; index < prefix_length && starts_with; index++) { for (size_t index = 0; index < prefix_length && starts_with; index++) {
starts_with = string[index] == prefix[index]; starts_with = string_value[index] == prefix[index];
} }
return starts_with; return starts_with;
} }
bool string_ends_with(const char* string, const char* prefix) { bool string_ends_with(const string_t string_value, const string_t prefix) {
bool ends_with = true; bool ends_with = true;
size_t string_length = string_get_length(string); size_t string_length = string_get_length(string_value);
size_t prefix_length = string_get_length(prefix); size_t prefix_length = string_get_length(prefix);
size_t index_string = string_length - 1; size_t index_string = string_length - 1;
size_t index_prefix = prefix_length - 1; size_t index_prefix = prefix_length - 1;
while (index_prefix > 0 && ends_with) { while (index_prefix > 0 && ends_with) {
ends_with = string[index_string] == prefix[index_prefix]; ends_with = string_value[index_string] == prefix[index_prefix];
index_string--; index_string--;
index_prefix--; index_prefix--;
} }

View File

@ -1,204 +1,223 @@
#ifndef __STRING__ #ifndef __LIBCPROJECT_STRING__
#define __STRING__ #define __LIBCPROJECT_STRING__
#include <stdbool.h> #include <stdbool.h>
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include "character.h"
#include "convert.h"
#include "hash_map.h"
#include "types.h"
/** /**
* @brief Return the length of a string (excluding '\0'). * @brief Return the length of a string (excluding '\0').
* *
* @param string * @param string_value
* @return size_t * @since v1.0.0
*/ */
size_t string_get_length(const char* string); size_t string_get_length(const string_t string_value);
/** /**
* @brief Converts all the alphabetic characters in a string to uppercase. * @brief Converts all the alphabetic characters in a string to uppercase.
* *
* @param string * @param string_value
* @return char* * @since v1.0.0
*/ */
char* string_to_uppercase(char* string); string_t string_to_uppercase(string_t string_value);
/** /**
* @brief Converts all the alphabetic characters in a string to lowercase. * @brief Converts all the alphabetic characters in a string to lowercase.
* *
* @param string * @param string_value
* @return char* * @since v1.0.0
*/ */
char* string_to_lowercase(char* string); string_t string_to_lowercase(string_t string_value);
/** /**
* @brief Replace all the occurrences of search value into replace value in the string. * @brief Replace all the occurrences of search value into replace value in the string.
* *
* @param string * @param string_value
* @param search_value A character search value. * @param search A character search value.
* @param replace_value A character containing the text to replace for match. * @param replace A character containing the text to replace for match.
* @return char* * @since v1.0.0
*/ */
char* string_replace(char* string, char search, char replace); string_t string_replace(string_t string_value, char search, char replace);
/** /**
* @brief Removes all whitespace from the start of a string. * @brief Removes all `character` from the start of a string.
* *
* @param string * @param string_value
* @return char* * @since v1.0.0
*/ */
char* string_trim_start(char* string); string_t string_trim_start(string_t string_value, char character);
/** /**
* @brief Removes all whitespace from the end of a string. * @brief Removes all `character` from the end of a string.
* *
* @param string * @param string_value
* @return char* * @since v1.0.0
*/ */
char* string_trim_end(char* string); string_t string_trim_end(string_t string_value, char character);
/** /**
* @brief Removes all whitespace from the start and end of a string. * @brief Removes all `character` from the start and end of a string.
* *
* @param string * @param string_value
* @return char* * @since v1.0.0
*/ */
char* string_trim(char* string); string_t string_trim(string_t string_value, char character);
/** /**
* @brief Return the copy of a string. * @brief Return the copy of a string.
* *
* @param string * @param string_value
* @return char* * @since v1.0.0
*/ */
char* string_copy(const char* string); string_t string_copy(const string_t string_value);
/** /**
* @brief Capitalizes the string. * @brief Capitalizes the string.
* *
* @param string * @param string_value
* @return char* * @since v1.0.0
*/ */
char* string_capitalize(char* string); string_t string_capitalize(string_t string_value);
/** /**
* @brief Returns the total number of occurrences of the given character in the string. * @brief Returns the total number of occurrences of the given character in the string.
* *
* @param string * @param string_value
* @param character * @param character
* @return size_t * @since v1.0.0
*/ */
size_t string_total_occurrences_of_character(char* string, char character); size_t string_total_occurrences_of_character(string_t string_value, char character);
/** /**
* @brief Reverse the characters in an array. * @brief Reverse the characters in an array.
* *
* @param string * @param string_value
* @return char* * @since v1.0.0
*/ */
char* string_reverse(const char* string); string_t string_reverse(const string_t string_value);
/** /**
* @brief Check if two strings are equals. * @brief Check if two strings are equals.
* *
* @param string1 * @param string1
* @param string2 * @param string2
* @return true if the strings are equals, false otherwise * @return true if the strings are equals, false otherwise.
* @since v1.0.0
*/ */
bool string_equals(const char* string1, const char* string2); bool string_equals(const string_t string1, const string_t string2);
/** /**
* @brief Check if the string is a integer. * @brief Check if the string is a integer.
* *
* @param string * @param string_value
* @return true if the string is a integer, false otherwise * @return true if the string is a integer, false otherwise.
* @since v1.0.0
*/ */
bool string_get_is_integer(const char* string); bool string_get_is_integer(const string_t string_value);
/** /**
* @brief Split a string into substrings using the specified separator and return them as an array and update the pointer `result_size` to the resulting size of the created array. * @brief Split a string into substrings using the specified separator and return them as an array and update the pointer `result_size` to the resulting size of the created array.
* *
* @param string * @param string_value
* @param separator * @param separator
* @return char** * @param result_size
* @since v1.0.0
*/ */
char** string_split(const char* string, char separator, size_t* result_size); string_t* string_split(const string_t string_value, char separator, size_t* result_size);
/** /**
* @brief Adds all the elements of an array into a string, separated by the specified separator string. * @brief Adds all the elements of an array into a string, separated by the specified separator string.
* *
* @param array * @param array
* @param separator * @param separator
* @return char* * @param array_length
* @since v1.0.0
*/ */
char* string_join(char** array, const char separator, size_t array_length); string_t string_join(string_t* array, const char separator, size_t array_length);
/** /**
* @brief Concatenate two strings. * @brief Concatenate two strings.
* *
* @param string1 * @param string1
* @param string2 * @param string2
* @return char* * @since v1.0.0
*/ */
char* string_concatenate(char* string1, char* string2); string_t string_concatenate(string_t string1, string_t string2);
/** /**
* @brief Check if a string contains only unique characters. * @brief Check if a string contains only unique characters.
* *
* @param string * @param string
* @return true if string contains only unique characters, false otherwise * @return true if string contains only unique characters, false otherwise.
* @since v1.0.0
*/ */
bool string_get_has_unique_characters(const char* string); bool string_get_has_unique_characters(const string_t string);
/** /**
* @brief Returns the part of the string between the start and end indexes (both included). * @brief Returns the part of the string between the start and end indexes (both included).
* *
* @param string * @param string_value
* @param index_start * @param index_start
* @param index_end * @param index_end
* @return char* * @since v1.0.0
*/ */
char* string_substring(const char* string, size_t index_start, size_t index_end); string_t string_substring(const string_t string_value, size_t index_start, size_t index_end);
/** /**
* @brief Check if a string contains a substring. * @brief Check if a string contains a substring.
* *
* @param string * @param string_value
* @param substring * @param substring
* @return true if the string contains the substring, false otherwise * @return true if the string contains the substring, false otherwise.
* @since v1.0.0
*/ */
bool string_get_is_substring(const char* string, const char* substring); bool string_get_is_substring(const string_t string_value, const string_t substring);
/** /**
* @brief Format a number to a string with specified separator. * @brief Format a number to a string with specified separator.
* *
* @param integer * @param number
* @return char* example: string_get_formatted_number(1000, " ") => "1 000" * @param separator
* @since v1.0.0
* @code
* string_get_formatted_number(1000, " ") // "1 000"
* string_get_formatted_number(1000, ",") // "1,000"
* @endcode
*/ */
char* string_get_formatted_number(const long long number, char* separator); string_t string_get_formatted_number(const long long number, string_t separator);
/** /**
* @brief Returns a pointer to the last occurrence of character in the string. * @brief Returns a pointer to the last occurrence of character in the string.
* *
* @param string * @param string_value
* @param character * @param character
* @return char* * @since v1.0.0
*/ */
char* string_get_last_occurence_of_character(const char* string, char character); string_t string_get_last_occurence_of_character(const string_t string_value, char character);
/** /**
* @brief Check if a string starts with a substring. * @brief Check if a string starts with a substring.
* *
* @param string * @param string_value
* @param prefix * @param prefix
* @return true if the string starts with the substring, false otherwise * @return true if the string starts with the substring, false otherwise.
* @since v1.0.0
*/ */
bool string_starts_with(const char* string, const char* prefix); bool string_starts_with(const string_t string_value, const string_t prefix);
/** /**
* @brief Check if a string ends with a substring. * @brief Check if a string ends with a substring.
* *
* @param string * @param string_value
* @param prefix * @param prefix
* @return true if the string ends with the substring, false otherwise * @return true if the string ends with the substring, false otherwise.
* @since v1.0.0
*/ */
bool string_ends_with(const char* string, const char* prefix); bool string_ends_with(const string_t string_value, const string_t prefix);
#endif #endif

View File

@ -1,33 +1,22 @@
#include "terminal.h" #include "terminal.h"
#include <stdbool.h> string_t terminal_input() {
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "character.h"
#include "dictionary.h"
#include "linked_list.h"
#include "queue.h"
#include "stack.h"
char* terminal_input() {
char character; char character;
size_t length = 1; size_t length = 1;
char* string = malloc(length * sizeof(char)); string_t string_value = malloc(length * sizeof(char));
if (string == NULL) { if (string_value == NULL) {
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
*string = '\0'; *string_value = '\0';
while ((character = getchar()) != '\n' && character != EOF) { while ((character = getchar()) != '\n' && character != EOF) {
length++; length++;
string = realloc(string, length * sizeof(char)); string_value = realloc(string_value, length * sizeof(char));
if (string == NULL) { if (string_value == NULL) {
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
character_append(string, character); character_append(string_value, character);
} }
return string; return string_value;
} }
void terminal_print_array(void* array, size_t array_size, size_t element_size, void (*print_element)(void*)) { void terminal_print_array(void* array, size_t array_size, size_t element_size, void (*print_element)(void*)) {
@ -105,18 +94,24 @@ void terminal_print_linked_list(struct linked_list* linked_list, void (*print_el
printf("NULL\n"); printf("NULL\n");
} }
void terminal_print_dictionary(struct dictionary* dictionary, void (*print_element)(void*)) { void terminal_print_hash_map(struct hash_map* hash_map, void (*print_element)(void*)) {
if (dictionary == NULL) { if (hash_map == NULL) {
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
printf("{\n"); printf("{\n");
for (size_t index = 0; index < dictionary->length; index++) { string_t* keys = hash_map_get_keys(hash_map);
struct dictionary_item* item = dictionary->items[index]; for (size_t index = 0; index < hash_map->length; index++) {
string_t key = keys[index];
void* value = hash_map_get(hash_map, key);
printf("\t\""); printf("\t\"");
terminal_print_string(item->key); terminal_print_string(key);
printf("\" -> "); printf("\" -> ");
print_element(&item->data); print_element(&value);
printf("\n"); printf("\n");
} }
printf("}\n"); printf("}\n");
} }
void terminal_print_array_list(struct array_list* list, void (*print_element)(void*)) {
terminal_print_array(list->data, list->size, sizeof(void*), print_element);
}

View File

@ -1,38 +1,119 @@
#ifndef __TERMINAL__ #ifndef __LIBCPROJECT_TERMINAL__
#define __TERMINAL__ #define __LIBCPROJECT_TERMINAL__
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include "dictionary.h" #include "array_list.h"
#include "character.h"
#include "hash_map.h"
#include "linked_list.h" #include "linked_list.h"
#include "queue.h" #include "queue.h"
#include "stack.h" #include "stack.h"
#include "types.h"
/** /**
* @brief Read a line from stdin. * @brief Read a line from stdin.
* * @since v1.0.0
* @return char*
*/ */
char* terminal_input(); string_t terminal_input();
/**
* @brief Print an array.
*
* @param array
* @param array_size
* @param element_size
* @param print_element
* @since v1.0.0
*/
void terminal_print_array(void* array, size_t array_size, size_t element_size, void (*print_element)(void*)); void terminal_print_array(void* array, size_t array_size, size_t element_size, void (*print_element)(void*));
/**
* @brief Print a int.
*
* @param value
* @since v1.0.0
*/
void terminal_print_int(void* value); void terminal_print_int(void* value);
/**
* @brief Print a long.
*
* @param value
* @since v1.0.0
*/
void terminal_print_long(void* value); void terminal_print_long(void* value);
/**
* @brief Print a unsigned long.
*
* @param value
* @since v1.0.0
*/
void terminal_print_unsigned_long(void* value); void terminal_print_unsigned_long(void* value);
/**
* @brief Print a char.
*
* @param value
* @since v1.0.0
*/
void terminal_print_char(void* value); void terminal_print_char(void* value);
/**
* @brief Print a string.
*
* @param value
* @since v1.0.0
*/
void terminal_print_string(void* value); void terminal_print_string(void* value);
/**
* @brief Print a stack.
*
* @param stack
* @param print_element
* @since v1.0.0
*/
void terminal_print_stack(struct stack* stack, void (*print_element)(void*)); void terminal_print_stack(struct stack* stack, void (*print_element)(void*));
/**
* @brief Print a queue.
*
* @param queue
* @param print_element
* @since v1.0.0
*/
void terminal_print_queue(struct queue* queue, void (*print_element)(void*)); void terminal_print_queue(struct queue* queue, void (*print_element)(void*));
/**
* @brief Print a linked list.
*
* @param linked_list
* @param print_element
* @since v1.0.0
*/
void terminal_print_linked_list(struct linked_list* linked_list, void (*print_element)(void*)); void terminal_print_linked_list(struct linked_list* linked_list, void (*print_element)(void*));
void terminal_print_dictionary(struct dictionary* dictionary, void (*print_element)(void*)); /**
* @brief Print a hash map.
*
* @param hash_map
* @param print_element
* @since v2.0.0
*/
void terminal_print_hash_map(struct hash_map* hash_map, void (*print_element)(void*));
/**
* @brief Print an array list.
*
* @param array_list
* @param print_element
* @since v3.0.0
*/
void terminal_print_array_list(struct array_list* list, void (*print_element)(void*));
#endif #endif

10
lib/types.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef __LIBCPROJECT_TYPES__
#define __LIBCPROJECT_TYPES__
#include <stdint.h>
typedef uint8_t byte_t;
typedef char* string_t;
#endif

View File

@ -1,15 +1,18 @@
#ifndef __LIBCPROJECT__ #ifndef __LIBCPROJECT__
#define __LIBCPROJECT__ #define __LIBCPROJECT__
#include "lib/array_list.h"
#include "lib/character.h" #include "lib/character.h"
#include "lib/convert.h" #include "lib/convert.h"
#include "lib/dictionary.h"
#include "lib/filesystem.h" #include "lib/filesystem.h"
#include "lib/hash_map.h"
#include "lib/linked_list.h" #include "lib/linked_list.h"
#include "lib/mathematics.h" #include "lib/mathematics.h"
#include "lib/queue.h" #include "lib/queue.h"
#include "lib/stack.h" #include "lib/stack.h"
#include "lib/string.h" #include "lib/string.h"
#include "lib/terminal.h" #include "lib/terminal.h"
#include "lib/types.h"
#include "version.h"
#endif #endif

6
main.c
View File

@ -4,8 +4,8 @@
#include "libcproject.h" #include "libcproject.h"
int main() { int main() {
char* string = "Hello, world!"; string_t string_value = "Hello, world!";
printf("%s\n", string); printf("%s\n", string_value);
printf("string_length = %ld\n", string_get_length(string)); printf("string_length = %ld\n", string_get_length(string_value));
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }

View File

@ -3,21 +3,22 @@
#include "libcproject.h" #include "libcproject.h"
int main(int argc, char* argv[]) { int main(int argc, string_t* argv) {
if (argc != 2) { if (argc != 2) {
fprintf(stderr, "Usage: %s <version>\n", argv[0]); fprintf(stderr, "Usage: %s <version>\n", argv[0]);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
char* content = "#ifndef __LIBCPROJECT_VERSION__\n"; string_t content = "#ifndef __LIBCPROJECT_VERSION__\n";
content = string_concatenate(content, "#define __LIBCPROJECT_VERSION__ \""); content = string_concatenate(content, "#define __LIBCPROJECT_VERSION__ \"");
content = string_concatenate(content, argv[1]); content = string_concatenate(content, argv[1]);
content = string_concatenate(content, "\"\n\n"); content = string_concatenate(content, "\"\n\n");
content = string_concatenate(content, "#endif\n"); content = string_concatenate(content, "#endif\n");
int result = filesystem_write("./version.h", content, string_get_length(content)); int result = filesystem_write("./version.h", (byte_t*)content, string_get_length(content));
if (result == -1) { if (result == -1) {
fprintf(stderr, "Error: Could not write to file.\n"); fprintf(stderr, "Error: Could not write to file.\n");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
printf("Success: Version set to %s.\n", argv[1]); printf("Success: Version set to %s.\n", argv[1]);
free(content);
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }

37
test/array_list_test.c Normal file
View File

@ -0,0 +1,37 @@
#include "array_list_test.h"
void array_list_test() {
struct array_list *list = array_list_initialization();
assert(list->size == 0);
array_list_add(list, (void *)'a');
array_list_add(list, (void *)'b');
array_list_add(list, (void *)'c');
array_list_add(list, (void *)'d');
array_list_add(list, (void *)'e');
array_list_add(list, (void *)'f');
assert(list->size == 6);
assert(array_list_get(list, 0) == (void *)'a');
assert(array_list_get(list, 1) == (void *)'b');
assert(array_list_get(list, 2) == (void *)'c');
assert(array_list_get(list, 3) == (void *)'d');
assert(array_list_get(list, 4) == (void *)'e');
assert(array_list_get(list, 5) == (void *)'f');
array_list_add(list, (void *)'a');
assert(array_list_get(list, 6) == (void *)'a');
assert(list->size == 7);
array_list_remove(list, 6);
assert(list->size == 6);
assert(array_list_get(list, 6) == NULL);
for (size_t index = 0; index < 100; index++) {
array_list_add(list, (void *)index);
}
assert(list->size == 106);
assert(array_list_get(list, 100) == (void *)94);
assert(array_list_get(list, 101) == (void *)95);
array_list_remove(list, 100);
assert(list->size == 105);
assert(array_list_get(list, 100) == (void *)95);
array_list_free(list);
}

13
test/array_list_test.h Normal file
View File

@ -0,0 +1,13 @@
#ifndef __ARRAY_LIST_TEST__
#define __ARRAY_LIST_TEST__
#include <assert.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "libcproject.h"
void array_list_test();
#endif

View File

@ -1,12 +1,5 @@
#include "character_test.h" #include "character_test.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include "libcproject.h"
#include "test.h"
void character_test() { void character_test() {
character_append_test(); character_append_test();
character_append_at_test(); character_append_at_test();
@ -27,7 +20,7 @@ void character_append_at_test() {
character_append_at(string, 'd', 1); character_append_at(string, 'd', 1);
assert(assert_string_equal(string, "adbc")); assert(assert_string_equal(string, "adbc"));
char string2[5] = "abcd"; char string2[6] = "abcd";
character_append_at(string2, 'e', 4); character_append_at(string2, 'e', 4);
assert(assert_string_equal(string2, "abcde")); assert(assert_string_equal(string2, "abcde"));
} }

View File

@ -1,6 +1,13 @@
#ifndef __CHARACTER_TEST__ #ifndef __CHARACTER_TEST__
#define __CHARACTER_TEST__ #define __CHARACTER_TEST__
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include "libcproject.h"
#include "test.h"
void character_test(); void character_test();
void character_append_test(); void character_append_test();

View File

@ -1,12 +1,5 @@
#include "convert_test.h" #include "convert_test.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include "libcproject.h"
#include "test.h"
void convert_test() { void convert_test() {
convert_character_to_string_test(); convert_character_to_string_test();
convert_character_to_digit_test(); convert_character_to_digit_test();
@ -17,11 +10,25 @@ void convert_test() {
} }
void convert_character_to_string_test() { void convert_character_to_string_test() {
assert(assert_string_equal(convert_character_to_string('a'), "a")); char* result = convert_character_to_string('a');
assert(assert_string_equal(convert_character_to_string('A'), "A")); assert(assert_string_equal(result, "a"));
assert(assert_string_equal(convert_character_to_string('0'), "0")); free(result);
assert(assert_string_equal(convert_character_to_string(' '), " "));
assert(assert_string_equal(convert_character_to_string('\0'), "")); result = convert_character_to_string('A');
assert(assert_string_equal(result, "A"));
free(result);
result = convert_character_to_string('0');
assert(assert_string_equal(result, "0"));
free(result);
result = convert_character_to_string(' ');
assert(assert_string_equal(result, " "));
free(result);
result = convert_character_to_string('\0');
assert(assert_string_equal(result, ""));
free(result);
} }
void convert_character_to_digit_test() { void convert_character_to_digit_test() {
@ -70,33 +77,109 @@ void convert_string_to_number_test() {
} }
void convert_number_to_string_test() { void convert_number_to_string_test() {
assert(assert_string_equal(convert_number_to_string(0), "0")); char* result = convert_number_to_string(0);
assert(assert_string_equal(convert_number_to_string(1), "1")); assert(assert_string_equal(result, "0"));
assert(assert_string_equal(convert_number_to_string(2), "2")); free(result);
assert(assert_string_equal(convert_number_to_string(3), "3"));
assert(assert_string_equal(convert_number_to_string(4), "4")); result = convert_number_to_string(1);
assert(assert_string_equal(convert_number_to_string(5), "5")); assert(assert_string_equal(result, "1"));
assert(assert_string_equal(convert_number_to_string(6), "6")); free(result);
assert(assert_string_equal(convert_number_to_string(7), "7"));
assert(assert_string_equal(convert_number_to_string(8), "8")); result = convert_number_to_string(2);
assert(assert_string_equal(convert_number_to_string(9), "9")); assert(assert_string_equal(result, "2"));
assert(assert_string_equal(convert_number_to_string(10), "10")); free(result);
assert(assert_string_equal(convert_number_to_string(11), "11"));
assert(assert_string_equal(convert_number_to_string(20), "20")); result = convert_number_to_string(3);
assert(assert_string_equal(convert_number_to_string(-0), "0")); assert(assert_string_equal(result, "3"));
assert(assert_string_equal(convert_number_to_string(-1), "-1")); free(result);
assert(assert_string_equal(convert_number_to_string(-20), "-20"));
result = convert_number_to_string(4);
assert(assert_string_equal(result, "4"));
free(result);
result = convert_number_to_string(5);
assert(assert_string_equal(result, "5"));
free(result);
result = convert_number_to_string(6);
assert(assert_string_equal(result, "6"));
free(result);
result = convert_number_to_string(7);
assert(assert_string_equal(result, "7"));
free(result);
result = convert_number_to_string(8);
assert(assert_string_equal(result, "8"));
free(result);
result = convert_number_to_string(9);
assert(assert_string_equal(result, "9"));
free(result);
result = convert_number_to_string(10);
assert(assert_string_equal(result, "10"));
free(result);
result = convert_number_to_string(11);
assert(assert_string_equal(result, "11"));
free(result);
result = convert_number_to_string(20);
assert(assert_string_equal(result, "20"));
free(result);
result = convert_number_to_string(-0);
assert(assert_string_equal(result, "0"));
free(result);
result = convert_number_to_string(-1);
assert(assert_string_equal(result, "-1"));
free(result);
result = convert_number_to_string(-20);
assert(assert_string_equal(result, "-20"));
free(result);
} }
void convert_number_from_base_to_another_test() { void convert_number_from_base_to_another_test() {
assert(assert_string_equal(convert_number_from_base_to_another("15", 10, 16), "F")); char* result = convert_number_from_base_to_another("15", 10, 16);
assert(assert_string_equal(convert_number_from_base_to_another("100000000", 2, 16), "100")); assert(assert_string_equal(result, "F"));
assert(assert_string_equal(convert_number_from_base_to_another("FFFFFF", 16, 10), "16777215")); free(result);
assert(assert_string_equal(convert_number_from_base_to_another("1D57", 17, 35), "75C"));
assert(assert_string_equal(convert_number_from_base_to_another("80E", 20, 5), "100324")); result = convert_number_from_base_to_another("100000000", 2, 16);
assert(assert_string_equal(convert_number_from_base_to_another("99", 10, 10), "99")); assert(assert_string_equal(result, "100"));
assert(assert_string_equal(convert_number_from_base_to_another("3433024", 6, 28), "8008")); free(result);
assert(assert_string_equal(convert_number_from_base_to_another("30288G3A", 17, 36), "KF12OI"));
assert(assert_string_equal(convert_number_from_base_to_another("10", 9, 9), "10")); result = convert_number_from_base_to_another("FFFFFF", 16, 10);
assert(assert_string_equal(convert_number_from_base_to_another("10E", 23, 8), "1037")); assert(assert_string_equal(result, "16777215"));
free(result);
result = convert_number_from_base_to_another("1D57", 17, 35);
assert(assert_string_equal(result, "75C"));
free(result);
result = convert_number_from_base_to_another("80E", 20, 5);
assert(assert_string_equal(result, "100324"));
free(result);
result = convert_number_from_base_to_another("99", 10, 10);
assert(assert_string_equal(result, "99"));
free(result);
result = convert_number_from_base_to_another("3433024", 6, 28);
assert(assert_string_equal(result, "8008"));
free(result);
result = convert_number_from_base_to_another("30288G3A", 17, 36);
assert(assert_string_equal(result, "KF12OI"));
free(result);
result = convert_number_from_base_to_another("10", 9, 9);
assert(assert_string_equal(result, "10"));
free(result);
result = convert_number_from_base_to_another("10E", 23, 8);
assert(assert_string_equal(result, "1037"));
free(result);
} }

View File

@ -1,6 +1,13 @@
#ifndef __CONVERT_TEST__ #ifndef __CONVERT_TEST__
#define __CONVERT_TEST__ #define __CONVERT_TEST__
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include "libcproject.h"
#include "test.h"
void convert_test(); void convert_test();
void convert_character_to_string_test(); void convert_character_to_string_test();

View File

@ -1,33 +0,0 @@
#include "dictionary_test.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include "libcproject.h"
void dictionary_test() {
struct dictionary *dictionary = dictionary_initialization();
assert(dictionary->length == 0);
dictionary_add(dictionary, "key", (void *)'a');
dictionary_add(dictionary, "key1", (void *)'b');
dictionary_add(dictionary, "key2", (void *)'c');
dictionary_add(dictionary, "key3", (void *)'d');
dictionary_add(dictionary, "key4", (void *)'e');
dictionary_add(dictionary, "key5", (void *)'f');
assert(dictionary->length == 6);
assert(dictionary_get(dictionary, "key")->data == (void *)'a');
assert(dictionary_get(dictionary, "key1")->data == (void *)'b');
assert(dictionary_get(dictionary, "key2")->data == (void *)'c');
assert(dictionary_get(dictionary, "key3")->data == (void *)'d');
assert(dictionary_get(dictionary, "key4")->data == (void *)'e');
assert(dictionary_get(dictionary, "key5")->data == (void *)'f');
dictionary_add(dictionary, "key5", (void *)'a');
assert(dictionary_get(dictionary, "key5")->data == (void *)'a');
assert(dictionary_contains_key(dictionary, "key5"));
assert(!dictionary_contains_key(dictionary, "invalid key"));
assert(dictionary_contains_key(dictionary, "key5"));
dictionary_remove(dictionary, "key5");
assert(dictionary->length == 5);
assert(!dictionary_contains_key(dictionary, "key5"));
}

View File

@ -1,6 +0,0 @@
#ifndef __DICTIONARY_TEST__
#define __DICTIONARY_TEST__
void dictionary_test();
#endif

28
test/hash_map_test.c Normal file
View File

@ -0,0 +1,28 @@
#include "hash_map_test.h"
void hash_map_test() {
struct hash_map *hash_map = hash_map_initialization();
assert(hash_map->length == 0);
hash_map_add(hash_map, "key", (void *)'a');
hash_map_add(hash_map, "key1", (void *)'b');
hash_map_add(hash_map, "key2", (void *)'c');
hash_map_add(hash_map, "key3", (void *)'d');
hash_map_add(hash_map, "key4", (void *)'e');
hash_map_add(hash_map, "key5", (void *)'f');
assert(hash_map->length == 6);
assert(hash_map_get(hash_map, "key") == (void *)'a');
assert(hash_map_get(hash_map, "key1") == (void *)'b');
assert(hash_map_get(hash_map, "key2") == (void *)'c');
assert(hash_map_get(hash_map, "key3") == (void *)'d');
assert(hash_map_get(hash_map, "key4") == (void *)'e');
assert(hash_map_get(hash_map, "key5") == (void *)'f');
hash_map_add(hash_map, "key5", (void *)'a');
assert(hash_map_get(hash_map, "key5") == (void *)'a');
assert(hash_map_contains_key(hash_map, "key5"));
assert(!hash_map_contains_key(hash_map, "invalid key"));
assert(hash_map_contains_key(hash_map, "key5"));
hash_map_remove(hash_map, "key5");
assert(hash_map->length == 5);
assert(!hash_map_contains_key(hash_map, "key5"));
hash_map_free(hash_map);
}

12
test/hash_map_test.h Normal file
View File

@ -0,0 +1,12 @@
#ifndef __HASH_MAP_TEST__
#define __HASH_MAP_TEST__
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include "libcproject.h"
void hash_map_test();
#endif

View File

@ -1,12 +1,5 @@
#include "linked_list_test.h" #include "linked_list_test.h"
#include <assert.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "libcproject.h"
void linked_list_test() { void linked_list_test() {
linked_list_initialization_test(); linked_list_initialization_test();
linked_list_add_in_head_test(); linked_list_add_in_head_test();
@ -20,6 +13,7 @@ void linked_list_initialization_test() {
struct linked_list *list = linked_list_initialization(); struct linked_list *list = linked_list_initialization();
assert(list->length == 0); assert(list->length == 0);
assert(list->head == NULL); assert(list->head == NULL);
linked_list_free(list);
} }
void linked_list_add_in_head_test() { void linked_list_add_in_head_test() {
@ -32,6 +26,7 @@ void linked_list_add_in_head_test() {
assert(((uintptr_t)list->head->next->data) == 8); assert(((uintptr_t)list->head->next->data) == 8);
assert(((uintptr_t)list->head->next->next->data) == 4); assert(((uintptr_t)list->head->next->next->data) == 4);
assert(list->head->next->next->next == NULL); assert(list->head->next->next->next == NULL);
linked_list_free(list);
} }
void linked_list_delete_in_head_test() { void linked_list_delete_in_head_test() {
@ -44,6 +39,7 @@ void linked_list_delete_in_head_test() {
assert(((uintptr_t)list->head->data) == 8); assert(((uintptr_t)list->head->data) == 8);
assert(((uintptr_t)list->head->next->data) == 4); assert(((uintptr_t)list->head->next->data) == 4);
assert(list->head->next->next == NULL); assert(list->head->next->next == NULL);
linked_list_free(list);
} }
void linked_list_add_after_last_test() { void linked_list_add_after_last_test() {
@ -61,6 +57,7 @@ void linked_list_add_after_last_test() {
assert(((uintptr_t)list->head->next->data) == 8); assert(((uintptr_t)list->head->next->data) == 8);
assert(((uintptr_t)list->head->next->next->data) == 4); assert(((uintptr_t)list->head->next->next->data) == 4);
assert(((uintptr_t)list->head->next->next->next->data) == 18); assert(((uintptr_t)list->head->next->next->next->data) == 18);
linked_list_free(list);
} }
void linked_list_reverse_test() { void linked_list_reverse_test() {
@ -81,6 +78,8 @@ void linked_list_reverse_test() {
assert((list_reversed->head->next->data) == (void *)'C'); assert((list_reversed->head->next->data) == (void *)'C');
assert((list_reversed->head->next->next->data) == (void *)'B'); assert((list_reversed->head->next->next->data) == (void *)'B');
assert((list_reversed->head->next->next->next->data) == (void *)'A'); assert((list_reversed->head->next->next->next->data) == (void *)'A');
linked_list_free(list);
linked_list_free(list_reversed);
} }
void linked_list_reverse_mutate_test() { void linked_list_reverse_mutate_test() {
@ -96,4 +95,5 @@ void linked_list_reverse_mutate_test() {
assert((list->head->next->data) == (void *)'C'); assert((list->head->next->data) == (void *)'C');
assert((list->head->next->next->data) == (void *)'B'); assert((list->head->next->next->data) == (void *)'B');
assert((list->head->next->next->next->data) == (void *)'A'); assert((list->head->next->next->next->data) == (void *)'A');
linked_list_free(list);
} }

View File

@ -1,6 +1,13 @@
#ifndef __LINKED_LIST_TEST__ #ifndef __LINKED_LIST_TEST__
#define __LINKED_LIST_TEST__ #define __LINKED_LIST_TEST__
#include <assert.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "libcproject.h"
void linked_list_test(); void linked_list_test();
void linked_list_initialization_test(); void linked_list_initialization_test();

View File

@ -1,9 +1,10 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include "array_list_test.h"
#include "character_test.h" #include "character_test.h"
#include "convert_test.h" #include "convert_test.h"
#include "dictionary_test.h" #include "hash_map_test.h"
#include "linked_list_test.h" #include "linked_list_test.h"
#include "mathematics_test.h" #include "mathematics_test.h"
#include "queue_test.h" #include "queue_test.h"
@ -11,9 +12,10 @@
#include "string_test.h" #include "string_test.h"
int main() { int main() {
array_list_test();
character_test(); character_test();
convert_test(); convert_test();
dictionary_test(); hash_map_test();
linked_list_test(); linked_list_test();
mathematics_test(); mathematics_test();
queue_test(); queue_test();

View File

@ -1,9 +1,5 @@
#include "mathematics_test.h" #include "mathematics_test.h"
#include <assert.h>
#include "libcproject.h"
void mathematics_test() { void mathematics_test() {
mathematics_absolute_value_test(); mathematics_absolute_value_test();
mathematics_pow_test(); mathematics_pow_test();

View File

@ -1,6 +1,10 @@
#ifndef __MATHEMATICS_TEST__ #ifndef __MATHEMATICS_TEST__
#define __MATHEMATICS_TEST__ #define __MATHEMATICS_TEST__
#include <assert.h>
#include "libcproject.h"
void mathematics_test(); void mathematics_test();
void mathematics_absolute_value_test(); void mathematics_absolute_value_test();

View File

@ -1,11 +1,5 @@
#include "queue_test.h" #include "queue_test.h"
#include <assert.h>
#include <stdint.h>
#include <stdlib.h>
#include "libcproject.h"
void queue_test() { void queue_test() {
queue_initialization_test(); queue_initialization_test();
queue_push_test(); queue_push_test();
@ -16,6 +10,7 @@ void queue_initialization_test() {
struct queue *queue = queue_initialization(); struct queue *queue = queue_initialization();
assert(queue->length == 0); assert(queue->length == 0);
assert(queue->first == NULL); assert(queue->first == NULL);
queue_free(queue);
} }
void queue_push_test() { void queue_push_test() {
@ -28,6 +23,7 @@ void queue_push_test() {
assert(((uintptr_t)queue->first->next->data) == 8); assert(((uintptr_t)queue->first->next->data) == 8);
assert(((uintptr_t)queue->first->next->next->data) == 15); assert(((uintptr_t)queue->first->next->next->data) == 15);
assert(queue->first->next->next->next == NULL); assert(queue->first->next->next->next == NULL);
queue_free(queue);
} }
void queue_pop_test() { void queue_pop_test() {
@ -41,4 +37,5 @@ void queue_pop_test() {
assert(((uintptr_t)queue->first->data) == 8); assert(((uintptr_t)queue->first->data) == 8);
assert(((uintptr_t)queue->first->next->data) == 15); assert(((uintptr_t)queue->first->next->data) == 15);
assert(queue->first->next->next == NULL); assert(queue->first->next->next == NULL);
queue_free(queue);
} }

View File

@ -1,6 +1,12 @@
#ifndef __QUEUE_TEST__ #ifndef __QUEUE_TEST__
#define __QUEUE_TEST__ #define __QUEUE_TEST__
#include <assert.h>
#include <stdint.h>
#include <stdlib.h>
#include "libcproject.h"
void queue_test(); void queue_test();
void queue_initialization_test(); void queue_initialization_test();

View File

@ -1,11 +1,5 @@
#include "stack_test.h" #include "stack_test.h"
#include <assert.h>
#include <stdint.h>
#include <stdlib.h>
#include "libcproject.h"
void stack_test() { void stack_test() {
stack_initialization_test(); stack_initialization_test();
stack_push_test(); stack_push_test();
@ -16,6 +10,7 @@ void stack_initialization_test() {
struct stack *stack = stack_initialization(); struct stack *stack = stack_initialization();
assert(stack->length == 0); assert(stack->length == 0);
assert(stack->first == NULL); assert(stack->first == NULL);
stack_free(stack);
} }
void stack_push_test() { void stack_push_test() {
@ -28,6 +23,7 @@ void stack_push_test() {
assert(((uintptr_t)stack->first->next->data) == 8); assert(((uintptr_t)stack->first->next->data) == 8);
assert(((uintptr_t)stack->first->next->next->data) == 4); assert(((uintptr_t)stack->first->next->next->data) == 4);
assert(stack->first->next->next->next == NULL); assert(stack->first->next->next->next == NULL);
stack_free(stack);
} }
void stack_pop_test() { void stack_pop_test() {
@ -41,4 +37,5 @@ void stack_pop_test() {
assert(((uintptr_t)stack->first->data) == 8); assert(((uintptr_t)stack->first->data) == 8);
assert(((uintptr_t)stack->first->next->data) == 4); assert(((uintptr_t)stack->first->next->data) == 4);
assert(stack->first->next->next == NULL); assert(stack->first->next->next == NULL);
stack_free(stack);
} }

View File

@ -1,6 +1,12 @@
#ifndef __STACK_TEST__ #ifndef __STACK_TEST__
#define __STACK_TEST__ #define __STACK_TEST__
#include <assert.h>
#include <stdint.h>
#include <stdlib.h>
#include "libcproject.h"
void stack_test(); void stack_test();
void stack_initialization_test(); void stack_initialization_test();

View File

@ -1,12 +1,5 @@
#include "string_test.h" #include "string_test.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include "libcproject.h"
#include "test.h"
void string_test() { void string_test() {
string_get_length_test(); string_get_length_test();
string_to_uppercase_test(); string_to_uppercase_test();
@ -34,78 +27,87 @@ void string_test() {
} }
void string_get_length_test() { void string_get_length_test() {
char *string = "Hello World!"; string_t string = "Hello World!";
size_t string_length = string_get_length(string); size_t string_length = string_get_length(string);
assert(string_length == 12); assert(string_length == 12);
} }
void string_to_uppercase_test() { void string_to_uppercase_test() {
char *string = "heLlO world"; string_t string = "heLlO world";
string = string_to_uppercase(string); string = string_to_uppercase(string);
assert(assert_string_equal(string, "HELLO WORLD")); assert(assert_string_equal(string, "HELLO WORLD"));
free(string);
} }
void string_to_lowercase_test() { void string_to_lowercase_test() {
char *string = "HellO WoRLd"; string_t string = "HellO WoRLd";
string = string_to_lowercase(string); string = string_to_lowercase(string);
assert(assert_string_equal(string, "hello world")); assert(assert_string_equal(string, "hello world"));
free(string);
} }
void string_replace_test() { void string_replace_test() {
char *string = "hello world"; string_t string = "hello world";
string = string_replace(string, 'l', 'z'); string = string_replace(string, 'l', 'z');
assert(assert_string_equal(string, "hezzo worzd")); assert(assert_string_equal(string, "hezzo worzd"));
free(string);
} }
void string_trim_start_test() { void string_trim_start_test() {
char *string = " hello world "; string_t string = " hello world ";
string = string_trim_start(string); string = string_trim_start(string, ' ');
assert(assert_string_equal(string, "hello world ")); assert(assert_string_equal(string, "hello world "));
free(string);
} }
void string_trim_end_test() { void string_trim_end_test() {
char *string = " hello world "; string_t string = " hello world ";
string = string_trim_end(string); string = string_trim_end(string, ' ');
assert(assert_string_equal(string, " hello world")); assert(assert_string_equal(string, " hello world"));
free(string);
} }
void string_trim_test() { void string_trim_test() {
char *string = " hello world "; string_t string = " hello world ";
string = string_trim(string); string = string_trim(string, ' ');
assert(assert_string_equal(string, "hello world")); assert(assert_string_equal(string, "hello world"));
free(string);
} }
void string_copy_test() { void string_copy_test() {
char *string = "hello world"; string_t string = "hello world";
char *string2 = string_copy(string); string_t string2 = string_copy(string);
assert(assert_string_equal(string, string2)); assert(assert_string_equal(string, string2));
string2[0] = 'a'; string2[0] = 'a';
assert(assert_string_not_equal(string, string2)); assert(assert_string_not_equal(string, string2));
assert(assert_string_equal(string, "hello world")); assert(assert_string_equal(string, "hello world"));
assert(assert_string_equal(string2, "aello world")); assert(assert_string_equal(string2, "aello world"));
free(string2);
} }
void string_capitalize_test() { void string_capitalize_test() {
char *string = "hello world"; string_t string = "hello world";
string = string_capitalize(string); string = string_capitalize(string);
assert(assert_string_equal(string, "Hello world")); assert(assert_string_equal(string, "Hello world"));
free(string);
} }
void string_total_occurrences_of_character_test() { void string_total_occurrences_of_character_test() {
char *string = "hello world"; string_t string = "hello world";
assert(string_total_occurrences_of_character(string, 'l') == 3); assert(string_total_occurrences_of_character(string, 'l') == 3);
} }
void string_reverse_test() { void string_reverse_test() {
char *string = "hello world"; string_t string = "hello world";
string = string_reverse(string); string = string_reverse(string);
assert(assert_string_equal(string, "dlrow olleh")); assert(assert_string_equal(string, "dlrow olleh"));
free(string);
} }
void string_equals_test() { void string_equals_test() {
char *string1 = "hello world"; string_t string1 = "hello world";
char *string2 = "dlrow olleh"; string_t string2 = "dlrow olleh";
char *string3 = "dlrow olleh"; string_t string3 = "dlrow olleh";
assert(!string_equals(string1, string2)); assert(!string_equals(string1, string2));
assert(string_equals(string1, string1)); assert(string_equals(string1, string1));
assert(string_equals(string2, string3)); assert(string_equals(string2, string3));
@ -124,29 +126,44 @@ void string_get_is_integer_test() {
} }
void string_split_test() { void string_split_test() {
char *string = "abc def ghij kl"; string_t string = "abc def ghij kl";
size_t result_length = 0; size_t result_length = 0;
char **result = string_split(string, ' ', &result_length); string_t* result = string_split(string, ' ', &result_length);
assert(result_length == 4); assert(result_length == 4);
assert(assert_string_equal(result[0], "abc")); assert(assert_string_equal(result[0], "abc"));
assert(assert_string_equal(result[1], "def")); assert(assert_string_equal(result[1], "def"));
assert(assert_string_equal(result[2], "ghij")); assert(assert_string_equal(result[2], "ghij"));
assert(assert_string_equal(result[3], "kl")); assert(assert_string_equal(result[3], "kl"));
for (size_t index = 0; index < result_length; index++) {
free(result[index]);
}
free(result);
} }
void string_join_test() { void string_join_test() {
char *string = "abc def ghij kl"; string_t string = "abc def ghij kl";
size_t result_length = 0; size_t result_length = 0;
char **result = string_split(string, ' ', &result_length); string_t* result = string_split(string, ' ', &result_length);
char *new_string = string_join(result, ' ', result_length); string_t new_string = string_join(result, ' ', result_length);
char *new_string2 = string_join(result, '+', result_length); string_t new_string2 = string_join(result, '+', result_length);
assert(assert_string_equal(new_string, string)); assert(assert_string_equal(new_string, string));
assert(assert_string_equal(new_string2, "abc+def+ghij+kl")); assert(assert_string_equal(new_string2, "abc+def+ghij+kl"));
free(new_string);
free(new_string2);
for (size_t index = 0; index < result_length; index++) {
free(result[index]);
}
free(result);
} }
void string_concatenate_test() { void string_concatenate_test() {
assert(assert_string_equal(string_concatenate("abc", "def"), "abcdef")); char* result = string_concatenate("abc", "def");
assert(assert_string_equal(string_concatenate("abc ", " defghi"), "abc defghi")); assert(assert_string_equal(result, "abcdef"));
free(result);
result = string_concatenate("abc", " defghi");
assert(assert_string_equal(result, "abc defghi"));
free(result);
} }
void string_get_has_unique_characters_test() { void string_get_has_unique_characters_test() {
@ -156,13 +173,14 @@ void string_get_has_unique_characters_test() {
} }
void string_substring_test() { void string_substring_test() {
char *string = "abcdef"; string_t string = "abcdef";
char *substring = string_substring(string, 1, 3); string_t substring = string_substring(string, 1, 3);
assert(assert_string_equal(substring, "bcd")); assert(assert_string_equal(substring, "bcd"));
free(substring);
} }
void string_get_is_substring_test() { void string_get_is_substring_test() {
char *string = "abcdef"; string_t string = "abcdef";
assert(string_get_is_substring(string, "abc")); assert(string_get_is_substring(string, "abc"));
assert(string_get_is_substring(string, "bcd")); assert(string_get_is_substring(string, "bcd"));
assert(string_get_is_substring(string, "de")); assert(string_get_is_substring(string, "de"));
@ -174,33 +192,61 @@ void string_get_is_substring_test() {
} }
void string_get_formatted_number_test() { void string_get_formatted_number_test() {
assert(assert_string_equal(string_get_formatted_number(1000, " "), "1 000")); char* result = string_get_formatted_number(1000, " ");
assert(assert_string_equal(string_get_formatted_number(123, ","), "123")); assert(assert_string_equal(result, "1 000"));
assert(assert_string_equal(string_get_formatted_number(1234, ","), "1,234")); free(result);
assert(assert_string_equal(string_get_formatted_number(12345, ","), "12,345"));
assert(assert_string_equal(string_get_formatted_number(123456, ","), "123,456")); result = string_get_formatted_number(123, ",");
assert(assert_string_equal(string_get_formatted_number(1234567, ","), "1,234,567")); assert(assert_string_equal(result, "123"));
assert(assert_string_equal(string_get_formatted_number(12345678, ","), "12,345,678")); free(result);
assert(assert_string_equal(string_get_formatted_number(123456789, ","), "123,456,789"));
assert(assert_string_equal(string_get_formatted_number(1234567890, ","), "1,234,567,890")); result = string_get_formatted_number(1234, ",");
assert(assert_string_equal(string_get_formatted_number(-123, ","), "-123")); assert(assert_string_equal(result, "1,234"));
assert(assert_string_equal(string_get_formatted_number(-1234, ","), "-1,234")); free(result);
assert(assert_string_equal(string_get_formatted_number(-12345, ","), "-12,345"));
assert(assert_string_equal(string_get_formatted_number(-123456, ","), "-123,456")); result = string_get_formatted_number(12345, ",");
assert(assert_string_equal(string_get_formatted_number(-1234567, ","), "-1,234,567")); assert(assert_string_equal(result, "12,345"));
assert(assert_string_equal(string_get_formatted_number(-12345678, ","), "-12,345,678")); free(result);
assert(assert_string_equal(string_get_formatted_number(-123456789, ","), "-123,456,789"));
assert(assert_string_equal(string_get_formatted_number(-1234567890, ","), "-1,234,567,890")); result = string_get_formatted_number(-123, ",");
assert(assert_string_equal(result, "-123"));
free(result);
result = string_get_formatted_number(-1234, ",");
assert(assert_string_equal(result, "-1,234"));
free(result);
result = string_get_formatted_number(-1234567890, ",");
assert(assert_string_equal(result, "-1,234,567,890"));
free(result);
} }
void string_get_last_occurence_of_character_test() { void string_get_last_occurence_of_character_test() {
char *string = "abcdef"; string_t string = "abcdef";
assert(assert_string_equal(string_get_last_occurence_of_character(string, 'a'), "abcdef"));
assert(assert_string_equal(string_get_last_occurence_of_character(string, 'b'), "bcdef")); char* result = string_get_last_occurence_of_character(string, 'a');
assert(assert_string_equal(string_get_last_occurence_of_character(string, 'c'), "cdef")); assert(assert_string_equal(result, "abcdef"));
assert(assert_string_equal(string_get_last_occurence_of_character(string, 'd'), "def")); free(result);
assert(assert_string_equal(string_get_last_occurence_of_character(string, 'e'), "ef"));
assert(assert_string_equal(string_get_last_occurence_of_character(string, 'f'), "f")); result = string_get_last_occurence_of_character(string, 'b');
assert(assert_string_equal(result, "bcdef"));
free(result);
result = string_get_last_occurence_of_character(string, 'c');
assert(assert_string_equal(result, "cdef"));
free(result);
result = string_get_last_occurence_of_character(string, 'd');
assert(assert_string_equal(result, "def"));
free(result);
result = string_get_last_occurence_of_character(string, 'e');
assert(assert_string_equal(result, "ef"));
free(result);
result = string_get_last_occurence_of_character(string, 'f');
assert(assert_string_equal(result, "f"));
free(result);
} }
void string_starts_with_test() { void string_starts_with_test() {

View File

@ -1,6 +1,13 @@
#ifndef __STRING_TEST__ #ifndef __STRING_TEST__
#define __STRING_TEST__ #define __STRING_TEST__
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include "libcproject.h"
#include "test.h"
void string_test(); void string_test();
void string_get_length_test(); void string_get_length_test();

View File

@ -1,8 +1,6 @@
#include <stdbool.h> #include "test.h"
#include <stdio.h>
#include <string.h>
bool assert_string_equal(const char *actual, const char *expected) { bool assert_string_equal(const string_t actual, const string_t expected) {
if (strcmp(expected, actual) != 0) { if (strcmp(expected, actual) != 0) {
printf("FAIL: expected = \"%s\" ; actual = \"%s\"\n", expected, actual); printf("FAIL: expected = \"%s\" ; actual = \"%s\"\n", expected, actual);
return false; return false;
@ -10,7 +8,7 @@ bool assert_string_equal(const char *actual, const char *expected) {
return true; return true;
} }
bool assert_string_not_equal(const char *actual, const char *expected) { bool assert_string_not_equal(const string_t actual, const string_t expected) {
if (strcmp(expected, actual) == 0) { if (strcmp(expected, actual) == 0) {
printf("FAIL: expected = \"%s\" ; actual = \"%s\"\n", expected, actual); printf("FAIL: expected = \"%s\" ; actual = \"%s\"\n", expected, actual);
return false; return false;

View File

@ -2,9 +2,13 @@
#define __TEST__ #define __TEST__
#include <stdbool.h> #include <stdbool.h>
#include <stdio.h>
#include <string.h>
bool assert_string_equal(const char *actual, const char *expected); #include "libcproject.h"
bool assert_string_not_equal(const char *actual, const char *expected); bool assert_string_equal(const string_t actual, const string_t expected);
bool assert_string_not_equal(const string_t actual, const string_t expected);
#endif #endif

View File

@ -1,4 +1,4 @@
#ifndef __LIBCPROJECT_VERSION__ #ifndef __LIBCPROJECT_VERSION__
#define __LIBCPROJECT_VERSION__ "1.1.2" #define __LIBCPROJECT_VERSION__ "3.0.0"
#endif #endif