1
1
mirror of https://github.com/theoludwig/libcproject.git synced 2024-12-11 21:13:00 +01:00

Compare commits

..

No commits in common. "develop" and "v1.1.0" have entirely different histories.

76 changed files with 888 additions and 3791 deletions

View File

@ -1,2 +1,2 @@
BasedOnStyle: "Google" BasedOnStyle: 'Google'
ColumnLimit: 0 ColumnLimit: 0

View File

@ -1,8 +1,8 @@
--- ---
name: "🐛 Bug Report" name: '🐛 Bug Report'
about: "Report an unexpected problem or unintended behavior." about: 'Report an unexpected problem or unintended behavior.'
title: "[Bug]" title: '[Bug]'
labels: "bug" labels: 'bug'
--- ---
<!-- <!--

View File

@ -1,8 +1,8 @@
--- ---
name: "📜 Documentation" name: '📜 Documentation'
about: "Correct spelling errors, improvements or additions to documentation files (README, CONTRIBUTING...)." about: 'Correct spelling errors, improvements or additions to documentation files (README, CONTRIBUTING...).'
title: "[Documentation]" title: '[Documentation]'
labels: "documentation" labels: 'documentation'
--- ---
<!-- Please make sure your issue has not already been fixed. --> <!-- Please make sure your issue has not already been fixed. -->

View File

@ -1,8 +1,8 @@
--- ---
name: "✨ Feature Request" name: '✨ Feature Request'
about: "Suggest a new feature idea." about: 'Suggest a new feature idea.'
title: "[Feature]" title: '[Feature]'
labels: "feature request" labels: 'feature request'
--- ---
<!-- Please make sure your issue has not already been fixed. --> <!-- Please make sure your issue has not already been fixed. -->

View File

@ -1,8 +1,8 @@
--- ---
name: "🔧 Improvement" name: '🔧 Improvement'
about: "Improve structure/format/performance/refactor/tests of the code." about: 'Improve structure/format/performance/refactor/tests of the code.'
title: "[Improvement]" title: '[Improvement]'
labels: "improvement" labels: 'improvement'
--- ---
<!-- Please make sure your issue has not already been fixed. --> <!-- Please make sure your issue has not already been fixed. -->

View File

@ -1,8 +1,8 @@
--- ---
name: "🙋 Question" name: '🙋 Question'
about: "Further information is requested." about: 'Further information is requested.'
title: "[Question]" title: '[Question]'
labels: "question" labels: 'question'
--- ---
### Question ### Question

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

@ -1,40 +1,31 @@
name: "CI" name: 'CI'
on: on:
push: push:
branches: [develop] branches: [develop]
pull_request: pull_request:
branches: [main, develop] branches: [master, develop]
jobs: jobs:
ci: ci:
runs-on: "ubuntu-latest" runs-on: 'ubuntu-latest'
steps: steps:
- uses: "actions/checkout@v4.1.7" - uses: 'actions/checkout@v3.0.0'
- run: "sudo apt update" - name: 'Install Build Tools'
run: 'sudo apt-get install --yes build-essential gcc make clang-format'
- name: "Install Build Tools" - run: 'make'
run: "sudo apt install --yes build-essential gcc make clang-format" - run: 'make run'
- run: 'make test'
- name: "Install Documentation Tools" - run: 'make lint'
run: "sudo apt install --yes doxygen doxygen-gui doxygen-doc graphviz" - run: 'make clean'
- run: "gcc --version"
- run: "make"
- run: "make run"
- run: "make test"
- run: "make lint"
- run: "make documentation"
- run: "make set_version"
- run: "make clean"
lint-commit: lint-commit:
runs-on: "ubuntu-latest" runs-on: 'ubuntu-latest'
steps: steps:
- uses: "actions/checkout@v4.1.7" - uses: 'actions/checkout@v3.0.0'
with: with:
fetch-depth: 0 fetch-depth: 0
- uses: "wagoid/commitlint-github-action@v6.1.2" - uses: 'wagoid/commitlint-github-action@v5.3.0'

View File

@ -1,57 +1,51 @@
name: "Release" name: 'Release'
on: on:
push: push:
branches: [main] branches: [master]
jobs: jobs:
release: release:
runs-on: "ubuntu-latest" runs-on: 'ubuntu-latest'
steps: steps:
- uses: "actions/checkout@v4.1.7" - uses: 'actions/checkout@v3.1.0'
with: with:
fetch-depth: 0 fetch-depth: 0
persist-credentials: false persist-credentials: false
submodules: "recursive"
- name: "Import GPG key" - name: 'Import GPG key'
uses: "crazy-max/ghaction-import-gpg@v6.1.0" uses: 'crazy-max/ghaction-import-gpg@v4'
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'
run: 'sudo apt-get install --yes build-essential gcc make clang-format doxygen doxygen-gui doxygen-doc graphviz'
- name: "Install Build Tools" - run: 'make set_version'
run: "sudo apt install --yes build-essential gcc make clang-format"
- name: "Install Documentation Tools" - name: 'Generate Documentation'
run: "sudo apt install --yes doxygen doxygen-gui doxygen-doc graphviz" run: 'make documentation'
- run: "make set_version" - name: 'Use Node.js'
uses: 'actions/setup-node@v3.1.0'
- name: "Use Node.js"
uses: "actions/setup-node@v4.0.3"
with: with:
node-version: "20.17.0" node-version: 'lts/*'
- name: "Install Release Tools" - name: 'Install Release Tools'
run: "npm install --save-dev semantic-release@23.1.1 @commitlint/cli@19.5.0 @commitlint/config-conventional@19.5.0 @semantic-release/git@10.0.1 @semantic-release/exec@6.0.3 @saithodev/semantic-release-backmerge@4.0.1 vercel@37.4.2" run: 'npm install --save-dev semantic-release @commitlint/cli @commitlint/config-conventional @semantic-release/git @semantic-release/exec @saithodev/semantic-release-backmerge vercel'
- run: "rm --force package.json package-lock.json" - run: 'rm --force package.json package-lock.json'
- name: "Release" - name: 'Release'
run: "npx semantic-release" run: 'npx semantic-release'
env: env:
GH_TOKEN: ${{ secrets.GH_TOKEN }} GH_TOKEN: ${{ secrets.GH_TOKEN }}
GIT_COMMITTER_NAME: ${{ secrets.GIT_NAME }} GIT_COMMITTER_NAME: ${{ secrets.GIT_NAME }}
GIT_COMMITTER_EMAIL: ${{ secrets.GIT_EMAIL }} GIT_COMMITTER_EMAIL: ${{ secrets.GIT_EMAIL }}
- name: "Generate Documentation" - name: 'Deploy to Vercel'
run: "make documentation"
- name: "Deploy to Vercel"
run: 'npx vercel ./documentation/html --token="${VERCEL_TOKEN}" --prod' run: 'npx vercel ./documentation/html --token="${VERCEL_TOKEN}" --prod'
env: env:
VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }} VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}

3
.gitignore vendored
View File

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

View File

@ -1,5 +1,5 @@
{ {
"branches": ["main"], "branches": ["master"],
"plugins": [ "plugins": [
[ [
"@semantic-release/commit-analyzer", "@semantic-release/commit-analyzer",
@ -16,7 +16,7 @@
[ [
"@semantic-release/exec", "@semantic-release/exec",
{ {
"prepareCmd": "make set_version && ./bin/set_version ${nextRelease.version}" "prepareCmd": "make set_version && ./bin/set_version.exe ${nextRelease.version}"
} }
], ],
[ [
@ -30,7 +30,7 @@
[ [
"@saithodev/semantic-release-backmerge", "@saithodev/semantic-release-backmerge",
{ {
"branches": [{ "from": "main", "to": "develop" }], "branches": [{ "from": "master", "to": "develop" }],
"backmergeStrategy": "merge" "backmergeStrategy": "merge"
} }
] ]

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@theoludwig.fr>. contact@divlo.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,14 +2,6 @@
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.
@ -19,7 +11,7 @@ All work on **libcproject** happens directly on this repository. Both core team
## Pull Requests ## Pull Requests
- **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. - **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.
- Ensure your code respect linting. - Ensure your code respect linting.
@ -29,19 +21,26 @@ If you're adding new features to **libcproject**, please include tests.
## Commits ## Commits
The commit message guidelines adheres to [Conventional Commits](https://www.conventionalcommits.org/) and [Semantic Versioning](https://semver.org/) for releases. 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.
## Git Submodules ### Types
To get the submodule: Types define which kind of changes you made to the project.
```sh | Types | Description |
git submodule update --init --recursive | -------- | ------------------------------------------------------------------------------------------------------------ |
``` | 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. |
To update the version: ### Scopes
```sh Scopes define what part of the code changed.
cd doxygen-awesome-css
git checkout v2.3.3
```

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,14 +8,11 @@ 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
EXCLUDE = test doxygen-awesome-css node_modules EXCLUDE = test doxygen-awesome-css
GENERATE_LATEX = NO GENERATE_LATEX = NO
GENERATE_TREEVIEW = YES GENERATE_TREEVIEW = YES
EXAMPLE_PATTERNS = * EXAMPLE_PATTERNS = *

View File

@ -1,6 +1,6 @@
# MIT License MIT License
Copyright (c) Théo LUDWIG <contact@theoludwig.fr> Copyright (c) Divlo
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,7 +1,6 @@
LIBRARY_NAME = libcproject LIBRARY_NAME = libcproject
CC = gcc CC = gcc
CC_FLAGS = -Wall -Wextra -Wfloat-equal -Wundef -Werror -std=c17 -pedantic -pedantic-errors -O3 -I./ CC_FLAGS = -Wall -Wextra -Wfloat-equal -Wundef -Werror -std=c17 -pedantic -pedantic-errors -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)
@ -9,42 +8,34 @@ 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 MAIN_EXECUTABLE = bin/main.exe
SET_VERSION_EXECUTABLE = bin/set_version SET_VERSION_EXECUTABLE = bin/set_version.exe
TEST_EXECUTABLE = bin/test TEST_EXECUTABLE = bin/test.exe
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
${CC} ${CC_FLAGS} ${CC_SANITIZER_FLAGS} -o ${MAIN_EXECUTABLE} ./main.c ${LIB_CC_FLAGS} ${CC} ${CC_FLAGS} -o ${MAIN_EXECUTABLE} ./main.c ${LIB_CC_FLAGS}
./${MAIN_EXECUTABLE} ${ARGS} ./${MAIN_EXECUTABLE} ${ARGS}
.PHONY: set_version .PHONY: set_version
set_version: ${LIB} ./set_version.c set_version: ${LIB} ./set_version.c
mkdir --parents ./bin mkdir --parents ./bin
${CC} ${CC_FLAGS} ${CC_SANITIZER_FLAGS} -o ${SET_VERSION_EXECUTABLE} ./set_version.c ${LIB_CC_FLAGS} ${CC} ${CC_FLAGS} -o ${SET_VERSION_EXECUTABLE} ./set_version.c ${LIB_CC_FLAGS}
.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} ${CC_SANITIZER_FLAGS} -o ${TEST_EXECUTABLE} $(addprefix build/, ${TEST_OBJECTS}) ${LIB_CC_FLAGS} ${CC} ${CC_FLAGS} -o ${TEST_EXECUTABLE} $(addprefix build/, ${TEST_OBJECTS}) ${LIB_CC_FLAGS}
./${TEST_EXECUTABLE} ${ARGS} ./${TEST_EXECUTABLE}
.PHONY: lint .PHONY: lint
lint: lint:

View File

@ -5,11 +5,11 @@
</p> </p>
<p align="center"> <p align="center">
<a href="./CONTRIBUTING.md"><img src="https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat" alt="Contributing" /></a> <a href="./CONTRIBUTING.md"><img src="https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat" /></a>
<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/theoludwig/libcproject/actions/workflows/ci.yml"><img src="https://github.com/theoludwig/libcproject/actions/workflows/ci.yml/badge.svg?branch=develop" alt="CI" /></a> <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://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 (`hash_map`, `array_list`, `linked_list`, `queue`, `stack`, etc.), we might need in our C projects. **libcproject** solve this by providing common functions or data structures (`dictionary`, `linked_list`, `queue`, `stack`, etc.) we might need in our C projects.
[Online documentation](https://libcproject.vercel.app/). [Online documentation](https://libcproject.vercel.app/).
@ -30,17 +30,14 @@ C is a low-level programming language and we often end up reinventing the wheel
- [GNU binutils](https://www.gnu.org/software/binutils/) - [GNU binutils](https://www.gnu.org/software/binutils/)
- [GNU gcc](https://gcc.gnu.org/) - [GNU gcc](https://gcc.gnu.org/)
- [GNU make](https://www.gnu.org/software/make/) - [GNU make](https://www.gnu.org/software/make/)
- [ClangFormat](https://clang.llvm.org/docs/ClangFormat.html) - [clang-format](https://clang.llvm.org/docs/ClangFormat.html)
- [Doxygen](https://www.doxygen.nl/) - [Doxygen](https://www.doxygen.nl/)
For example on GNU/Linux Ubuntu: For example on GNU/Linux Ubuntu:
```sh ```sh
# Install Build Tools sudo apt-get install build-essential gcc make clang-format
sudo apt install build-essential gcc make clang-format sudo apt-get install doxygen doxygen-gui doxygen-doc graphviz
# Install Documentation Tools
sudo apt install doxygen doxygen-gui doxygen-doc graphviz
``` ```
## Usage ## Usage
@ -58,30 +55,31 @@ 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: Create a new project ### Step 1: Compile `libcproject`
```sh
make
```
### Step 2: Create a new project
```sh ```sh
mkdir my-project mkdir my-project
cd my-project cd my-project
``` ```
### Step 2: Install and Compile `libcproject` in the project ### Step 3: Install `libcproject` in the project
```sh ```sh
# Clone the repository mkdir libcproject
git clone git@github.com:theoludwig/libcproject.git cp --recursive <path-to-libcproject> ./ # copy
# or
# Go to libcproject directory ln -s <path-to-libcproject> ./ # symbolic link
cd libcproject
# Compile the library
make
``` ```
### Step 3: Create a new C file ### Step 4: Create a new C file
```sh ```sh
cd ..
touch main.c touch main.c
``` ```
@ -92,17 +90,17 @@ touch main.c
#include "libcproject/libcproject.h" #include "libcproject/libcproject.h"
int main() { int main() {
string_t string = "Hello, world!"; // `string_t` is a typedef from `libcproject` char* string = "Hello, world!";
printf("%s\n", string); printf("%s\n", string);
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)); // `string_get_length` is a function from `libcproject`
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
``` ```
### Step 4: 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 ./main.c -L. -l:./libcproject/build/libcproject.a gcc -o ./main.exe ./main.c -L. -l:./libcproject/build/libcproject.a
``` ```
## 💡 Contributing ## 💡 Contributing

@ -1 +1 @@
Subproject commit 40e9b25b6174dd3b472d8868f63323a870dfeeb8 Subproject commit a3c119b4797be2039761ec1fa0731f038e3026f6

View File

@ -1,61 +0,0 @@
#include "array_list.h"
struct array_list* array_list_initialization() {
return array_list_initialization_with_capacity(ARRAY_LIST_INITIAL_CAPACITY);
}
struct array_list* array_list_initialization_with_capacity(size_t capacity) {
struct array_list* list = malloc(sizeof(struct array_list));
if (list == NULL) {
perror("Error (array_list_initialization)");
exit(EXIT_FAILURE);
}
list->size = 0;
list->capacity = capacity;
list->capacity_step = capacity;
list->data = malloc(sizeof(void*) * list->capacity);
if (list->data == NULL) {
perror("Error (array_list_initialization)");
exit(EXIT_FAILURE);
}
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 += list->capacity_step;
list->data = realloc(list->data, sizeof(void*) * list->capacity);
if (list->data == NULL) {
perror("Error (array_list_add)");
exit(EXIT_FAILURE);
}
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; i < list->size - 1; i++) {
list->data[i] = list->data[i + 1];
}
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);
}

View File

@ -1,72 +0,0 @@
#ifndef __LIBCPROJECT_ARRAY_LIST__
#define __LIBCPROJECT_ARRAY_LIST__
#include <errno.h>
#include <stdbool.h>
#include <stdio.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;
size_t capacity_step;
};
/**
* @brief Initializes a new array list.
* @since v1.2.0
*/
struct array_list* array_list_initialization();
/**
* @brief Initializes a new array list with a capacity.
* @since v5.0.0
*/
struct array_list* array_list_initialization_with_capacity(size_t capacity);
/**
* @brief Adds an element to the end of the array list.
*
* @param list
* @param element
* @since v1.2.0
*/
void array_list_add(struct array_list* list, void* element);
/**
* @brief Removes an element from the array list.
*
* @param list
* @param index
* @since v1.2.0
*/
void array_list_remove(struct array_list* list, size_t index);
/**
* @brief Gets an element from the array list.
*
* @param list
* @param index
* @return void*
* @since v1.2.0
*/
void* array_list_get(struct array_list* list, size_t index);
/**
* @brief Frees the array list.
*
* @param list
* @since v3.0.0
*/
void array_list_free(struct array_list* list);
#endif

View File

@ -1,17 +0,0 @@
#include "assert.h"
bool assert_string_equal(const string_t actual, const string_t expected) {
if (!string_equals(actual, expected)) {
printf("FAIL: expected = \"%s\" ; actual = \"%s\"\n", expected, actual);
return false;
}
return true;
}
bool assert_string_not_equal(const string_t actual, const string_t expected) {
if (string_equals(actual, expected)) {
printf("FAIL: expected = \"%s\" ; actual = \"%s\"\n", expected, actual);
return false;
}
return true;
}

View File

@ -1,30 +0,0 @@
#ifndef __LIBCPROJECT_ASSERT__
#define __LIBCPROJECT_ASSERT__
#include <assert.h>
#include <errno.h>
#include <stdbool.h>
#include <stdlib.h>
#include "string.h"
#include "types.h"
/**
* @brief Check if the two strings are equal. If they are not equal, print the expected and actual strings.
*
* @param character
* @return bool
* @since v5.0.0
*/
bool assert_string_equal(const string_t actual, const string_t expected);
/**
* @brief Check if the two strings are not equal. If they are equal, print the expected and actual strings.
*
* @param character
* @return bool
* @since v5.0.0
*/
bool assert_string_not_equal(const string_t actual, const string_t expected);
#endif

View File

@ -1,11 +1,16 @@
#include "character.h" #include "character.h"
void character_append(string_t string, const char character) { #include <stdbool.h>
#include <stdlib.h>
#include "string.h"
void character_append(char* string, const char character) {
size_t length = string_get_length(string); size_t length = string_get_length(string);
character_append_at(string, character, length); character_append_at(string, character, length);
} }
void character_append_at(string_t string, const char character, const size_t index) { void character_append_at(char* string, const char character, const size_t index) {
size_t length = string_get_length(string); size_t length = string_get_length(string);
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[index_string] = string[index_string - 1];
@ -32,9 +37,9 @@ bool character_get_is_digit(const char character) {
return character >= '0' && character <= '9'; return character >= '0' && character <= '9';
} }
uint8_t character_get_alphabet_position(const char character) { unsigned char character_get_alphabet_position(const char character) {
const char letter = character_to_lower(character); const char letter = character_to_lower(character);
uint8_t position = 0; unsigned char position = 0;
if (letter >= 'a' && letter <= 'z') { if (letter >= 'a' && letter <= 'z') {
position = (letter - 'a') + 1; position = (letter - 'a') + 1;
} }

View File

@ -1,22 +1,17 @@
#ifndef __LIBCPROJECT_CHARACTER__ #ifndef __CHARACTER__
#define __LIBCPROJECT_CHARACTER__ #define __CHARACTER__
#include <errno.h>
#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
* @param character * @param character
* @since v1.0.0
*/ */
void character_append(string_t string, char character); void character_append(char* string, 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.
@ -24,15 +19,14 @@ void character_append(string_t string, char character);
* @param string * @param string
* @param character * @param character
* @param index * @param index
* @since v1.0.0
*/ */
void character_append_at(string_t string, const char character, const size_t index); void character_append_at(char* string, const char character, const size_t index);
/** /**
* @brief Converts the character to uppercase. * @brief Converts the character to uppercase.
* *
* @param character * @param character
* @since v1.0.0 * @return const char
*/ */
char character_to_upper(const char character); char character_to_upper(const char character);
@ -40,16 +34,16 @@ char character_to_upper(const char character);
* @brief Converts the character to lowercase. * @brief Converts the character to lowercase.
* *
* @param character * @param character
* @since v1.0.0 * @return const char
*/ */
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 character * @param string1
* @return bool * @param string2
* @since v1.0.0 * @return true if the character is a digit, false otherwise
*/ */
bool character_get_is_digit(const char character); bool character_get_is_digit(const char character);
@ -58,9 +52,8 @@ 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 uint8_t * @return char
* @since v1.0.0
*/ */
uint8_t character_get_alphabet_position(const char character); unsigned char character_get_alphabet_position(const char character);
#endif #endif

View File

@ -1,13 +1,19 @@
#include "convert.h" #include "convert.h"
string_t convert_character_to_string(const char character) { #include <stdio.h>
string_t string = malloc(sizeof(char) * 2); #include <stdlib.h>
#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) {
perror("Error (convert_character_to_string)");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
string[0] = character; character_append(string, character);
string[1] = '\0';
return string; return string;
} }
@ -19,9 +25,9 @@ char convert_digit_to_character(const char digit) {
return digit + '0'; return digit + '0';
} }
int64_t convert_string_to_number(const string_t string) { long long convert_string_to_number(const char* string) {
bool is_negative = string[0] == '-'; bool is_negative = string[0] == '-';
int64_t integer = 0; long long integer = 0;
size_t length = string_get_length(string); size_t length = string_get_length(string);
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[index]);
@ -29,54 +35,46 @@ int64_t convert_string_to_number(const string_t string) {
return is_negative ? integer * -1 : integer; return is_negative ? integer * -1 : integer;
} }
string_t convert_number_to_string(const int64_t integer) { char* 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;
int64_t current = mathematics_absolute_value(integer); char* string = malloc(sizeof(char*) * length);
while (current != 0) {
current = current / 10;
length++;
}
if (is_negative) {
length++;
}
string_t string = malloc(sizeof(char) * length);
if (string == NULL) { if (string == NULL) {
perror("Error (convert_number_to_string)");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
current = mathematics_absolute_value(integer); long long current = mathematics_absolute_value(integer);
size_t index = 0;
while (current != 0) { while (current != 0) {
string[index++] = convert_digit_to_character(current % 10); character_append(string, convert_digit_to_character(current % 10));
current = current / 10; current = current / 10;
length++;
string = realloc(string, sizeof(char*) * length);
} }
if (is_negative) { if (is_negative) {
string[index++] = '-'; character_append(string, '-');
length++;
string = realloc(string, sizeof(char*) * length);
} }
string[index] = '\0'; return string_reverse(string);
string_reverse(string);
return string;
} }
string_t convert_number_from_base_10_to_base(uint64_t number, uint64_t base) { char* convert_number_from_base_10_to_base(unsigned long long number, unsigned int base) {
if (number == 0) { if (number == 0) {
return "0"; return "0";
} }
int64_t remainders[64]; int remainders[64];
int64_t index = 0; int index = 0;
while (number > 0) { while (number > 0) {
remainders[index] = number % base; remainders[index] = number % base;
number = number / base; number = number / base;
index++; index++;
} }
string_t result = malloc(sizeof(char) * (index + 1)); char* result = malloc(sizeof(char) * (index + 1));
int64_t index_result = 0; int index_result = 0;
for (int64_t iteration = index - 1; iteration >= 0; iteration--) { for (int iteration = index - 1; iteration >= 0; iteration--) {
int64_t remainder = remainders[iteration]; int remainder = remainders[iteration];
if (remainder >= 10) { if (remainder >= 10) {
result[index_result] = (char)((remainder - 10) + 'A'); result[index_result] = (char)((remainder - 10) + 'A');
} else { } else {
@ -84,21 +82,20 @@ string_t convert_number_from_base_10_to_base(uint64_t number, uint64_t base) {
} }
index_result++; index_result++;
} }
result[index_result] = '\0';
return result; return result;
} }
uint64_t convert_number_from_base_to_base_10(string_t number, uint64_t base) { int convert_number_from_base_to_base_10(char* number, unsigned int base) {
size_t length = string_get_length(number); int length = string_get_length(number);
int64_t exponent = length - 1; int exponent = length - 1;
uint64_t result = 0; int result = 0;
int64_t index = 0; int index = 0;
while (exponent >= 0) { while (exponent >= 0) {
int64_t current_number = (int64_t)(number[index] - '0'); int current_number = (int)(number[index] - '0');
if (current_number >= 10) { if (current_number >= 10) {
current_number = (int64_t)(number[index] - 'A') + 10; current_number = (int)(number[index] - 'A') + 10;
} else { } else {
current_number = (int64_t)(number[index] - '0'); current_number = (int)(number[index] - '0');
} }
result = result + current_number * mathematics_pow(base, exponent); result = result + current_number * mathematics_pow(base, exponent);
exponent--; exponent--;
@ -107,6 +104,6 @@ uint64_t convert_number_from_base_to_base_10(string_t number, uint64_t base) {
return result; return result;
} }
string_t convert_number_from_base_to_another(string_t number, uint64_t base_from, uint64_t base_target) { char* convert_number_from_base_to_another(char* 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,90 +1,20 @@
#ifndef __LIBCPROJECT_CONVERT__ #ifndef __CONVERT__
#define __LIBCPROJECT_CONVERT__ #define __CONVERT__
#include <errno.h> 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
* @return string_t
* @since v1.0.0
*/
string_t convert_character_to_string(const char character);
/**
* @brief Convert a character to a digit.
*
* @param character
* @return char
* @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
* @return char
* @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
* @return int64_t
* @since v1.0.0
*/
int64_t convert_string_to_number(const string_t string);
/** char* convert_number_to_string(const long long integer);
* @brief Convert a number to a string.
*
* @param integer
* @return string_t
* @since v1.0.0
*/
string_t convert_number_to_string(const int64_t 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
* @return string_t
* @since v1.0.0
*/
string_t convert_number_from_base_10_to_base(uint64_t number, uint64_t 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
* @return uint64_t
* @since v1.0.0
*/
uint64_t convert_number_from_base_to_base_10(string_t number, uint64_t 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
* @return string_t
* @since v1.0.0
*/
string_t convert_number_from_base_to_another(string_t number, uint64_t base_from, uint64_t base_target);
#endif #endif

View File

@ -1,339 +0,0 @@
#include "date.h"
struct date *date_copy(struct date *date_to_copy) {
struct date *date = malloc(sizeof(struct date));
if (date == NULL) {
perror("Error (date_copy)");
exit(EXIT_FAILURE);
}
date->year = date_to_copy->year;
date->month = date_to_copy->month;
date->day = date_to_copy->day;
date->hours = date_to_copy->hours;
date->minutes = date_to_copy->minutes;
date->seconds = date_to_copy->seconds;
date->milliseconds = date_to_copy->milliseconds;
date->timezone_utc_offset = date_to_copy->timezone_utc_offset;
return date;
}
bool date_get_is_valid_year(uint16_t year) {
return year <= 9999;
}
bool date_get_is_valid_month(uint8_t month) {
return month >= 1 && month <= 12;
}
bool date_get_is_valid_day(uint8_t day) {
return day >= 1 && day <= 31;
}
bool date_get_is_valid_hours(uint8_t hours) {
return hours <= 23;
}
bool date_get_is_valid_minutes(uint8_t minutes) {
return minutes <= 59;
}
bool date_get_is_valid_seconds(uint8_t seconds) {
return seconds <= 59;
}
bool date_get_is_valid_milliseconds(uint16_t milliseconds) {
return milliseconds <= 999;
}
bool date_get_is_valid_timezone_utc_offset(int8_t timezone_utc_offset) {
return timezone_utc_offset >= -12 && timezone_utc_offset <= 14;
}
bool date_get_is_valid(struct date *date) {
size_t date_days_of_month = date_get_days_of_month(date->month, date->year);
return (date_get_is_valid_month(date->month) &&
date_get_is_valid_day(date->day) &&
date->day <= date_days_of_month &&
date_get_is_valid_hours(date->hours) &&
date_get_is_valid_minutes(date->minutes) &&
date_get_is_valid_seconds(date->seconds) &&
date_get_is_valid_milliseconds(date->milliseconds) &&
date_get_is_valid_timezone_utc_offset(date->timezone_utc_offset));
}
string_t date_to_iso_string(struct date *date_original) {
struct date *date = date_copy(date_original);
date_to_utc(date);
size_t iso_string_length = 24;
string_t result = malloc(sizeof(char) * (iso_string_length + 1));
string_t year_string = string_zero_pad(date->year, 4);
string_t month_string = string_zero_pad(date->month, 2);
string_t day_string = string_zero_pad(date->day, 2);
string_t hours_string = string_zero_pad(date->hours, 2);
string_t minutes_string = string_zero_pad(date->minutes, 2);
string_t seconds_string = string_zero_pad(date->seconds, 2);
string_t milliseconds_string = string_zero_pad(date->milliseconds, 3);
sprintf(result, "%s-%s-%sT%s:%s:%s.%sZ", year_string, month_string, day_string, hours_string, minutes_string, seconds_string, milliseconds_string);
free(year_string);
free(month_string);
free(day_string);
free(hours_string);
free(minutes_string);
free(seconds_string);
free(milliseconds_string);
free(date);
return result;
}
string_t date_to_iso_string_without_time(struct date *date) {
size_t iso_string_length = 10;
string_t result = malloc(sizeof(char) * (iso_string_length + 1));
if (result == NULL) {
perror("Error (date_to_iso_string_without_time)");
exit(EXIT_FAILURE);
}
string_t year_string = string_zero_pad(date->year, 4);
string_t month_string = string_zero_pad(date->month, 2);
string_t day_string = string_zero_pad(date->day, 2);
sprintf(result, "%s-%s-%s", year_string, month_string, day_string);
free(year_string);
free(month_string);
free(day_string);
return result;
}
struct date *date_from_iso_string(string_t iso_string) {
struct date *date = malloc(sizeof(struct date));
if (date == NULL) {
perror("Error (date_from_iso_string)");
exit(EXIT_FAILURE);
}
string_t year_string = string_substring(iso_string, 0, 3);
date->year = (uint16_t)convert_string_to_number(year_string);
free(year_string);
string_t month_string = string_substring(iso_string, 5, 6);
date->month = (uint8_t)convert_string_to_number(month_string);
free(month_string);
string_t day_string = string_substring(iso_string, 8, 9);
date->day = (uint8_t)convert_string_to_number(day_string);
free(day_string);
string_t hours_string = string_substring(iso_string, 11, 12);
date->hours = (uint8_t)convert_string_to_number(hours_string);
free(hours_string);
string_t minutes_string = string_substring(iso_string, 14, 15);
date->minutes = (uint8_t)convert_string_to_number(minutes_string);
free(minutes_string);
string_t seconds_string = string_substring(iso_string, 17, 18);
date->seconds = (uint8_t)convert_string_to_number(seconds_string);
free(seconds_string);
string_t milliseconds_string = string_substring(iso_string, 20, 22);
date->milliseconds = (uint16_t)convert_string_to_number(milliseconds_string);
free(milliseconds_string);
date->timezone_utc_offset = 0;
return date;
}
uint8_t date_get_days_of_month(uint8_t month, uint16_t year) {
switch (month) {
case 1:
return 31;
case 2:
return date_get_is_leap_year(year) ? 29 : 28;
case 3:
return 31;
case 4:
return 30;
case 5:
return 31;
case 6:
return 30;
case 7:
return 31;
case 8:
return 31;
case 9:
return 30;
case 10:
return 31;
case 11:
return 30;
case 12:
return 31;
default:
return 0;
}
}
bool date_get_is_leap_year(uint16_t year) {
return (year % 4 == 0 && year % 100 != 0) || year % 400 == 0;
}
uint64_t date_convert_milliseconds_to_seconds(uint16_t milliseconds) {
return milliseconds / MILLISECONDS_PER_SECOND;
}
uint64_t date_convert_seconds_to_milliseconds(uint64_t seconds) {
return seconds * MILLISECONDS_PER_SECOND;
}
uint64_t date_convert_days_to_seconds(uint64_t days) {
return days * SECONDS_PER_DAY;
}
uint64_t date_convert_hms_to_seconds(uint8_t hours, uint8_t minutes, uint8_t seconds) {
return (hours * SECONDS_PER_HOUR) + (minutes * SECONDS_PER_MINUTE) + seconds;
}
uint64_t date_to_total_seconds(struct date *date) {
uint64_t total_seconds = 0;
for (uint16_t year = 0; year < date->year; year++) {
total_seconds += 365 * SECONDS_PER_DAY;
if (date_get_is_leap_year(year)) {
total_seconds += SECONDS_PER_DAY;
}
}
for (uint8_t month = 1; month < date->month; month++) {
total_seconds += date_convert_days_to_seconds(date_get_days_of_month(month, date->year));
}
total_seconds += date_convert_days_to_seconds(date->day - 1);
total_seconds += date_convert_hms_to_seconds(date->hours, date->minutes, date->seconds);
return total_seconds;
}
uint64_t date_duration_seconds_between_2_dates(struct date *date1, struct date *date2) {
struct date *utc_date1 = date_copy(date1);
struct date *utc_date2 = date_copy(date2);
date_to_utc(utc_date1);
date_to_utc(utc_date2);
uint64_t total_seconds_date1 = date_to_total_seconds(utc_date1);
uint64_t total_seconds_date2 = date_to_total_seconds(utc_date2);
free(utc_date1);
free(utc_date2);
return total_seconds_date1 > total_seconds_date2 ? total_seconds_date1 - total_seconds_date2 : total_seconds_date2 - total_seconds_date1;
}
void date_add_hours(struct date *date, int64_t hours) {
if (hours == 0) {
return;
}
int64_t total_hours = date->hours + hours;
int64_t additional_days = total_hours / 24;
int64_t new_hours = total_hours % 24;
if (new_hours < 0) {
new_hours += 24;
additional_days -= 1;
}
date->hours = (uint8_t)new_hours;
if (additional_days != 0) {
date->day += additional_days;
while (date->day > date_get_days_of_month(date->month, date->year)) {
date->day -= date_get_days_of_month(date->month, date->year);
date->month++;
if (date->month > 12) {
date->month = 1;
date->year++;
}
}
while (date->day < 1) {
date->month--;
if (date->month < 1) {
date->month = 12;
date->year--;
}
date->day += date_get_days_of_month(date->month, date->year);
}
}
}
void date_add_days(struct date *date, int64_t days) {
date_add_hours(date, days * 24);
}
void date_to_utc(struct date *date) {
if (date->timezone_utc_offset == 0) {
return;
}
int8_t timezone_utc_offset = date->timezone_utc_offset;
date->timezone_utc_offset = 0;
date_add_hours(date, mathematics_opposite(timezone_utc_offset));
}
struct date *date_get_now_utc() {
struct date *date = malloc(sizeof(struct date));
if (date == NULL) {
perror("Error (date_get_now_utc)");
exit(EXIT_FAILURE);
}
time_t current_time = time(NULL);
struct tm *current_time_tm = gmtime(&current_time);
date->year = (uint16_t)(current_time_tm->tm_year + 1900);
date->month = (uint8_t)(current_time_tm->tm_mon + 1);
date->day = (uint8_t)current_time_tm->tm_mday;
date->hours = (uint8_t)current_time_tm->tm_hour;
date->minutes = (uint8_t)current_time_tm->tm_min;
date->seconds = (uint8_t)current_time_tm->tm_sec;
date->milliseconds = 0;
date->timezone_utc_offset = 0;
return date;
}
struct date *date_get_now_local() {
struct date *date = malloc(sizeof(struct date));
if (date == NULL) {
perror("Error (date_get_now_local)");
exit(EXIT_FAILURE);
}
time_t current_time = time(NULL);
struct tm *current_time_tm = localtime(&current_time);
date->year = (uint16_t)(current_time_tm->tm_year + 1900);
date->month = (uint8_t)(current_time_tm->tm_mon + 1);
date->day = (uint8_t)current_time_tm->tm_mday;
date->hours = (uint8_t)current_time_tm->tm_hour;
date->minutes = (uint8_t)current_time_tm->tm_min;
date->seconds = (uint8_t)current_time_tm->tm_sec;
date->milliseconds = 0;
date->timezone_utc_offset = 0;
return date;
}
uint16_t date_get_age(struct date *birth_date, struct date *current_date) {
uint16_t age = current_date->year - birth_date->year;
if (current_date->month < birth_date->month || (current_date->month == birth_date->month && current_date->day < birth_date->day)) {
age--;
}
return age;
}

View File

@ -1,350 +0,0 @@
#ifndef __LIBCPROJECT_DATE__
#define __LIBCPROJECT_DATE__
#include <errno.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "convert.h"
#include "mathematics.h"
#include "string.h"
#include "types.h"
#define SECONDS_PER_MINUTE 60
#define SECONDS_PER_HOUR (60 * SECONDS_PER_MINUTE)
#define SECONDS_PER_DAY (24 * SECONDS_PER_HOUR)
#define MILLISECONDS_PER_SECOND 1000
/**
* @brief Date object representing a single moment in time.
* @since v4.3.0
*/
struct date {
/**
* Year.
* Between [0, 9999] (inclusive).
* As per ISO 8601, a four-digit year [YYYY] and represents years from 0000 to 9999, year 0000 being equal to 1 BC and all others AD.
*/
uint16_t year;
/**
* Month.
* Between [1, 12] (inclusive).
*/
uint8_t month;
/**
* Day.
* Between [1, 31] (inclusive).
*/
uint8_t day;
/**
* Hours.
* Between [0, 23] (inclusive).
*/
uint8_t hours;
/**
* Minutes.
* Between [0, 59] (inclusive).
*/
uint8_t minutes;
/**
* Seconds.
* Between [0, 59] (inclusive).
*/
uint8_t seconds;
/**
* Milliseconds.
* Between [0, 999] (inclusive).
*/
uint16_t milliseconds;
/**
* Timezone UTC offset.
* Between [-12, 14]
*/
int8_t timezone_utc_offset;
};
/**
* @brief Return the copy of a date.
*
* @param date
* @return struct date*
* @since v4.3.0
*/
struct date *date_copy(struct date *date_to_copy);
/**
* @brief Check if a year is valid, between [0, 9999] (inclusive).
*
* @param year
* @return bool
* @since v4.3.0
*/
bool date_get_is_valid_year(uint16_t year);
/**
* @brief Check if a month is valid, between [1, 12] (inclusive).
*
* @param month
* @return bool
* @since v4.3.0
*/
bool date_get_is_valid_month(uint8_t month);
/**
* @brief Check if a day is valid, between [1, 31] (inclusive).
*
* @param day
* @return bool
* @since v4.3.0
*/
bool date_get_is_valid_day(uint8_t day);
/**
* @brief Check if hours are valid, between [0, 23] (inclusive).
*
* @param hours
* @return bool
* @since v4.3.0
*/
bool date_get_is_valid_hours(uint8_t hours);
/**
* @brief Check if minutes are valid, between [0, 59] (inclusive).
*
* @param minutes
* @return bool
* @since v4.3.0
*/
bool date_get_is_valid_minutes(uint8_t minutes);
/**
* @brief Check if seconds are valid, between [0, 59] (inclusive).
*
* @param seconds
* @return bool
* @since v4.3.0
*/
bool date_get_is_valid_seconds(uint8_t seconds);
/**
* @brief Check if milliseconds are valid, between [0, 999] (inclusive).
*
* @param milliseconds
* @return bool
* @since v4.3.0
*/
bool date_get_is_valid_milliseconds(uint16_t milliseconds);
/**
* @brief Check if the timezone UTC offset is valid, between [-12, 14] (inclusive).
*
* @param timezone_utc_offset
* @return bool
* @since v4.3.0
*/
bool date_get_is_valid_timezone_utc_offset(int8_t timezone_utc_offset);
/**
* @brief Check if the date is valid (all fields are possible).
*
* @param date
* @return bool
* @since v4.3.0
*/
bool date_get_is_valid(struct date *date);
/**
* @brief String representing the date in the date time string format, a simplified format based on ISO 8601, which is always 24 characters long (`YYYY-MM-DDTHH:mm:ss.sssZ`). The timezone is always UTC, as denoted by the suffix `Z`.
*
* @param date
* @return string_t
*
* @code
* date_to_iso_string() // "2024-09-11T09:39:18.203Z"
* @endcode
*
* @since v4.3.0
*/
string_t date_to_iso_string(struct date *date);
/**
* @brief String representing the date in the ISO 8601 format, without time information (`YYYY-MM-DD`).
*
* @param date
* @return string_t
*
* @code
* date_to_iso_string_without_time() // "2024-09-11"
* @endcode
*
* @since v4.3.0
*/
string_t date_to_iso_string_without_time(struct date *date);
/**
* @brief Create a date from an ISO 8601 string, with the format `YYYY-MM-DDTHH:mm:ss.sssZ`.
*
* The timezone is always UTC, as denoted by the suffix `Z`.
*
* @param iso_string
* @return struct date*
* @since v4.3.0
*/
struct date *date_from_iso_string(string_t iso_string);
/**
* @brief Get number of days in one month [1, 12].
*
* @param month
* @return uint8_t
* @since v4.3.0
*/
uint8_t date_get_days_of_month(uint8_t month, uint16_t year);
/**
* @brief Determine if a year is a leap year.
*
* @param year
* @return bool
*
* @code
* date_is_leap_year(2020) // true
*
* date_is_leap_year(2021) // false
*
* date_is_leap_year(2022) // false
*
* date_is_leap_year(2023) // false
*
* date_is_leap_year(2024) // true
* @endcode
*
* @since v4.3.0
*/
bool date_get_is_leap_year(uint16_t year);
/**
* @brief Convert milliseconds to seconds.
*
* @param milliseconds
* @return uint64_t
* @since v4.3.0
*/
uint64_t date_convert_milliseconds_to_seconds(uint16_t milliseconds);
/**
* @brief Convert seconds to milliseconds.
*
* @param seconds
* @return uint64_t
* @since v4.3.0
*/
uint64_t date_convert_seconds_to_milliseconds(uint64_t seconds);
/**
* @brief Convert days to seconds.
*
* @param days
* @return uint64_t
* @since v4.3.0
*/
uint64_t date_convert_days_to_seconds(uint64_t days);
/**
* @brief Convert hours, minutes, and seconds to seconds.
*
* @param hours
* @param minutes
* @param seconds
* @return uint64_t
* @since v4.3.0
*/
uint64_t date_convert_hms_to_seconds(uint8_t hours, uint8_t minutes, uint8_t seconds);
/**
* @brief Convert a date to total seconds.
*
* @param date
* @return uint64_t
* @since v4.3.0
*/
uint64_t date_to_total_seconds(struct date *date);
/**
* @brief Calculate the duration in seconds between 2 dates.
*
* @param date1
* @param date2
* @return uint64_t
* @since v4.3.0
*/
uint64_t date_duration_seconds_between_2_dates(struct date *date1, struct date *date2);
/**
* @brief Add hours to the date, managing the day, month, year changes if necessary.
*
* NOTE: Mutates the date.
*
* @param date
* @param hours
* @since v4.3.0
*/
void date_add_hours(struct date *date, int64_t hours);
/**
* @brief Adds days to the date, managing month and year changes as needed.
*
* NOTE: Mutates the date.
*
* @param date The date to which days are being added.
* @param days The number of days to add.
* @since v4.3.0
*/
void date_add_days(struct date *date, int64_t days);
/**
* @brief Transform the date with a Timezone UTC Offset to UTC (timezone_utc_offset = 0).
*
* NOTE: Mutates the date.
*
* @param date
* @since v4.3.0
*/
void date_to_utc(struct date *date);
/**
* @brief Get the current date in UTC.
*
* @return struct date*
* @since v5.1.0
*/
struct date *date_get_now_utc();
/**
* @brief Get the current date in local time.
*
* @return struct date*
* @since v5.1.0
*/
struct date *date_get_now_local();
/**
* @brief Calculates the age of a person based on their birth date.
*
* @param birth_date
* @return uint16_t
* @since v5.1.0
*/
uint16_t date_get_age(struct date *birth_date, struct date *current_date);
#endif

68
lib/dictionary.c Normal file
View File

@ -0,0 +1,68 @@
#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;
}

34
lib/dictionary.h Normal file
View File

@ -0,0 +1,34 @@
#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,6 +1,17 @@
#include "filesystem.h" #include "filesystem.h"
int filesystem_read(string_t path, byte_t **file_content, size_t *file_size) { #include <dirent.h>
#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;
@ -8,243 +19,39 @@ int filesystem_read(string_t path, byte_t **file_content, size_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);
if (read(file_descriptor, *file_content, *file_size) == -1) { read(file_descriptor, *file_content, *file_size);
return -1;
}
close(file_descriptor); close(file_descriptor);
return 0; return 0;
} }
int filesystem_write(string_t path, byte_t *file_content, size_t file_size) { int filesystem_write(char *path, char *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;
} }
if (write(file_descriptor, file_content, file_size) == -1) { write(file_descriptor, file_content, file_size);
return -1;
}
close(file_descriptor); close(file_descriptor);
return 0; return 0;
} }
bool filesystem_exists(string_t path) { char *filesystem_get_mimetype(char *path) {
return access(path, F_OK) == 0; if (string_ends_with(path, ".html")) {
} return "text/html";
int filesystem_remove(string_t path) {
return remove(path);
}
string_t filesystem_get_mimetype(string_t path) {
if (string_ends_with(path, ".aac")) {
return "audio/aac";
}
if (string_ends_with(path, ".abw")) {
return "application/x-abiword";
}
if (string_ends_with(path, ".arc")) {
return "application/x-freearc";
}
if (string_ends_with(path, ".avif")) {
return "image/avif";
}
if (string_ends_with(path, ".avi")) {
return "video/x-msvideo";
}
if (string_ends_with(path, ".azw")) {
return "application/vnd.amazon.ebook";
}
if (string_ends_with(path, ".bin")) {
return "application/octet-stream";
}
if (string_ends_with(path, ".bmp")) {
return "image/bmp";
}
if (string_ends_with(path, ".bz")) {
return "application/x-bzip";
}
if (string_ends_with(path, ".bz2")) {
return "application/x-bzip2";
}
if (string_ends_with(path, ".cda")) {
return "application/x-cdf";
}
if (string_ends_with(path, ".csh")) {
return "application/x-csh";
} }
if (string_ends_with(path, ".css")) { if (string_ends_with(path, ".css")) {
return "text/css"; return "text/css";
} }
if (string_ends_with(path, ".csv")) { if (string_ends_with(path, ".js")) {
return "text/csv";
}
if (string_ends_with(path, ".doc")) {
return "application/msword";
}
if (string_ends_with(path, ".docx")) {
return "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
}
if (string_ends_with(path, ".eot")) {
return "application/vnd.ms-fontobject";
}
if (string_ends_with(path, ".epub")) {
return "application/epub+zip";
}
if (string_ends_with(path, ".gz")) {
return "application/gzip";
}
if (string_ends_with(path, ".gif")) {
return "image/gif";
}
if (string_ends_with(path, ".htm") || string_ends_with(path, ".html")) {
return "text/html";
}
if (string_ends_with(path, ".ico")) {
return "image/vnd.microsoft.icon";
}
if (string_ends_with(path, ".ics")) {
return "text/calendar";
}
if (string_ends_with(path, ".jar")) {
return "application/java-archive";
}
if (string_ends_with(path, ".jpg") || string_ends_with(path, ".jpeg") || string_ends_with(path, ".jpe") || string_ends_with(path, ".jif") || string_ends_with(path, ".jfif") || string_ends_with(path, ".jfi")) {
return "image/jpeg";
}
if (string_ends_with(path, ".js") || string_ends_with(path, ".mjs") || string_ends_with(path, ".cjs")) {
return "text/javascript"; return "text/javascript";
} }
if (string_ends_with(path, ".json")) {
return "application/json";
}
if (string_ends_with(path, ".jsonld")) {
return "application/ld+json";
}
if (string_ends_with(path, ".mid") || string_ends_with(path, ".midi")) {
return "audio/midi";
}
if (string_ends_with(path, ".mp3")) {
return "audio/mpeg";
}
if (string_ends_with(path, ".mp4")) {
return "video/mp4";
}
if (string_ends_with(path, ".mpeg")) {
return "video/mpeg";
}
if (string_ends_with(path, ".mpkg")) {
return "application/vnd.apple.installer+xml";
}
if (string_ends_with(path, ".odp")) {
return "application/vnd.oasis.opendocument.presentation";
}
if (string_ends_with(path, ".ods")) {
return "application/vnd.oasis.opendocument.spreadsheet";
}
if (string_ends_with(path, ".odt")) {
return "application/vnd.oasis.opendocument.text";
}
if (string_ends_with(path, ".oga")) {
return "audio/ogg";
}
if (string_ends_with(path, ".ogv")) {
return "video/ogg";
}
if (string_ends_with(path, ".ogx")) {
return "application/ogg";
}
if (string_ends_with(path, ".opus")) {
return "audio/opus";
}
if (string_ends_with(path, ".otf")) {
return "font/otf";
}
if (string_ends_with(path, ".png")) { if (string_ends_with(path, ".png")) {
return "image/png"; return "image/png";
} }
if (string_ends_with(path, ".pdf")) { if (string_ends_with(path, ".jpg") || string_ends_with(path, ".jpeg")) {
return "application/pdf"; return "image/jpeg";
} }
if (string_ends_with(path, ".php")) { if (string_ends_with(path, ".gif")) {
return "application/x-httpd-php"; return "image/gif";
} }
if (string_ends_with(path, ".ppt")) {
return "application/vnd.ms-powerpoint";
}
if (string_ends_with(path, ".pptx")) {
return "application/vnd.openxmlformats-officedocument.presentationml.presentation";
}
if (string_ends_with(path, ".rar")) {
return "application/vnd.rar";
}
if (string_ends_with(path, ".rtf")) {
return "application/rtf";
}
if (string_ends_with(path, ".sh")) {
return "application/x-sh";
}
if (string_ends_with(path, ".svg")) {
return "image/svg+xml";
}
if (string_ends_with(path, ".tar")) {
return "application/x-tar";
}
if (string_ends_with(path, ".tif") || string_ends_with(path, ".tiff")) {
return "image/tiff";
}
if (string_ends_with(path, ".ts")) {
return "application/typescript";
}
if (string_ends_with(path, ".ttf")) {
return "font/ttf";
}
if (string_ends_with(path, ".txt")) {
return "text/plain"; return "text/plain";
} }
if (string_ends_with(path, ".vsd")) {
return "application/vnd.visio";
}
if (string_ends_with(path, ".wav")) {
return "audio/wav";
}
if (string_ends_with(path, ".weba") || string_ends_with(path, ".webm")) {
return "audio/webm";
}
if (string_ends_with(path, ".webp")) {
return "image/webp";
}
if (string_ends_with(path, ".woff")) {
return "font/woff";
}
if (string_ends_with(path, ".woff2")) {
return "font/woff2";
}
if (string_ends_with(path, ".xhtml")) {
return "application/xhtml+xml";
}
if (string_ends_with(path, ".xls")) {
return "application/vnd.ms-excel";
}
if (string_ends_with(path, ".xlsx")) {
return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
}
if (string_ends_with(path, ".xml")) {
return "application/xml";
}
if (string_ends_with(path, ".xul")) {
return "application/vnd.mozilla.xul+xml";
}
if (string_ends_with(path, ".zip")) {
return "application/zip";
}
if (string_ends_with(path, ".3gp")) {
return "video/3gpp";
}
if (string_ends_with(path, ".3g2")) {
return "video/3gpp2";
}
if (string_ends_with(path, ".7z")) {
return "application/x-7z-compressed";
}
return "application/octet-stream";
}

View File

@ -1,30 +1,19 @@
#ifndef __LIBCPROJECT_FILESYSTEM__ #ifndef __FILESYSTEM__
#define __LIBCPROJECT_FILESYSTEM__ #define __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.
* *
* @param path * @param path
* @param file_content * @param file_content
* @param file_size The size of the file that was read (mutated by the function). * @param file_size
* @retval -1 if the file does not exist or if there is an error.
* @retval 0 for success.
* @return int * @return int
* @since v1.0.0 * @retval -1 if the file does not exist
* @retval 0 for success
*/ */
int filesystem_read(string_t path, byte_t **file_content, size_t *file_size); int filesystem_read(char *path, char **file_content, off_t *file_size);
/** /**
* @brief Write the content to a file. * @brief Write the content to a file.
@ -32,43 +21,18 @@ int filesystem_read(string_t path, byte_t **file_content, size_t *file_size);
* @param path * @param path
* @param file_content * @param file_content
* @param file_size * @param file_size
* @retval -1 if there is an error.
* @retval 0 for success.
* @return int * @return int
* @since v1.0.0 * @retval -1 if errors
* @retval 0 for success
*/ */
int filesystem_write(string_t path, byte_t *file_content, size_t file_size); int filesystem_write(char *path, char *file_content, off_t file_size);
/** /**
* @brief Check if a path exists. * @brief Get the mimetype of a file.
* *
* @param path * @param path
* @return bool * @return char*
* @since v3.1.0
*/ */
bool filesystem_exists(string_t path); char *filesystem_get_mimetype(char *path);
/**
* @brief Removes a path.
*
* @param path
* @return int
* @retval -1 if there is an error.
* @retval 0 for success.
* @return int
* @since v3.1.0
*/
int filesystem_remove(string_t path);
/**
* @brief Get the mimetype of a file based on its extension.
*
* @param path
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types
* @see https://www.iana.org/assignments/media-types/media-types.xhtml
* @return string_t
* @since v1.0.0
*/
string_t filesystem_get_mimetype(string_t path);
#endif #endif

View File

@ -1,244 +0,0 @@
#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 (uint8_t 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 (uint8_t 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 (uint8_t 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 (uint8_t 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);
}

View File

@ -1,110 +0,0 @@
#ifndef __LIBCPROJECT_HASH_MAP__
#define __LIBCPROJECT_HASH_MAP__
#include <errno.h>
#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).
* @see https://en.wikipedia.org/wiki/SipHash
* @see https://github.com/veorq/SipHash
*
* @param key
* @param capacity
* @return uint64_t
* @since v2.0.0
*/
uint64_t hash(string_t key, size_t capacity);
/**
* @brief Hash map initialization.
*
* @return struct hash_map*
* @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
* @return void*
* @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
* @return bool
* @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
* @return string_t*
* @since v2.0.0
*/
string_t *hash_map_get_keys(struct hash_map *hash_map);
/**
* @brief Frees the hash map.
*
* @param hash_map
* @since v3.0.0
*/
void hash_map_free(struct hash_map *hash_map);
#endif

View File

@ -1,9 +1,13 @@
#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(struct linked_list)); struct linked_list *list = malloc(sizeof(*list));
if (list == NULL) { if (list == NULL) {
perror("Error (linked_list_initialization)");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
list->head = NULL; list->head = NULL;
@ -12,14 +16,8 @@ struct linked_list *linked_list_initialization() {
} }
struct linked_list_node *linked_list_add_in_head(struct linked_list *list, void *new_data) { struct linked_list_node *linked_list_add_in_head(struct linked_list *list, void *new_data) {
if (list == NULL) { struct linked_list_node *node_new = malloc(sizeof(*node_new));
errno = EINVAL; if (list == NULL || node_new == NULL) {
perror("Error (linked_list_add_in_head)");
exit(EXIT_FAILURE);
}
struct linked_list_node *node_new = malloc(sizeof(struct linked_list_node));
if (node_new == NULL) {
perror("Error (linked_list_add_in_head)");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
node_new->data = new_data; node_new->data = new_data;
@ -31,8 +29,6 @@ struct linked_list_node *linked_list_add_in_head(struct linked_list *list, void
void linked_list_delete_in_head(struct linked_list *list) { void linked_list_delete_in_head(struct linked_list *list) {
if (list == NULL) { if (list == NULL) {
errno = EINVAL;
perror("Error (linked_list_delete_in_head)");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (list->head != NULL) { if (list->head != NULL) {
@ -44,17 +40,11 @@ void linked_list_delete_in_head(struct linked_list *list) {
} }
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) {
if (list == NULL) {
errno = EINVAL;
perror("Error (linked_list_add_after_last)");
exit(EXIT_FAILURE);
}
if (list->head == NULL) { if (list->head == NULL) {
return linked_list_add_in_head(list, new_data); return linked_list_add_in_head(list, new_data);
} }
struct linked_list_node *node_new = malloc(sizeof(struct linked_list_node)); struct linked_list_node *node_new = malloc(sizeof(*node_new));
if (node_new == NULL) { if (list == NULL || node_new == NULL) {
perror("Error (linked_list_add_after_last)");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
node_new->data = new_data; node_new->data = new_data;
@ -83,7 +73,6 @@ 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;
} }
@ -100,14 +89,3 @@ 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,90 +1,30 @@
#ifndef __LIBCPROJECT_LINKED_LIST__ #ifndef __LINKED_LIST__
#define __LIBCPROJECT_LINKED_LIST__ #define __LINKED_LIST__
#include <errno.h>
#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.
*
* @return struct linked_list*
* @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.
*
* @param list
* @param new_value
* @return struct linked_list_node*
* @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.
*
* @param 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.
*
* @param list
* @param new_data
* @return struct linked_list_node*
* @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.
*
* @param list
* @return struct linked_list*
* @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.
*
* @param list
* @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.
*
* @param list
* @since v3.0.0
*/
void linked_list_free(struct linked_list *list);
#endif #endif

View File

@ -1,23 +1,25 @@
#include "mathematics.h" #include "mathematics.h"
bool mathematics_equals(const float64_t number1, const float64_t number2) { #include <stdbool.h>
return (number1 - number2) < MATHEMATICS_DOUBLE_PRECISION;
bool mathematics_equals(const float number1, const float number2) {
return (number1 - number2) < MATHEMATICS_FLOAT_PRECISION;
} }
uint64_t mathematics_absolute_value(const int64_t number) { unsigned long long mathematics_absolute_value(const long long number) {
if (number >= 0) { if (number >= 0) {
return number; return number;
} }
return -number; return -number;
} }
uint64_t mathematics_pow(uint64_t base, uint64_t exponent) { unsigned long long mathematics_pow(unsigned long long base, unsigned long long exponent) {
return exponent == 0 ? 1 : base * mathematics_pow(base, exponent - 1); return exponent == 0 ? 1 : base * mathematics_pow(base, exponent - 1);
} }
float64_t mathematics_root(float64_t number, uint64_t nth_root) { float mathematics_root(float number, unsigned int nth_root) {
float64_t result = number; float result = number;
float64_t previous_result = 0; float previous_result = 0;
while (!mathematics_equals(result, previous_result)) { while (!mathematics_equals(result, previous_result)) {
result = (((nth_root - 1) * previous_result) + (number / mathematics_pow(result, nth_root - 1))) / nth_root; result = (((nth_root - 1) * previous_result) + (number / mathematics_pow(result, nth_root - 1))) / nth_root;
previous_result = result; previous_result = result;
@ -25,46 +27,10 @@ float64_t mathematics_root(float64_t number, uint64_t nth_root) {
return result; return result;
} }
float64_t mathematics_square_root(float64_t number) { float mathematics_square_root(float number) {
return mathematics_root(number, 2); return mathematics_root(number, 2);
} }
uint64_t mathematics_factorial(uint64_t number) { unsigned long long mathematics_factorial(unsigned long long number) {
return number == 0 ? 1 : number * mathematics_factorial(number - 1); return number == 0 ? 1 : number * mathematics_factorial(number - 1);
} }
int64_t mathematics_opposite(int64_t number) {
return number * -1;
}
int64_t mathematics_max(int64_t number1, int64_t number2) {
return number1 > number2 ? number1 : number2;
}
int64_t mathematics_max_values(int64_t *values, size_t values_length) {
int64_t max = 0;
if (values_length <= 0) {
return max;
}
max = values[0];
for (size_t index = 1; index < values_length; index++) {
max = mathematics_max(max, values[index]);
}
return max;
}
int64_t mathematics_min(int64_t number1, int64_t number2) {
return number1 > number2 ? number2 : number1;
}
int64_t mathematics_min_values(int64_t *values, size_t values_length) {
int64_t min = 0;
if (values_length <= 0) {
return min;
}
min = values[0];
for (size_t index = 1; index < values_length; index++) {
min = mathematics_min(min, values[index]);
}
return min;
}

View File

@ -1,124 +1,27 @@
#ifndef __LIBCPROJECT_MATHEMATICS__ #ifndef __MATHEMATICS__
#define __LIBCPROJECT_MATHEMATICS__ #define __MATHEMATICS__
#define MATHEMATICS_DOUBLE_PRECISION 0.0000000001 #define MATHEMATICS_FLOAT_PRECISION 0.00000001
#include <errno.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdlib.h>
#include "types.h" bool mathematics_equals(const float number1, const float number2);
unsigned long long mathematics_absolute_value(const long long number);
unsigned long long mathematics_pow(unsigned long long base, unsigned long long exponent);
/** /**
* @brief Verify that 2 numbers are equal. * @brief Calculates the nth root of a number using Heron's method.
*
* @param number1
* @param number2
* @return bool
* @since v1.0.0
*/
bool mathematics_equals(const float64_t number1, const float64_t number2);
/**
* @brief Get the absolute value of a number.
*
* @param number
* @return uint64_t
* @since v1.0.0
*/
uint64_t mathematics_absolute_value(const int64_t number);
/**
* @brief Calculates the power of a number.
*
* @param base
* @param exponent
* @return uint64_t
* @since v1.0.0
*/
uint64_t mathematics_pow(uint64_t base, uint64_t exponent);
/**
* @brief Calculates the nth root of a number.
* *
* @param number * @param number
* @param nth_root * @param nth_root
* @return float64_t * @return float
* @since v1.0.0
*/ */
float64_t mathematics_root(float64_t number, uint64_t nth_root); float mathematics_root(float number, unsigned int nth_root);
/** float mathematics_square_root(float number);
* @brief Calculates the square root of a number using Heron's method.
*
* @param number
* @return float64_t
* @since v1.0.0
*/
float64_t mathematics_square_root(float64_t number);
/** unsigned long long mathematics_factorial(unsigned long long number);
* @brief Calculates the factorial of a number.
*
* @param number
* @return uint64_t
* @since v1.0.0
*/
uint64_t mathematics_factorial(uint64_t number);
/**
* @brief Calulcates the opposite number (additive inverse).
*
* @param number
* @return int64_t
*
* @code
* mathematics_opposite(7) // -7
*
* mathematics_opposite(-7) // 7
* @endcode
* @since v4.3.0
*/
int64_t mathematics_opposite(int64_t number);
/**
* @brief Returns the largest number between 2 numbers.
*
* @param number1
* @param number2
* @return int64_t
* @since v4.3.0
*/
int64_t mathematics_max(int64_t number1, int64_t number2);
/**
* @brief Returns the largest number between multiple numbers. If the array is empty, returns 0.
*
* @param values
* @param values_length
* @return int64_t
* @since v4.3.0
*/
int64_t mathematics_max_values(int64_t *values, size_t values_length);
/**
* @brief Returns the smallest number between 2 numbers.
*
* @param number1
* @param number2
* @return int64_t
* @since v4.3.0
*/
int64_t mathematics_min(int64_t number1, int64_t number2);
/**
* @brief Returns the smallest number between multiple numbers. If the array is empty, returns 0.
*
* @param values
* @param values_length
* @return int64_t
* @since v4.3.0
*/
int64_t mathematics_min_values(int64_t *values, size_t values_length);
#endif #endif

View File

@ -1,9 +1,11 @@
#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(struct queue)); struct queue *queue = malloc(sizeof(*queue));
if (queue == NULL) { if (queue == NULL) {
perror("Error (queue_initialization)");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
queue->first = NULL; queue->first = NULL;
@ -12,14 +14,8 @@ struct queue *queue_initialization() {
} }
void queue_push(struct queue *queue, void *data) { void queue_push(struct queue *queue, void *data) {
if (queue == NULL) { struct queue_node *node_new = malloc(sizeof(*node_new));
errno = EINVAL; if (queue == NULL || node_new == NULL) {
perror("Error (queue_push)");
exit(EXIT_FAILURE);
}
struct queue_node *node_new = malloc(sizeof(struct queue_node));
if (node_new == NULL) {
perror("Error (queue_push)");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
node_new->data = data; node_new->data = data;
@ -38,8 +34,6 @@ void queue_push(struct queue *queue, void *data) {
void *queue_pop(struct queue *queue) { void *queue_pop(struct queue *queue) {
if (queue == NULL) { if (queue == NULL) {
errno = EINVAL;
perror("Error (queue_pop)");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
struct queue_node *node = queue->first; struct queue_node *node = queue->first;
@ -52,18 +46,3 @@ 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) {
errno = EINVAL;
perror("Error (queue_free)");
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,62 +1,23 @@
#ifndef __LIBCPROJECT_QUEUE__ #ifndef __QUEUE__
#define __LIBCPROJECT_QUEUE__ #define __QUEUE__
#include <errno.h>
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include "types.h" // FIFO = First In First Out
/**
* @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.
*
* @return struct queue*
* @since v1.0.0
*/
struct queue *queue_initialization(); struct queue *queue_initialization();
/**
* @brief Push data to queue.
*
* @param queue
* @param data
* @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.
*
* @param queue
* @return void*
* @since v1.0.0
*/
void *queue_pop(struct queue *queue); void *queue_pop(struct queue *queue);
/**
* @brief Frees the queue.
*
* @param queue
* @since v3.0.0
*/
void queue_free(struct queue *queue);
#endif #endif

View File

@ -1,9 +1,11 @@
#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(struct stack)); struct stack *stack = malloc(sizeof(*stack));
if (stack == NULL) { if (stack == NULL) {
perror("Error (stack_initialization)");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
stack->first = NULL; stack->first = NULL;
@ -12,14 +14,8 @@ struct stack *stack_initialization() {
} }
void stack_push(struct stack *stack, void *data) { void stack_push(struct stack *stack, void *data) {
if (stack == NULL) { struct stack_node *node_new = malloc(sizeof(*node_new));
errno = EINVAL; if (stack == NULL || data == NULL) {
perror("Error (stack_push)");
exit(EXIT_FAILURE);
}
struct stack_node *node_new = malloc(sizeof(struct stack_node));
if (data == NULL) {
perror("Error (stack_push)");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
node_new->data = data; node_new->data = data;
@ -30,8 +26,6 @@ void stack_push(struct stack *stack, void *data) {
void *stack_pop(struct stack *stack) { void *stack_pop(struct stack *stack) {
if (stack == NULL) { if (stack == NULL) {
errno = EINVAL;
perror("Error (stack_pop)");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
struct stack_node *node = stack->first; struct stack_node *node = stack->first;
@ -44,18 +38,3 @@ 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) {
errno = EINVAL;
perror("Error (stack_free)");
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,62 +1,23 @@
#ifndef __LIBCPROJECT_STACK__ #ifndef __STACK__
#define __LIBCPROJECT_STACK__ #define __STACK__
#include <errno.h>
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include "types.h" // LIFO = Last In First Out
/**
* @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.
*
* @return struct stack*
* @since v1.0.0
*/
struct stack *stack_initialization(); struct stack *stack_initialization();
/**
* @brief Push data to stack.
*
* @param stack
* @param data
* @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.
*
* @param stack
* @return void*
* @since v1.0.0
*/
void *stack_pop(struct stack *stack); void *stack_pop(struct stack *stack);
/**
* @brief Frees the stack.
*
* @param stack
* @since v3.0.0
*/
void stack_free(struct stack *stack);
#endif #endif

View File

@ -1,6 +1,14 @@
#include "string.h" #include "string.h"
size_t string_get_length(const string_t string) { #include <stdbool.h>
#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[length] != '\0') {
length++; length++;
@ -8,99 +16,107 @@ size_t string_get_length(const string_t string) {
return length; return length;
} }
void string_to_uppercase(string_t string) { char* string_to_uppercase(char* string) {
size_t string_length = string_get_length(string); size_t string_length = string_get_length(string);
for (size_t index = 0; index < string_length; index++) { char* result = malloc(sizeof(char*) * string_length);
string[index] = character_to_upper(string[index]); if (result == NULL) {
exit(EXIT_FAILURE);
} }
string[string_length] = '\0'; for (size_t index = 0; index < string_length; index++) {
character_append(result, character_to_upper(string[index]));
}
return result;
} }
void string_to_lowercase(string_t string) { char* string_to_lowercase(char* string) {
size_t string_length = string_get_length(string); size_t string_length = string_get_length(string);
for (size_t index = 0; index < string_length; index++) { char* result = malloc(sizeof(char*) * string_length);
string[index] = character_to_lower(string[index]); if (result == NULL) {
exit(EXIT_FAILURE);
} }
string[string_length] = '\0'; for (size_t index = 0; index < string_length; index++) {
character_append(result, character_to_lower(string[index]));
}
return result;
} }
void string_replace(string_t string, char search, char replace) { char* string_replace(char* string, char search, char replace) {
size_t string_length = string_get_length(string); size_t string_length = string_get_length(string);
char* result = malloc(sizeof(char*) * string_length);
if (result == NULL) {
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[index];
if (is_search_value) { if (is_search_value) {
string[index] = replace; character_append(result, replace);
} else { } else {
string[index] = string[index]; character_append(result, string[index]);
} }
} }
string[string_length] = '\0'; return result;
} }
void string_remove_character(string_t string, char search) { char* string_trim_start(char* string) {
size_t string_length = string_get_length(string); size_t string_length = string_get_length(string);
for (size_t index = 0; index < string_length; index++) { char* result = malloc(sizeof(char*) * string_length);
if (string[index] == search) { if (result == NULL) {
for (size_t index_string = index; index_string < string_length; index_string++) {
string[index_string] = string[index_string + 1];
}
string_length--;
index--;
}
}
string[string_length] = '\0';
}
void string_trim_start(string_t string, char character) {
size_t string_length = string_get_length(string);
size_t index_space = 0;
while (string[index_space] == character) {
index_space++;
}
for (size_t index = 0; index < string_length - index_space; index++) {
string[index] = string[index + index_space];
}
string[string_length - index_space] = '\0';
}
void string_trim_end(string_t string, char character) {
size_t string_length = string_get_length(string);
size_t index_space = string_length - 1;
while (string[index_space] == character) {
index_space--;
}
string[index_space + 1] = '\0';
}
void string_trim(string_t string, char character) {
string_trim_start(string, character);
string_trim_end(string, character);
}
string_t string_copy(const string_t string) {
size_t source_length = string_get_length(string);
string_t copy = malloc(sizeof(char) * (source_length + 1));
if (copy == NULL) {
perror("Error (string_copy)");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
size_t index; size_t index_space = 0;
for (index = 0; index < source_length; index++) { while (string[index_space] == ' ') {
copy[index] = string[index]; index_space++;
} }
copy[index] = '\0'; for (size_t index = index_space; index < string_length; index++) {
return copy; character_append(result, string[index]);
}
return result;
} }
void string_capitalize(string_t string) { char* string_trim_end(char* string) {
size_t string_length = string_get_length(string); size_t string_length = string_get_length(string);
if (string_length == 0) { char* result = malloc(sizeof(char*) * string_length);
return; if (result == NULL) {
exit(EXIT_FAILURE);
} }
string[0] = character_to_upper(string[0]); size_t index_space = string_length - 1;
while (string[index_space] == ' ') {
index_space--;
}
for (size_t index = 0; index < index_space + 1; index++) {
character_append(result, string[index]);
}
return result;
} }
size_t string_total_occurrences_of_character(string_t string, char character) { char* string_trim(char* string) {
char* result = string_trim_start(string);
result = string_trim_end(result);
return result;
}
char* string_copy(const char* string) {
return string_substring(string, 0, string_get_length(string));
}
char* string_capitalize(char* string) {
size_t string_length = string_get_length(string);
char* result = malloc(sizeof(char*) * string_length);
if (result == NULL) {
exit(EXIT_FAILURE);
}
for (size_t index = 0; index < string_length; index++) {
bool is_first_character = index == 0;
if (is_first_character) {
character_append(result, character_to_upper(string[index]));
} else {
character_append(result, string[index]);
}
}
return result;
}
size_t string_total_occurrences_of_character(char* string, 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);
for (size_t index = 0; index < string_length; index++) { for (size_t index = 0; index < string_length; index++) {
@ -112,20 +128,21 @@ size_t string_total_occurrences_of_character(string_t string, char character) {
return result; return result;
} }
void string_reverse(const string_t string) { char* string_reverse(const char* string) {
size_t string_length = string_get_length(string); size_t string_length = string_get_length(string);
size_t index_start = 0; size_t index = 0;
size_t index_end = string_length - 1; char* result = malloc(sizeof(char*) * string_length);
while (index_start < index_end) { if (result == NULL) {
char temporary = string[index_start]; exit(EXIT_FAILURE);
string[index_start] = string[index_end];
string[index_end] = temporary;
index_start++;
index_end--;
} }
for (index = string_length - 1; index > 0; index--) {
character_append(result, string[index]);
}
character_append(result, string[index]);
return result;
} }
bool string_equals(const string_t string1, const string_t string2) { bool string_equals(const char* string1, const char* 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;
@ -137,7 +154,7 @@ bool string_equals(const string_t string1, const string_t string2) {
return is_equal; return is_equal;
} }
bool string_get_is_integer(const string_t string) { bool string_get_is_integer(const char* string) {
size_t index = 0; size_t index = 0;
size_t string_length = string_get_length(string); size_t string_length = string_get_length(string);
bool is_integer = string_length >= 1; bool is_integer = string_length >= 1;
@ -157,130 +174,106 @@ bool string_get_is_integer(const string_t string) {
return is_integer; return is_integer;
} }
string_t* string_split(const string_t string, char separator, size_t* result_size) { char** string_split(const char* string, char separator, size_t* result_size) {
size_t string_length = string_get_length(string); size_t string_length = string_get_length(string);
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;
string_t current = malloc(sizeof(char) * (string_length + 1)); char* current = malloc(sizeof(char*) * string_length);
string_t* result = NULL; char** result = malloc(sizeof(char**) * index_result);
if (current == NULL) { if (result == NULL || current == NULL) {
perror("Error (string_split)");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
while (index_string < string_length) { while (index_string < string_length) {
if (string[index_string] == separator) { if (string[index_string] == separator) {
current[index_current] = '\0';
result = realloc(result, sizeof(string_t) * (index_result + 1));
if (result == NULL) {
perror("Error (string_split)");
exit(EXIT_FAILURE);
}
result[index_result] = string_copy(current); result[index_result] = string_copy(current);
index_result++; index_result++;
result = realloc(result, sizeof(char*) * index_result);
if (result == NULL) {
exit(EXIT_FAILURE);
}
index_current = 0; index_current = 0;
current = string_copy("");
} else { } else {
current[index_current] = string[index_string]; character_append(current, string[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) {
perror("Error (string_split)");
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;
} }
string_t string_join(string_t* array, const char separator, size_t array_length) { char* string_join(char** array, const char separator, size_t array_length) {
size_t total_length = 0; size_t string_length = array_length;
for (size_t index_array = 0; index_array < array_length; index_array++) { char* string = malloc(sizeof(char*) * string_length);
total_length += string_get_length(array[index_array]);
}
size_t string_length = total_length + (array_length - 1);
string_t string = malloc(sizeof(char) * (string_length + 1));
if (string == NULL) { if (string == NULL) {
perror("Error (string_join)");
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++) {
string_t substring = array[index_array]; char* 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++) {
string[current_index] = substring[index_substring]; character_append(string, 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) {
string[current_index] = separator; character_append(string, separator);
current_index++;
} }
} }
string[string_length] = '\0';
return string; return string;
} }
void string_concatenate(string_t* destination, string_t source) { char* string_concatenate(char* string1, char* string2) {
size_t destination_length = string_get_length(*destination); size_t string1_length = string_get_length(string1);
size_t source_length = string_get_length(source); size_t string2_length = string_get_length(string2);
size_t new_length = destination_length + source_length; size_t result_length = string1_length + string2_length;
*destination = realloc(*destination, sizeof(char) * (new_length + 1)); char* result = malloc(sizeof(char*) * result_length);
if (*destination == NULL) { if (result == NULL) {
perror("Error (string_concatenate)");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
size_t index_destination = destination_length; for (size_t index_string1 = 0; index_string1 < string1_length; index_string1++) {
for (size_t index_source = 0; index_source < source_length; index_source++) { character_append(result, string1[index_string1]);
(*destination)[index_destination++] = source[index_source];
} }
(*destination)[index_destination] = '\0'; for (size_t index_string2 = 0; index_string2 < string2_length; index_string2++) {
character_append(result, string2[index_string2]);
} }
bool string_get_has_unique_characters(const string_t string) {
bool has_unique = true;
size_t string_length = string_get_length(string);
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++) {
char character = string[index];
keys[index] = convert_character_to_string(character);
string_t key = keys[index];
if (hash_map_contains_key(characters_already_seen, key)) {
has_unique = false;
} else {
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;
}
string_t string_substring(const string_t string, size_t index_start, size_t index_end) {
size_t substring_length = index_end - index_start + 1;
string_t result = malloc(sizeof(char) * (substring_length + 1));
for (size_t index = 0; index < substring_length; index++) {
result[index] = string[index_start + index];
}
result[substring_length] = '\0';
return result; return result;
} }
bool string_get_is_substring(const string_t string, const string_t substring) { bool string_get_has_unique_characters(const char* string) {
bool has_unique = true;
size_t string_length = string_get_length(string);
struct dictionary* characters_already_seen = dictionary_initialization();
for (size_t index = 0; index < string_length && has_unique; index++) {
char character = string[index];
char* key = convert_character_to_string(character);
if (dictionary_contains_key(characters_already_seen, key)) {
has_unique = false;
} else {
dictionary_add(characters_already_seen, key, (void*)true);
}
}
return has_unique;
}
char* string_substring(const char* string, size_t index_start, size_t index_end) {
size_t string_length = string_get_length(string);
char* result = malloc(sizeof(char*) * string_length);
for (size_t index = index_start; index <= index_end; index++) {
character_append(result, string[index]);
}
return result;
}
bool string_get_is_substring(const char* string, const char* 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);
size_t substring_length = string_get_length(substring); size_t substring_length = string_get_length(substring);
@ -296,73 +289,57 @@ bool string_get_is_substring(const string_t string, const string_t substring) {
return is_substring; return is_substring;
} }
string_t string_get_formatted_number(const int64_t number, string_t separator) { char* string_get_formatted_number(const long long number, char* separator) {
string_t number_string_temp = convert_number_to_string(number); char* number_string = convert_number_to_string(number);
string_t number_string = number_string_temp; bool is_negative = number_string[0] == '-';
bool is_negative = number_string_temp[0] == '-';
if (is_negative) { if (is_negative) {
number_string = string_substring(number_string_temp, 1, string_get_length(number_string_temp)); number_string = string_substring(number_string, 1, string_get_length(number_string));
free(number_string_temp);
} }
size_t number_string_length = string_get_length(number_string); size_t number_string_length = string_get_length(number_string);
size_t formatted_length = number_string_length + (number_string_length - 1) / 3; char* result = malloc(sizeof(char*) * number_string_length);
string_t result = malloc(sizeof(char) * (formatted_length + 1));
if (result == NULL) { if (result == NULL) {
perror("Error (string_get_formatted_number)");
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_index++; result = string_concatenate(result, convert_character_to_string(number_string[index_reversed]));
if (count == 3 && index != number_string_length - 1) { if (count == 3) {
for (size_t sep_index = 0; sep_index < string_get_length(separator); sep_index++) { result = string_concatenate(result, separator);
result[result_index] = separator[sep_index];
result_index++;
}
count = 0; count = 0;
} }
} }
free(number_string); result = string_reverse(result);
result[formatted_length] = '\0'; size_t result_length = string_get_length(result);
string_reverse(result); if (result_length % 4 == 0) {
result = string_substring(result, 1, result_length);
}
if (is_negative) { if (is_negative) {
string_t negative_result = convert_character_to_string('-'); result = string_concatenate(convert_character_to_string('-'), result);
string_concatenate(&negative_result, result);
free(result);
return negative_result;
} }
return result; return result;
} }
string_t string_get_last_occurence_of_character(const string_t string, char character) { char* string_get_last_occurence_of_character(const char* string, char character) {
size_t string_length = string_get_length(string); size_t string_length = string_get_length(string);
size_t index_last_occurrence = SIZE_MAX; char* result = malloc(sizeof(char*) * string_length);
for (size_t index = 0; index < string_length; index++) {
if (string[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) {
perror("Error (string_get_last_occurence_of_character)");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
size_t index_result = 0; size_t index_result = 0;
for (size_t index = index_last_occurrence; index < string_length; index++) { for (size_t index = 0; index < string_length; index++) {
result[index_result++] = string[index]; if (string[index] == character) {
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 string_t string, const string_t prefix) { bool string_starts_with(const char* string, const char* 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++) {
@ -371,7 +348,7 @@ bool string_starts_with(const string_t string, const string_t prefix) {
return starts_with; return starts_with;
} }
bool string_ends_with(const string_t string, const string_t prefix) { bool string_ends_with(const char* string, const char* 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);
size_t prefix_length = string_get_length(prefix); size_t prefix_length = string_get_length(prefix);
@ -384,59 +361,3 @@ bool string_ends_with(const string_t string, const string_t prefix) {
} }
return ends_with; return ends_with;
} }
size_t string_position_of(const string_t string, const char character) {
size_t position_found = 0;
size_t string_length = string_get_length(string);
for (size_t index = 0; index < string_length && position_found == 0; index++) {
if (string[index] == character) {
position_found = index + 1;
}
}
return position_found;
}
size_t string_last_position_of(const string_t string, const char character) {
size_t position_found = 0;
size_t string_length = string_get_length(string);
while (string_length > 0 && position_found == 0) {
if (string[string_length - 1] == character) {
position_found = string_length;
}
string_length--;
}
return position_found;
}
string_t string_pad_start(const string_t string, const string_t pad_string, size_t target_length) {
string_t result = malloc(sizeof(char) * (target_length + 1));
size_t initial_length = string_get_length(string);
size_t left_length = target_length - initial_length;
if (target_length <= initial_length) {
left_length = 0;
}
size_t pad_length = string_get_length(pad_string);
size_t count_pad_string = 0;
size_t index_initial_string = 0;
for (size_t index = 0; index < target_length; index++) {
if (index < left_length) {
size_t index_pad_string = count_pad_string % pad_length;
result[index] = pad_string[index_pad_string];
count_pad_string += 1;
} else {
result[index] = string[index_initial_string];
index_initial_string += 1;
}
}
result[target_length] = '\0';
return result;
}
string_t string_zero_pad(uint64_t number, size_t places) {
string_t number_string = convert_number_to_string((int64_t)number);
string_t pad_string = string_copy("0");
string_t result = string_pad_start(number_string, pad_string, places);
free(pad_string);
free(number_string);
return result;
}

View File

@ -1,116 +1,82 @@
#ifndef __LIBCPROJECT_STRING__ #ifndef __STRING__
#define __LIBCPROJECT_STRING__ #define __STRING__
#include <errno.h>
#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
* @return size_t * @return size_t
* @since v1.0.0
*/ */
size_t string_get_length(const string_t string); size_t string_get_length(const char* string);
/** /**
* @brief Converts all the alphabetic characters in a string to uppercase. * @brief Converts all the alphabetic characters in a string to uppercase.
* *
* NOTE: Mutates the string.
*
* @param string * @param string
* @since v1.0.0 * @return char*
*/ */
void string_to_uppercase(string_t string); char* string_to_uppercase(char* string);
/** /**
* @brief Converts all the alphabetic characters in a string to lowercase. * @brief Converts all the alphabetic characters in a string to lowercase.
* *
* NOTE: Mutates the string.
*
* @param string * @param string
* @since v1.0.0 * @return char*
*/ */
void string_to_lowercase(string_t string); char* string_to_lowercase(char* string);
/** /**
* @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.
* *
* NOTE: Mutates the string.
*
* @param string * @param string
* @param search A character search value. * @param search_value A character search value.
* @param replace A character containing the text to replace for match. * @param replace_value A character containing the text to replace for match.
* @since v1.0.0 * @return char*
*/ */
void string_replace(string_t string, char search, char replace); char* string_replace(char* string, char search, char replace);
/** /**
* @brief Removes all the occurrences of a character in a string. * @brief Removes all whitespace from the start of a string.
*
* NOTE: Mutates the string.
* *
* @param string * @param string
* @param search A character search value. * @return char*
* @since v4.1.0
*/ */
void string_remove_character(string_t string, char search); char* string_trim_start(char* string);
/** /**
* @brief Removes all `character` from the start of a string. * @brief Removes all whitespace from the end of a string.
*
* NOTE: Mutates the string.
* *
* @param string * @param string
* @since v1.0.0 * @return char*
*/ */
void string_trim_start(string_t string, char character); char* string_trim_end(char* string);
/** /**
* @brief Removes all `character` from the end of a string. * @brief Removes all whitespace from the start and end of a string.
*
* NOTE: Mutates the string.
* *
* @param string * @param string
* @since v1.0.0 * @return char*
*/ */
void string_trim_end(string_t string, char character); char* string_trim(char* string);
/**
* @brief Removes all `character` from the start and end of a string.
*
* NOTE: Mutates the string.
*
* @param string
* @since v1.0.0
*/
void string_trim(string_t string, char character);
/** /**
* @brief Return the copy of a string. * @brief Return the copy of a string.
* *
* @param string * @param string
* @return string_t * @return char*
* @since v1.0.0
*/ */
string_t string_copy(const string_t string); char* string_copy(const char* string);
/** /**
* @brief Capitalizes the string. * @brief Capitalizes the string.
* *
* NOTE: Mutates the string.
*
* @param string * @param string
* @since v1.0.0 * @return char*
*/ */
void string_capitalize(string_t string); char* string_capitalize(char* string);
/** /**
* @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.
@ -118,83 +84,68 @@ void string_capitalize(string_t string);
* @param string * @param string
* @param character * @param character
* @return size_t * @return size_t
* @since v1.0.0
*/ */
size_t string_total_occurrences_of_character(string_t string, char character); size_t string_total_occurrences_of_character(char* string, char character);
/** /**
* @brief Reverse the characters in a string. * @brief Reverse the characters in an array.
*
* NOTE: Mutates the string.
* *
* @param string * @param string
* @since v1.0.0 * @return char*
*/ */
void string_reverse(const string_t string); char* string_reverse(const char* string);
/** /**
* @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. * @return true if the strings are equals, false otherwise
* @return false if the strings are not equals.
* @since v1.0.0
*/ */
bool string_equals(const string_t string1, const string_t string2); bool string_equals(const char* string1, const char* string2);
/** /**
* @brief Check if the string is an integer. * @brief Check if the string is a integer.
* *
* @param string * @param string
* @return true if the string is an integer. * @return true if the string is a integer, false otherwise
* @return false if the string is not an integer.
* @since v1.0.0
*/ */
bool string_get_is_integer(const string_t string); bool string_get_is_integer(const char* string);
/** /**
* @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
* @param separator * @param separator
* @param result_size * @return char**
* @return string_t*
* @since v1.0.0
*/ */
string_t* string_split(const string_t string, char separator, size_t* result_size); char** string_split(const char* string, 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
* @param array_length * @return char*
* @return string_t
* @since v1.0.0
*/ */
string_t string_join(string_t* array, const char separator, size_t array_length); char* string_join(char** array, const char separator, size_t array_length);
/** /**
* @brief Concatenate two strings. * @brief Concatenate two strings.
* *
* NOTE: Mutates the string `destination`. * @param string1
* * @param string2
* @param destination * @return char*
* @param source
* @since v1.0.0
*/ */
void string_concatenate(string_t* destination, string_t source); char* string_concatenate(char* string1, char* 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. * @return true if string contains only unique characters, false otherwise
* @return false if string contains duplicate characters.
* @since v1.0.0
*/ */
bool string_get_has_unique_characters(const string_t string); bool string_get_has_unique_characters(const char* 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).
@ -202,127 +153,52 @@ bool string_get_has_unique_characters(const string_t string);
* @param string * @param string
* @param index_start * @param index_start
* @param index_end * @param index_end
* @return string_t * @return char*
* @since v1.0.0
*/ */
string_t string_substring(const string_t string, size_t index_start, size_t index_end); char* string_substring(const char* string, 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
* @param substring * @param substring
* @return true if the string contains the substring. * @return true if the string contains the substring, false otherwise
* @return false if the string does not contain the substring.
* @since v1.0.0
*/ */
bool string_get_is_substring(const string_t string, const string_t substring); bool string_get_is_substring(const char* string, const char* substring);
/** /**
* @brief Format a number to a string with specified separator. * @brief Format a number to a string with specified separator.
* *
* @param number * @param integer
* @param separator * @return char* example: string_get_formatted_number(1000, " ") => "1 000"
* @return string_t
*
* @code
* string_get_formatted_number(1000, " ") // "1 000"
*
* string_get_formatted_number(1000, ",") // "1,000"
* @endcode
* @since v1.0.0
*/ */
string_t string_get_formatted_number(const int64_t number, string_t separator); char* string_get_formatted_number(const long long number, char* 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
* @param character * @param character
* @return string_t * @return char*
* @since v1.0.0
*/ */
string_t string_get_last_occurence_of_character(const string_t string, char character); char* string_get_last_occurence_of_character(const char* string, char character);
/** /**
* @brief Check if a string starts with a substring. * @brief Check if a string starts with a substring.
* *
* @param string * @param string
* @param prefix * @param prefix
* @return true if the string starts with the substring. * @return true if the string starts with the substring, false otherwise
* @return false if the string does not start with the substring.
* @since v1.0.0
*/ */
bool string_starts_with(const string_t string, const string_t prefix); bool string_starts_with(const char* string, const char* prefix);
/** /**
* @brief Check if a string ends with a substring. * @brief Check if a string ends with a substring.
* *
* @param string * @param string
* @param prefix * @param prefix
* @return true if the string ends with the substring. * @return true if the string ends with the substring, false otherwise
* @return false if the string does not end with the substring.
* @since v1.0.0
*/ */
bool string_ends_with(const string_t string, const string_t prefix); bool string_ends_with(const char* string, const char* prefix);
/**
* @brief Returns the position (index + 1) within the string of the first occurrence of the specified substring (0 if not found).
*
* @param string
* @param substring
* @return size_t
*
* @code
* string_position_of("hello world", 'e') // 2
* @endcode
* @since v4.2.0
*/
size_t string_position_of(const string_t string, const char character);
/**
* @brief Returns the position (index + 1) within the string of the last occurrence of the specified substring (0 if not found).
*
* @param string
* @param character
* @return size_t
*
* @code
* string_last_position_of("hello world", 'o') // 8
* @endcode
* @since v4.2.0
*/
size_t string_last_position_of(const string_t string, const char character);
/**
* @brief Pads a `string` with another `pad_string` (multiple times, if needed) until the resulting string reaches the `target_length`. The padding is applied from the start (left) of the string.
*
* @param string The string to pad.
* @param pad_string The string to pad the current string with, to the left.
* @param target_length
* @return string_t
*
* @code
* string_pad_start("hello", " ", 10) // " hello"
* @endcode
* @since v4.3.0
*/
string_t string_pad_start(const string_t string, const string_t pad_string, size_t target_length);
/**
* @brief Pad a number with zeros.
*
* @param number
* @param places
* @return string_t
*
* @code
* string_zero_pad(1, 2) // "01"
*
* string_zero_pad(10, 2) // "10"
* @endcode
* @since v4.3.0
*/
string_t string_zero_pad(uint64_t number, size_t places);
#endif #endif

View File

@ -1,11 +1,21 @@
#include "terminal.h" #include "terminal.h"
string_t terminal_input() { #include <stdbool.h>
#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;
string_t string = malloc(length * sizeof(char)); char* string = malloc(length * sizeof(char));
if (string == NULL) { if (string == NULL) {
perror("Error (terminal_input)");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
*string = '\0'; *string = '\0';
@ -13,7 +23,6 @@ string_t terminal_input() {
length++; length++;
string = realloc(string, length * sizeof(char)); string = realloc(string, length * sizeof(char));
if (string == NULL) { if (string == NULL) {
perror("Error (terminal_input)");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
character_append(string, character); character_append(string, character);
@ -21,12 +30,21 @@ string_t terminal_input() {
return string; return string;
} }
void terminal_print_int(void* value) { void terminal_print_array(void* array, size_t array_size, size_t element_size, void (*print_element)(void*)) {
printf("%d", *(int*)value); printf("[");
for (size_t index = 0; index < array_size; index++) {
void* element = (char*)array + index * element_size;
print_element(element);
bool is_last = index == array_size - 1;
if (!is_last) {
printf(", ");
}
}
printf("]\n");
} }
void terminal_print_bool(void* value) { void terminal_print_int(void* value) {
printf("%s", *(bool*)value ? "true" : "false"); printf("%d", *(int*)value);
} }
void terminal_print_long(void* value) { void terminal_print_long(void* value) {
@ -37,78 +55,23 @@ void terminal_print_unsigned_long(void* value) {
printf("%lu", *(unsigned long*)value); printf("%lu", *(unsigned long*)value);
} }
void terminal_print_float(void* value) {
printf("%f", *(float*)value);
}
void terminal_print_double(void* value) {
printf("%f", *(double*)value);
}
void terminal_print_int8_t(void* value) {
printf("%d", *(int8_t*)value);
}
void terminal_print_int16_t(void* value) {
printf("%d", *(int16_t*)value);
}
void terminal_print_int32_t(void* value) {
printf("%d", *(int32_t*)value);
}
void terminal_print_int64_t(void* value) {
printf("%ld", *(int64_t*)value);
}
void terminal_print_uint8_t(void* value) {
printf("%u", *(uint8_t*)value);
}
void terminal_print_uint16_t(void* value) {
printf("%u", *(uint16_t*)value);
}
void terminal_print_uint32_t(void* value) {
printf("%u", *(uint32_t*)value);
}
void terminal_print_uint64_t(void* value) {
printf("%lu", *(uint64_t*)value);
}
void terminal_print_char(void* value) { void terminal_print_char(void* value) {
printf("%c", *(string_t)value); printf("%c", *(char*)value);
}
void terminal_print_array(void* array, size_t array_size, size_t element_size, void (*print_element)(void*)) {
printf("[");
for (size_t index = 0; index < array_size; index++) {
void* element = (string_t)array + index * element_size;
print_element(element);
bool is_last = index == array_size - 1;
if (!is_last) {
printf(", ");
}
}
printf("]\n");
} }
void terminal_print_string(void* value) { void terminal_print_string(void* value) {
printf("%s", (string_t)value); printf("%s", (char*)value);
} }
void terminal_print_stack(struct stack* stack, void (*print_element)(void*)) { void terminal_print_stack(struct stack* stack, void (*print_element)(void*)) {
if (stack == NULL) { if (stack == NULL) {
errno = EINVAL;
perror("Error (terminal_print_stack)");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
struct stack_node* node_current = stack->first; struct stack_node* node_current = stack->first;
while (node_current != NULL) { while (node_current != NULL) {
printf("|\t"); printf("|\t");
void* element = node_current->data; void* element = (char*)node_current->data;
print_element(element); print_element(&element);
node_current = node_current->next; node_current = node_current->next;
printf("\t|\n"); printf("\t|\n");
} }
@ -116,15 +79,13 @@ void terminal_print_stack(struct stack* stack, void (*print_element)(void*)) {
void terminal_print_queue(struct queue* queue, void (*print_element)(void*)) { void terminal_print_queue(struct queue* queue, void (*print_element)(void*)) {
if (queue == NULL) { if (queue == NULL) {
errno = EINVAL;
perror("Error (terminal_print_queue)");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
struct queue_node* node_current = queue->first; struct queue_node* node_current = queue->first;
while (node_current != NULL) { while (node_current != NULL) {
printf("|\t"); printf("|\t");
void* element = node_current->data; void* element = (char*)node_current->data;
print_element(element); print_element(&element);
node_current = node_current->next; node_current = node_current->next;
printf("\t|\n"); printf("\t|\n");
} }
@ -132,49 +93,30 @@ void terminal_print_queue(struct queue* queue, void (*print_element)(void*)) {
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*)) {
if (linked_list == NULL) { if (linked_list == NULL) {
errno = EINVAL;
perror("Error (terminal_print_linked_list)");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
struct linked_list_node* node_current = linked_list->head; struct linked_list_node* node_current = linked_list->head;
while (node_current != NULL) { while (node_current != NULL) {
void* element = (string_t)node_current->data; void* element = (char*)node_current->data;
node_current = node_current->next; node_current = node_current->next;
print_element(element); print_element(&element);
printf(" -> "); printf(" -> ");
} }
printf("NULL\n"); printf("NULL\n");
} }
void terminal_print_hash_map(struct hash_map* hash_map, void (*print_element)(void*)) { void terminal_print_dictionary(struct dictionary* dictionary, void (*print_element)(void*)) {
if (hash_map == NULL) { if (dictionary == NULL) {
errno = EINVAL;
perror("Error (terminal_print_hash_map)");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
printf("{\n"); printf("{\n");
string_t* keys = hash_map_get_keys(hash_map); for (size_t index = 0; index < dictionary->length; index++) {
for (size_t index = 0; index < hash_map->length; index++) { struct dictionary_item* item = dictionary->items[index];
string_t key = keys[index];
void* value = hash_map_get(hash_map, key);
printf("\t\""); printf("\t\"");
terminal_print_string(key); terminal_print_string(item->key);
printf("\" -> "); printf("\" -> ");
print_element(value); print_element(&item->data);
printf("\n"); printf("\n");
} }
printf("}\n"); printf("}\n");
free(keys);
}
void terminal_print_array_list(struct array_list* list, void (*print_element)(void*)) {
printf("[");
for (size_t index = 0; index < list->size; index++) {
void* element = list->data[index];
print_element(element);
if (index < list->size - 1) {
printf(", ");
}
}
printf("]\n");
} }

View File

@ -1,210 +1,38 @@
#ifndef __LIBCPROJECT_TERMINAL__ #ifndef __TERMINAL__
#define __LIBCPROJECT_TERMINAL__ #define __TERMINAL__
#include <errno.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include "array_list.h" #include "dictionary.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.
* *
* @return string_t * @return char*
* @since v1.0.0
*/ */
string_t terminal_input(); char* terminal_input();
/**
* @brief Print a int.
*
* @param value
* @since v1.0.0
*/
void terminal_print_int(void* value);
/**
* @brief Print a boolean.
*
* @param value
* @since v5.0.0
*/
void terminal_print_bool(void* value);
/**
* @brief Print a long.
*
* @param value
* @since v1.0.0
*/
void terminal_print_long(void* value);
/**
* @brief Print a unsigned long.
*
* @param value
* @since v1.0.0
*/
void terminal_print_unsigned_long(void* value);
/**
* @brief Print a float.
*
* @param value
* @since v5.0.0
*/
void terminal_print_float(void* value);
/**
* @brief Print a double.
*
* @param value
* @since v5.0.0
*/
void terminal_print_double(void* value);
/**
* @brief Print a int8_t.
*
* @param value
* @since v5.0.0
*/
void terminal_print_int8_t(void* value);
/**
* @brief Print a int16_t.
*
* @param value
* @since v5.0.0
*/
void terminal_print_int16_t(void* value);
/**
* @brief Print a int32_t.
*
* @param value
* @since v5.0.0
*/
void terminal_print_int32_t(void* value);
/**
* @brief Print a int64_t.
*
* @param value
* @since v5.0.0
*/
void terminal_print_int64_t(void* value);
/**
* @brief Print a uint8_t.
*
* @param value
* @since v5.0.0
*/
void terminal_print_uint8_t(void* value);
/**
* @brief Print a uint16_t.
*
* @param value
* @since v5.0.0
*/
void terminal_print_uint16_t(void* value);
/**
* @brief Print a uint32_t.
*
* @param value
* @since v5.0.0
*/
void terminal_print_uint32_t(void* value);
/**
* @brief Print a uint64_t.
*
* @param value
* @since v5.0.0
*/
void terminal_print_uint64_t(void* value);
/**
* @brief Print a char.
*
* @param value
* @since v1.0.0
*/
void terminal_print_char(void* value);
/**
* @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*));
/** void terminal_print_int(void* value);
* @brief Print a string.
* void terminal_print_long(void* value);
* @param value
* @since v1.0.0 void terminal_print_unsigned_long(void* value);
*/
void terminal_print_char(void* value);
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 list
* @param print_element
* @since v3.0.0
*/
void terminal_print_array_list(struct array_list* list, void (*print_element)(void*));
#endif #endif

View File

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

View File

@ -1,20 +1,15 @@
#ifndef __LIBCPROJECT__ #ifndef __LIBCPROJECT__
#define __LIBCPROJECT__ #define __LIBCPROJECT__
#include "lib/array_list.h"
#include "lib/assert.h"
#include "lib/character.h" #include "lib/character.h"
#include "lib/convert.h" #include "lib/convert.h"
#include "lib/date.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

133
main.c
View File

@ -4,135 +4,8 @@
#include "libcproject.h" #include "libcproject.h"
int main() { int main() {
int integer = 5; char* string = "Hello, world!";
terminal_print_int(&integer); printf("%s\n", string);
printf("\n"); printf("string_length = %ld\n", string_get_length(string));
bool boolean = true;
printf("terminal_print_bool: ");
terminal_print_bool(&boolean);
printf(", ");
boolean = false;
terminal_print_bool(&boolean);
printf("\n");
long integer_long = 5;
printf("terminal_print_long: ");
terminal_print_long(&integer_long);
printf("\n");
unsigned long integer_unsigned_long = 5;
printf("terminal_print_unsigned_long: ");
terminal_print_unsigned_long(&integer_unsigned_long);
printf("\n");
float floating_point = 5.5;
printf("terminal_print_float: ");
terminal_print_float(&floating_point);
printf("\n");
double floating_point_double = 5.5;
printf("terminal_print_double: ");
terminal_print_double(&floating_point_double);
printf("\n");
int8_t integer_8 = 5;
printf("terminal_print_int8_t: ");
terminal_print_int8_t(&integer_8);
printf("\n");
int16_t integer_16 = 5;
printf("terminal_print_int16_t: ");
terminal_print_int16_t(&integer_16);
printf("\n");
int32_t integer_32 = 5;
printf("terminal_print_int32_t: ");
terminal_print_int32_t(&integer_32);
printf("\n");
int64_t integer_64 = 5;
printf("terminal_print_int64_t: ");
terminal_print_int64_t(&integer_64);
printf("\n");
uint8_t integer_unsigned_8 = 5;
printf("terminal_print_uint8_t: ");
terminal_print_uint8_t(&integer_unsigned_8);
printf("\n");
uint16_t integer_unsigned_16 = 5;
printf("terminal_print_uint16_t: ");
terminal_print_uint16_t(&integer_unsigned_16);
printf("\n");
uint32_t integer_unsigned_32 = 5;
printf("terminal_print_uint32_t: ");
terminal_print_uint32_t(&integer_unsigned_32);
printf("\n");
uint64_t integer_unsigned_64 = 5;
printf("terminal_print_uint64_t: ");
terminal_print_uint64_t(&integer_unsigned_64);
printf("\n");
char character = 'c';
printf("terminal_print_char: ");
terminal_print_char(&character);
printf("\n");
int array[] = {1, 2, 3, 4, 5};
printf("terminal_print_array: ");
terminal_print_array(array, 5, sizeof(int), terminal_print_int);
string_t string = "Hello, world!";
printf("terminal_print_string: ");
terminal_print_string(string);
printf("\n");
struct stack* stack = stack_initialization();
stack_push(stack, &integer);
printf("terminal_print_stack: ");
terminal_print_stack(stack, terminal_print_int);
stack_free(stack);
struct queue* queue = queue_initialization();
queue_push(queue, &integer);
printf("terminal_print_queue: ");
terminal_print_queue(queue, terminal_print_int);
queue_free(queue);
struct linked_list* linked_list = linked_list_initialization();
linked_list_add_after_last(linked_list, string);
linked_list_add_after_last(linked_list, string);
printf("terminal_print_linked_list: ");
terminal_print_linked_list(linked_list, terminal_print_string);
linked_list_free(linked_list);
struct hash_map* hash_map = hash_map_initialization();
hash_map_add(hash_map, "key", &integer);
printf("terminal_print_hash_map: ");
terminal_print_hash_map(hash_map, terminal_print_int);
hash_map_free(hash_map);
struct array_list* array_list = array_list_initialization();
array_list_add(array_list, &integer);
array_list_add(array_list, &integer);
printf("terminal_print_array_list: ");
terminal_print_array_list(array_list, terminal_print_int);
array_list_free(array_list);
struct date* date = date_get_now_utc();
string_t iso_string = date_to_iso_string(date);
printf("date_get_now_utc = %s\n", iso_string);
free(iso_string);
free(date);
date = date_get_now_local();
iso_string = date_to_iso_string(date);
printf("date_get_now_local = %s\n", iso_string);
free(iso_string);
free(date);
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }

View File

@ -3,23 +3,21 @@
#include "libcproject.h" #include "libcproject.h"
int main(int argc, string_t* argv) { int main(int argc, char* 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;
} }
string_t content = string_copy("#ifndef __LIBCPROJECT_VERSION__\n"); char* content = "#ifndef __LIBCPROJECT_VERSION__\n";
string_concatenate(&content, "#define __LIBCPROJECT_VERSION__ \""); content = string_concatenate(content, "#define __LIBCPROJECT_VERSION__ \"");
string_concatenate(&content, argv[1]); content = string_concatenate(content, argv[1]);
string_concatenate(&content, "\"\n\n"); content = string_concatenate(content, "\"\n\n");
string_concatenate(&content, "#endif\n"); content = string_concatenate(content, "#endif\n");
int result = filesystem_write("./version.h", (byte_t*)content, string_get_length(content)); int result = filesystem_write("./version.h", 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");
perror("Error (set_version)");
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;
} }

View File

@ -1,48 +0,0 @@
#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);
list = array_list_initialization();
array_list_add(list, (void *)'a');
array_list_add(list, (void *)'b');
array_list_add(list, (void *)'c');
array_list_remove(list, 1);
assert(array_list_get(list, 0) == (void *)'a');
assert(array_list_get(list, 1) == (void *)'c');
assert(list->size == 2);
array_list_free(list);
}

View File

@ -1,13 +0,0 @@
#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,5 +1,12 @@
#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();
@ -20,7 +27,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[6] = "abcd"; char string2[5] = "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,12 +1,6 @@
#ifndef __CHARACTER_TEST__ #ifndef __CHARACTER_TEST__
#define __CHARACTER_TEST__ #define __CHARACTER_TEST__
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include "libcproject.h"
void character_test(); void character_test();
void character_append_test(); void character_append_test();

View File

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

View File

@ -1,191 +0,0 @@
#include "date_test.h"
void date_test() {
date_copy_test();
date_to_iso_string_test();
date_to_iso_string_without_time_test();
date_from_iso_string_test();
date_get_is_leap_year_test();
date_duration_seconds_between_2_dates_test();
date_to_utc_test();
date_get_age_test();
}
void date_copy_test() {
struct date *date = malloc(sizeof(struct date));
date->year = 2024;
date->month = 9;
date->day = 10;
date->hours = 20;
date->minutes = 34;
date->seconds = 25;
date->milliseconds = 76;
date->timezone_utc_offset = 0;
struct date *date2 = date_copy(date);
assert(date != date2);
assert(date->year == date2->year);
assert(date->month == date2->month);
assert(date->day == date2->day);
assert(date->hours == date2->hours);
assert(date->minutes == date2->minutes);
assert(date->seconds == date2->seconds);
assert(date->milliseconds == date2->milliseconds);
assert(date->timezone_utc_offset == date2->timezone_utc_offset);
date->year = 2025;
assert(date->year == 2025);
assert(date2->year == 2024);
free(date);
free(date2);
}
void date_to_iso_string_test() {
struct date *date = malloc(sizeof(struct date));
date->year = 2024;
date->month = 9;
date->day = 10;
date->hours = 20;
date->minutes = 34;
date->seconds = 25;
date->milliseconds = 76;
date->timezone_utc_offset = 0;
string_t iso_string = date_to_iso_string(date);
assert(assert_string_equal(iso_string, "2024-09-10T20:34:25.076Z"));
free(iso_string);
free(date);
}
void date_to_iso_string_without_time_test() {
struct date *date = malloc(sizeof(struct date));
date->year = 2024;
date->month = 9;
date->day = 10;
date->hours = 20;
date->minutes = 34;
date->seconds = 25;
date->milliseconds = 76;
date->timezone_utc_offset = 0;
string_t iso_string = date_to_iso_string_without_time(date);
assert(assert_string_equal(iso_string, "2024-09-10"));
free(iso_string);
free(date);
}
void date_from_iso_string_test() {
string_t iso_string = "2024-09-10T20:34:25.076Z";
struct date *date = date_from_iso_string(iso_string);
assert(date->year == 2024);
assert(date->month == 9);
assert(date->day == 10);
assert(date->hours == 20);
assert(date->minutes == 34);
assert(date->seconds == 25);
assert(date->milliseconds == 76);
assert(date->timezone_utc_offset == 0);
free(date);
}
void date_get_is_leap_year_test() {
assert(date_get_is_leap_year(2020));
assert(!date_get_is_leap_year(2021));
assert(!date_get_is_leap_year(2022));
assert(!date_get_is_leap_year(2023));
assert(date_get_is_leap_year(2024));
}
void date_duration_seconds_between_2_dates_test() {
struct date *date1 = date_from_iso_string("2024-09-10T20:34:25.076Z");
struct date *date2 = date_from_iso_string("2024-09-10T20:34:25.076Z");
assert(date_duration_seconds_between_2_dates(date1, date2) == 0);
free(date1);
free(date2);
date1 = date_from_iso_string("2024-09-10T20:34:25.076Z");
date2 = date_from_iso_string("2024-09-10T23:34:26.076Z");
assert(date_duration_seconds_between_2_dates(date1, date2) == 10801);
free(date1);
free(date2);
date1 = date_from_iso_string("2024-09-10T20:34:25.076Z");
date2 = date_from_iso_string("2024-09-10T20:48:25.076Z");
assert(date_duration_seconds_between_2_dates(date1, date2) == 840);
free(date1);
free(date2);
date1 = date_from_iso_string("2024-09-10T20:34:25.076Z");
date2 = date_from_iso_string("2024-09-10T20:34:38.076Z");
assert(date_duration_seconds_between_2_dates(date1, date2) == 13);
free(date1);
free(date2);
}
void date_to_utc_test() {
struct date *date = date_from_iso_string("2024-09-10T20:34:25.076Z");
date->timezone_utc_offset = 3;
date_to_utc(date);
assert(date->timezone_utc_offset == 0);
string_t iso_string = date_to_iso_string(date);
assert(assert_string_equal(iso_string, "2024-09-10T17:34:25.076Z"));
free(iso_string);
free(date);
date = date_from_iso_string("2024-09-10T20:34:25.076Z");
date->timezone_utc_offset = -3;
date_to_utc(date);
assert(date->timezone_utc_offset == 0);
iso_string = date_to_iso_string(date);
assert(assert_string_equal(iso_string, "2024-09-10T23:34:25.076Z"));
free(iso_string);
free(date);
date = date_from_iso_string("2024-01-01T00:00:00.000Z");
date->timezone_utc_offset = 3;
date_to_utc(date);
assert(date->timezone_utc_offset == 0);
iso_string = date_to_iso_string(date);
assert(assert_string_equal(iso_string, "2023-12-31T21:00:00.000Z"));
free(iso_string);
free(date);
date = date_from_iso_string("2023-12-31T21:00:00.000Z");
date->timezone_utc_offset = -4;
date_to_utc(date);
assert(date->timezone_utc_offset == 0);
iso_string = date_to_iso_string(date);
assert(assert_string_equal(iso_string, "2024-01-01T01:00:00.000Z"));
free(iso_string);
free(date);
}
void date_get_age_test() {
struct date *birth_date = date_from_iso_string("1980-02-20T00:00:00.000Z");
struct date *current_date = date_from_iso_string("2018-03-20T00:00:00.000Z");
assert(date_get_age(birth_date, current_date) == 38);
free(birth_date);
free(current_date);
birth_date = date_from_iso_string("1980-07-20T00:00:00.000Z");
current_date = date_from_iso_string("2018-03-20T00:00:00.000Z");
assert(date_get_age(birth_date, current_date) == 37);
free(birth_date);
free(current_date);
birth_date = date_from_iso_string("1980-03-20T00:00:00.000Z");
current_date = date_from_iso_string("2018-03-20T00:00:00.000Z");
assert(date_get_age(birth_date, current_date) == 38);
free(birth_date);
free(current_date);
birth_date = date_from_iso_string("1980-03-25T00:00:00.000Z");
current_date = date_from_iso_string("2018-03-20T00:00:00.000Z");
assert(date_get_age(birth_date, current_date) == 37);
free(birth_date);
free(current_date);
}

View File

@ -1,26 +0,0 @@
#ifndef __DATE_TEST__
#define __DATE_TEST__
#include <assert.h>
#include "libcproject.h"
void date_test();
void date_copy_test();
void date_to_iso_string_test();
void date_to_iso_string_without_time_test();
void date_from_iso_string_test();
void date_get_is_leap_year_test();
void date_duration_seconds_between_2_dates_test();
void date_to_utc_test();
void date_get_age_test();
#endif

33
test/dictionary_test.c Normal file
View File

@ -0,0 +1,33 @@
#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"));
}

6
test/dictionary_test.h Normal file
View File

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

View File

@ -1,28 +0,0 @@
#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);
}

View File

@ -1,12 +0,0 @@
#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,5 +1,12 @@
#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();
@ -13,7 +20,6 @@ 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() {
@ -26,7 +32,6 @@ 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() {
@ -39,7 +44,6 @@ 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() {
@ -57,7 +61,6 @@ 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() {
@ -78,8 +81,6 @@ 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() {
@ -95,5 +96,4 @@ 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,13 +1,6 @@
#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,11 +1,9 @@
#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 "date_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"
@ -13,11 +11,9 @@
#include "string_test.h" #include "string_test.h"
int main() { int main() {
array_list_test();
character_test(); character_test();
convert_test(); convert_test();
date_test(); dictionary_test();
hash_map_test();
linked_list_test(); linked_list_test();
mathematics_test(); mathematics_test();
queue_test(); queue_test();

View File

@ -1,16 +1,15 @@
#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();
mathematics_root_test(); mathematics_root_test();
mathematics_square_root_test(); mathematics_square_root_test();
mathematics_factorial_test(); mathematics_factorial_test();
mathematics_opposite_test();
mathematics_max_test();
mathematics_max_values_test();
mathematics_min_test();
mathematics_min_values_test();
} }
void mathematics_absolute_value_test() { void mathematics_absolute_value_test() {
@ -61,38 +60,3 @@ void mathematics_factorial_test() {
assert(mathematics_factorial(9) == 362880); assert(mathematics_factorial(9) == 362880);
assert(mathematics_factorial(10) == 3628800); assert(mathematics_factorial(10) == 3628800);
} }
void mathematics_opposite_test() {
assert(mathematics_opposite(-7) == 7);
assert(mathematics_opposite(7) == -7);
}
void mathematics_max_test() {
assert(mathematics_max(0, 0) == 0);
assert(mathematics_max(0, 1) == 1);
assert(mathematics_max(2, 0) == 2);
assert(mathematics_max(54, 37) == 54);
}
void mathematics_max_values_test() {
int64_t values[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
assert(mathematics_max_values(values, 10) == 9);
int64_t values2[] = {8, 6, 4, 7};
assert(mathematics_max_values(values2, 4) == 8);
}
void mathematics_min_test() {
assert(mathematics_min(0, 0) == 0);
assert(mathematics_min(3, 5) == 3);
assert(mathematics_min(2, 1) == 1);
assert(mathematics_min(54, 37) == 37);
}
void mathematics_min_values_test() {
int64_t values[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
assert(mathematics_min_values(values, 10) == 0);
int64_t values2[] = {9, 6, 8, 7};
assert(mathematics_min_values(values2, 4) == 6);
}

View File

@ -1,10 +1,6 @@
#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();
@ -17,14 +13,4 @@ void mathematics_square_root_test();
void mathematics_factorial_test(); void mathematics_factorial_test();
void mathematics_opposite_test();
void mathematics_max_test();
void mathematics_max_values_test();
void mathematics_min_test();
void mathematics_min_values_test();
#endif #endif

View File

@ -1,5 +1,11 @@
#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();
@ -10,7 +16,6 @@ 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() {
@ -23,7 +28,6 @@ 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() {
@ -37,5 +41,4 @@ 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,12 +1,6 @@
#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,5 +1,11 @@
#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();
@ -10,7 +16,6 @@ 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() {
@ -23,7 +28,6 @@ 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() {
@ -37,5 +41,4 @@ 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,12 +1,6 @@
#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,11 +1,17 @@
#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();
string_to_lowercase_test(); string_to_lowercase_test();
string_replace_test(); string_replace_test();
string_remove_character_test();
string_trim_start_test(); string_trim_start_test();
string_trim_end_test(); string_trim_end_test();
string_trim_test(); string_trim_test();
@ -25,102 +31,81 @@ void string_test() {
string_get_last_occurence_of_character_test(); string_get_last_occurence_of_character_test();
string_starts_with_test(); string_starts_with_test();
string_ends_with_test(); string_ends_with_test();
string_position_of_test();
string_last_position_of_test();
string_pad_start_test();
string_zero_pad_test();
} }
void string_get_length_test() { void string_get_length_test() {
string_t string = "Hello World!"; char *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);
assert(strlen(string) == string_length);
} }
void string_to_uppercase_test() { void string_to_uppercase_test() {
string_t string = string_copy("heLlO world"); char *string = "heLlO world";
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() {
string_t string = string_copy("HellO WoRLd"); char *string = "HellO WoRLd";
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() {
string_t string = string_copy("hello world"); char *string = "hello world";
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_remove_character_test() {
string_t string = string_copy("hello world");
string_remove_character(string, 'l');
assert(assert_string_equal(string, "heo word"));
free(string);
} }
void string_trim_start_test() { void string_trim_start_test() {
string_t string = string_copy(" hello world "); char *string = " hello world ";
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() {
string_t string = string_copy(" hello world "); char *string = " hello world ";
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() {
string_t string = string_copy(" hello world "); char *string = " hello world ";
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() {
string_t string = "hello world"; char *string = "hello world";
string_t string2 = string_copy(string); char *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() {
string_t string = string_copy("hello world"); char *string = "hello world";
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() {
string_t string = "hello world"; char *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() {
string_t string = string_copy("hello world"); char *string = "hello world";
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() {
string_t string1 = "hello world"; char *string1 = "hello world";
string_t string2 = "dlrow olleh"; char *string2 = "dlrow olleh";
string_t string3 = "dlrow olleh"; char *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));
@ -139,46 +124,29 @@ void string_get_is_integer_test() {
} }
void string_split_test() { void string_split_test() {
string_t string = "abc def ghij kl"; char *string = "abc def ghij kl";
size_t result_length = 0; size_t result_length = 0;
string_t* result = string_split(string, ' ', &result_length); char **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() {
string_t string = "abc def ghij kl"; char *string = "abc def ghij kl";
size_t result_length = 0; size_t result_length = 0;
string_t* result = string_split(string, ' ', &result_length); char **result = string_split(string, ' ', &result_length);
string_t new_string = string_join(result, ' ', result_length); char *new_string = string_join(result, ' ', result_length);
string_t new_string2 = string_join(result, '+', result_length); char *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() {
string_t result = string_copy("abc"); assert(assert_string_equal(string_concatenate("abc", "def"), "abcdef"));
string_concatenate(&result, "def"); assert(assert_string_equal(string_concatenate("abc ", " defghi"), "abc defghi"));
assert(assert_string_equal(result, "abcdef"));
free(result);
result = string_copy("abcz");
string_concatenate(&result, " defghi");
assert(assert_string_equal(result, "abcz defghi"));
free(result);
} }
void string_get_has_unique_characters_test() { void string_get_has_unique_characters_test() {
@ -188,14 +156,13 @@ void string_get_has_unique_characters_test() {
} }
void string_substring_test() { void string_substring_test() {
string_t string = "abcdef"; char *string = "abcdef";
string_t substring = string_substring(string, 1, 3); char *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() {
string_t string = "abcdef"; char *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"));
@ -207,61 +174,33 @@ void string_get_is_substring_test() {
} }
void string_get_formatted_number_test() { void string_get_formatted_number_test() {
string_t result = string_get_formatted_number(1000, " "); assert(assert_string_equal(string_get_formatted_number(1000, " "), "1 000"));
assert(assert_string_equal(result, "1 000")); assert(assert_string_equal(string_get_formatted_number(123, ","), "123"));
free(result); assert(assert_string_equal(string_get_formatted_number(1234, ","), "1,234"));
assert(assert_string_equal(string_get_formatted_number(12345, ","), "12,345"));
result = string_get_formatted_number(123, ","); assert(assert_string_equal(string_get_formatted_number(123456, ","), "123,456"));
assert(assert_string_equal(result, "123")); assert(assert_string_equal(string_get_formatted_number(1234567, ","), "1,234,567"));
free(result); assert(assert_string_equal(string_get_formatted_number(12345678, ","), "12,345,678"));
assert(assert_string_equal(string_get_formatted_number(123456789, ","), "123,456,789"));
result = string_get_formatted_number(1234, ","); assert(assert_string_equal(string_get_formatted_number(1234567890, ","), "1,234,567,890"));
assert(assert_string_equal(result, "1,234")); assert(assert_string_equal(string_get_formatted_number(-123, ","), "-123"));
free(result); assert(assert_string_equal(string_get_formatted_number(-1234, ","), "-1,234"));
assert(assert_string_equal(string_get_formatted_number(-12345, ","), "-12,345"));
result = string_get_formatted_number(12345, ","); assert(assert_string_equal(string_get_formatted_number(-123456, ","), "-123,456"));
assert(assert_string_equal(result, "12,345")); assert(assert_string_equal(string_get_formatted_number(-1234567, ","), "-1,234,567"));
free(result); assert(assert_string_equal(string_get_formatted_number(-12345678, ","), "-12,345,678"));
assert(assert_string_equal(string_get_formatted_number(-123456789, ","), "-123,456,789"));
result = string_get_formatted_number(-123, ","); assert(assert_string_equal(string_get_formatted_number(-1234567890, ","), "-1,234,567,890"));
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() {
string_t string = "abcdef"; char *string = "abcdef";
assert(assert_string_equal(string_get_last_occurence_of_character(string, 'a'), "abcdef"));
string_t result = string_get_last_occurence_of_character(string, 'a'); assert(assert_string_equal(string_get_last_occurence_of_character(string, 'b'), "bcdef"));
assert(assert_string_equal(result, "abcdef")); assert(assert_string_equal(string_get_last_occurence_of_character(string, 'c'), "cdef"));
free(result); assert(assert_string_equal(string_get_last_occurence_of_character(string, 'd'), "def"));
assert(assert_string_equal(string_get_last_occurence_of_character(string, 'e'), "ef"));
result = string_get_last_occurence_of_character(string, 'b'); assert(assert_string_equal(string_get_last_occurence_of_character(string, 'f'), "f"));
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() {
@ -281,55 +220,3 @@ void string_ends_with_test() {
assert(!string_ends_with("abcdef", "bcd")); assert(!string_ends_with("abcdef", "bcd"));
assert(!string_ends_with("abcdef", "abcdefg")); assert(!string_ends_with("abcdef", "abcdefg"));
} }
void string_position_of_test() {
assert(string_position_of("hello world", 'e') == 2);
assert(string_position_of("hello world", 'o') == 5);
assert(string_position_of("abcdef", 'a') == 1);
assert(string_position_of("abcdef", 'b') == 2);
assert(string_position_of("abcdef", 'c') == 3);
assert(string_position_of("abcdef", 'd') == 4);
assert(string_position_of("abcdef", 'e') == 5);
assert(string_position_of("abcdef", 'f') == 6);
assert(string_position_of("abcdef", 'g') == 0);
}
void string_last_position_of_test() {
assert(string_last_position_of("hello world", 'e') == 2);
assert(string_last_position_of("hello world", 'o') == 8);
assert(string_last_position_of("abcdef", 'a') == 1);
assert(string_last_position_of("abcdef", 'b') == 2);
assert(string_last_position_of("abcdef", 'c') == 3);
assert(string_last_position_of("abcdef", 'd') == 4);
assert(string_last_position_of("abcdef", 'e') == 5);
assert(string_last_position_of("abcdef", 'f') == 6);
assert(string_last_position_of("abcdef", 'g') == 0);
}
void string_pad_start_test() {
string_t result = string_pad_start("hello", "ab", 10);
assert(assert_string_equal(result, "ababahello"));
free(result);
result = string_pad_start("hello", "ab", 4);
assert(assert_string_equal(result, "hell"));
free(result);
result = string_pad_start("hello", "ab", 5);
assert(assert_string_equal(result, "hello"));
free(result);
result = string_pad_start("hello", "ab", 6);
assert(assert_string_equal(result, "ahello"));
free(result);
}
void string_zero_pad_test() {
string_t result = string_zero_pad(1, 2);
assert(assert_string_equal(result, "01"));
free(result);
result = string_zero_pad(10, 2);
assert(assert_string_equal(result, "10"));
free(result);
}

View File

@ -1,12 +1,6 @@
#ifndef __STRING_TEST__ #ifndef __STRING_TEST__
#define __STRING_TEST__ #define __STRING_TEST__
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include "libcproject.h"
void string_test(); void string_test();
void string_get_length_test(); void string_get_length_test();
@ -17,8 +11,6 @@ void string_to_lowercase_test();
void string_replace_test(); void string_replace_test();
void string_remove_character_test();
void string_trim_start_test(); void string_trim_start_test();
void string_trim_end_test(); void string_trim_end_test();
@ -57,12 +49,4 @@ void string_starts_with_test();
void string_ends_with_test(); void string_ends_with_test();
void string_position_of_test();
void string_last_position_of_test();
void string_pad_start_test();
void string_zero_pad_test();
#endif #endif

19
test/test.c Normal file
View File

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

10
test/test.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef __TEST__
#define __TEST__
#include <stdbool.h>
bool assert_string_equal(const char *actual, const char *expected);
bool assert_string_not_equal(const char *actual, const char *expected);
#endif

View File

@ -1,4 +1,4 @@
#ifndef __LIBCPROJECT_VERSION__ #ifndef __LIBCPROJECT_VERSION__
#define __LIBCPROJECT_VERSION__ "5.1.0" #define __LIBCPROJECT_VERSION__ "1.1.0"
#endif #endif