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

Compare commits

...

42 Commits

Author SHA1 Message Date
semantic-release-bot
d14b56904e
chore(release): 5.1.0 [skip ci] 2024-10-08 06:50:16 +00:00
b0fd3bf373
feat(date): add date_get_age
Fixes #7
2024-10-08 08:47:16 +02:00
95ad9f24f4
feat(date): add date_get_now_local
Related #7
2024-10-08 08:37:24 +02:00
ded2ca0795
feat(date): add date_get_now_utc
Related #7
2024-10-08 08:36:14 +02:00
semantic-release-bot
a7aef0b954
chore(release): 5.0.0 [skip ci] 2024-09-25 13:00:04 +00:00
336bbf6197
feat: add assert module 2024-09-25 14:57:34 +02:00
1be12c2a97
perf: allow to init array_list with initial capacity
Fixes #8
2024-09-25 14:34:33 +02:00
51d7123c8d
fix!: usage of stdint instead of int types for cross-platform compatibility
BREAKING CHANGE: Functions signatures changed.

Fixes #9
2024-09-25 14:26:15 +02:00
6ac47429e8
feat: use double instead of float for better precision
BREAKING CHANGE: Functions signatures changed
in the `mathematics` module.

BREAKING CHANGE: Renamed `MATHEMATICS_FLOAT_PRECISION` to `MATHEMATICS_DOUBLE_PRECISION`
2024-09-25 12:53:28 +02:00
semantic-release-bot
b3c17983b3
chore(release): 4.3.0 [skip ci] 2024-09-15 17:24:10 +00:00
aff8233483
feat: add date module 2024-09-15 19:21:35 +02:00
e1d9b714db
chore: update @since version 2024-09-15 18:43:39 +02:00
740aab1fcf
chore: rename master branch to main 2024-09-15 18:39:10 +02:00
fd6330c08c
build(deps): update latest 2024-09-15 18:38:21 +02:00
164ea2a7f8
docs: fix string_get_formatted_number examples 2024-09-15 18:25:01 +02:00
2fd8d102e9
feat: add mathematics_max, mathematics_min
Also add `mathematics_max_values` and
`mathematics_min_values` to check in array.
2024-09-13 15:35:19 +02:00
85ce5228ef
feat: add mathematics_opposite 2024-09-13 14:44:26 +02:00
c49d5f5421
feat: add string_zero_pad 2024-09-12 12:31:58 +02:00
35b868d0c1
feat: add string_pad_start 2024-09-12 12:22:53 +02:00
7683aa1db7
docs(license): add email address 2024-01-30 01:25:17 +01:00
semantic-release-bot
6eee39fffb
chore(release): 4.2.1 [skip ci] 2023-12-26 20:20:38 +00:00
ab9860e969
fix: markdownlint in LICENSE 2023-12-26 21:19:20 +01:00
semantic-release-bot
a50773e058
chore(release): 4.2.0 [skip ci] 2023-12-26 19:47:09 +00:00
1e0bf99ef6
feat: add string_last_position_of 2023-12-26 20:40:46 +01:00
ec6e748d24
feat: add string_position_of 2023-12-26 20:30:54 +01:00
9bb21e070f
build(deps): update latest 2023-12-26 19:42:12 +01:00
bb9c7a1668
Merge branch 'master' of github.com:theoludwig/libcproject 2023-10-23 23:02:35 +02:00
211648d29f
chore: better Prettier config for easier reviews 2023-10-23 23:02:29 +02:00
semantic-release-bot
574aeb414e
chore(release): 4.1.1 [skip ci] 2023-10-13 09:07:49 +00:00
ChepakiLeCookie
e0115dd7d9
fix: error in array_list_remove (always removed the last index and not the index given) (#6)
Co-authored-by: Maxime Rumpler <mrumpler68@gmail.com>
2023-10-13 11:04:38 +02:00
semantic-release-bot
269b1f7451
chore(release): 4.1.0 [skip ci] 2023-08-10 09:06:44 +00:00
c6df05e634
refactor: avoid usage of char*, instead use string_t 2023-08-10 00:32:49 +02:00
07e2f4db45
fix: convert numbers base to another only accept unsigned integers 2023-08-09 23:29:58 +02:00
b9ba3fbff4
docs: consistency improvements 2023-08-09 21:08:15 +02:00
7ef38fa993
chore: always use apt instead of apt-get 2023-08-09 20:29:19 +02:00
f99e4941e4
fix: correct usage of malloc and sizeof for structs 2023-08-09 20:25:03 +02:00
6505e3ba49
feat: add string_remove_character 2023-08-09 20:21:33 +02:00
f0716c2e12
docs: invalid @param for character_append 2023-08-09 20:17:54 +02:00
semantic-release-bot
78fe9ff404
chore(release): 4.0.0 [skip ci] 2023-08-08 12:24:43 +00:00
e5190818c4
perf: mutate destination string for string_concatenate
BREAKING CHANGE: Function signature changed
2023-08-07 00:42:11 +02:00
b922fd9cd3
fix: handle EXIT_FAILURE by printing error message with perror 2023-08-07 00:11:07 +02:00
72645da4b2
perf: mutate strings instead of copy when possible
BREAKING CHANGE: Most of string functions mutates the string instead of copying now.
This allows better performance when copy is not needed.
It also allows more granual control.
If copy is wanted, simply use `string_copy` before calling the function.

Impacted functions are:
`string_to_uppercase`, `string_to_lowercase`, `string_replace`,
`string_trim_start`, `string_trim_end`, `string_trim`,
`string_capitalize`, `string_reverse`
2023-08-06 23:17:07 +02:00
58 changed files with 2209 additions and 473 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,40 +1,40 @@
name: 'CI' name: "CI"
on: on:
push: push:
branches: [develop] branches: [develop]
pull_request: pull_request:
branches: [master, develop] branches: [main, develop]
jobs: jobs:
ci: ci:
runs-on: 'ubuntu-latest' runs-on: "ubuntu-latest"
steps: steps:
- uses: 'actions/checkout@v3.5.3' - uses: "actions/checkout@v4.1.7"
- run: 'sudo apt update' - run: "sudo apt update"
- name: 'Install Build Tools' - name: "Install Build Tools"
run: 'sudo apt-get install --yes build-essential gcc make clang-format' run: "sudo apt install --yes build-essential gcc make clang-format"
- name: 'Install Documentation Tools' - name: "Install Documentation Tools"
run: 'sudo apt-get install --yes doxygen doxygen-gui doxygen-doc graphviz' run: "sudo apt install --yes doxygen doxygen-gui doxygen-doc graphviz"
- run: 'gcc --version' - run: "gcc --version"
- run: 'make' - run: "make"
- run: 'make run' - run: "make run"
- run: 'make test' - run: "make test"
- run: 'make lint' - run: "make lint"
- run: 'make documentation' - run: "make documentation"
- run: 'make set_version' - run: "make set_version"
- run: 'make clean' - run: "make clean"
lint-commit: lint-commit:
runs-on: 'ubuntu-latest' runs-on: "ubuntu-latest"
steps: steps:
- uses: 'actions/checkout@v3.5.3' - uses: "actions/checkout@v4.1.7"
with: with:
fetch-depth: 0 fetch-depth: 0
- uses: 'wagoid/commitlint-github-action@v5.4.1' - uses: "wagoid/commitlint-github-action@v6.1.2"

View File

@ -1,57 +1,57 @@
name: 'Release' name: "Release"
on: on:
push: push:
branches: [master] branches: [main]
jobs: jobs:
release: release:
runs-on: 'ubuntu-latest' runs-on: "ubuntu-latest"
steps: steps:
- uses: 'actions/checkout@v3.5.3' - uses: "actions/checkout@v4.1.7"
with: with:
fetch-depth: 0 fetch-depth: 0
persist-credentials: false persist-credentials: false
submodules: recursive submodules: "recursive"
- name: 'Import GPG key' - name: "Import GPG key"
uses: 'crazy-max/ghaction-import-gpg@v5.3.0' uses: "crazy-max/ghaction-import-gpg@v6.1.0"
with: with:
gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }} gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }}
git_user_signingkey: true git_user_signingkey: true
git_commit_gpgsign: true git_commit_gpgsign: true
- run: 'sudo apt update' - run: "sudo apt update"
- name: 'Install Build Tools' - name: "Install Build Tools"
run: 'sudo apt-get install --yes build-essential gcc make clang-format' run: "sudo apt install --yes build-essential gcc make clang-format"
- name: 'Install Documentation Tools' - name: "Install Documentation Tools"
run: 'sudo apt-get install --yes doxygen doxygen-gui doxygen-doc graphviz' run: "sudo apt install --yes doxygen doxygen-gui doxygen-doc graphviz"
- run: 'make set_version' - run: "make set_version"
- name: 'Use Node.js' - name: "Use Node.js"
uses: 'actions/setup-node@v3.7.0' uses: "actions/setup-node@v4.0.3"
with: with:
node-version: '18.17.0' node-version: "20.17.0"
- name: 'Install Release Tools' - name: "Install Release Tools"
run: 'npm install --save-dev semantic-release@21.0.7 @commitlint/cli@17.6.7 @commitlint/config-conventional@17.6.7 @semantic-release/git@10.0.1 @semantic-release/exec@6.0.3 @saithodev/semantic-release-backmerge@3.2.0 vercel@31.2.2' run: "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: '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: "Generate Documentation"
run: 'make documentation' run: "make documentation"
- name: 'Deploy to Vercel' - 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 }}

View File

@ -1,5 +1,5 @@
{ {
"branches": ["master"], "branches": ["main"],
"plugins": [ "plugins": [
[ [
"@semantic-release/commit-analyzer", "@semantic-release/commit-analyzer",
@ -30,7 +30,7 @@
[ [
"@saithodev/semantic-release-backmerge", "@saithodev/semantic-release-backmerge",
{ {
"branches": [{ "from": "master", "to": "develop" }], "branches": [{ "from": "main", "to": "develop" }],
"backmergeStrategy": "merge" "backmergeStrategy": "merge"
} }
] ]

View File

@ -30,3 +30,18 @@ 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 adheres to [Conventional Commits](https://www.conventionalcommits.org/) and [Semantic Versioning](https://semver.org/) for releases.
## Git Submodules
To get the submodule:
```sh
git submodule update --init --recursive
```
To update the version:
```sh
cd doxygen-awesome-css
git checkout v2.3.3
```

View File

@ -12,7 +12,7 @@ FILE_PATTERNS = *.h \
CODE_OF_CONDUCT.md \ CODE_OF_CONDUCT.md \
CONTRIBUTING.md \ CONTRIBUTING.md \
LICENSE 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 node_modules

View File

@ -1,6 +1,6 @@
MIT License # MIT License
Copyright (c) Théo LUDWIG Copyright (c) Théo LUDWIG <contact@theoludwig.fr>
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

@ -32,13 +32,13 @@ build/test/%.o: test/%.c ${HEADER_FILES} | build/test
.PHONY: run .PHONY: run
run: ${LIB} ./main.c run: ${LIB} ./main.c
mkdir --parents ./bin mkdir --parents ./bin
${CC} ${CC_FLAGS} -o ${MAIN_EXECUTABLE} ./main.c ${LIB_CC_FLAGS} ${CC} ${CC_FLAGS} ${CC_SANITIZER_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} -o ${SET_VERSION_EXECUTABLE} ./set_version.c ${LIB_CC_FLAGS} ${CC} ${CC_FLAGS} ${CC_SANITIZER_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})

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" /></a> <a href="./CONTRIBUTING.md"><img src="https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat" alt="Contributing" /></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" /></a> <a href="https://github.com/theoludwig/libcproject/actions/workflows/ci.yml"><img src="https://github.com/theoludwig/libcproject/actions/workflows/ci.yml/badge.svg?branch=develop" alt="CI" /></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>
@ -37,10 +37,10 @@ For example on GNU/Linux Ubuntu:
```sh ```sh
# Install Build Tools # Install Build Tools
sudo apt-get install build-essential gcc make clang-format sudo apt install build-essential gcc make clang-format
# Install Documentation Tools # Install Documentation Tools
sudo apt-get install doxygen doxygen-gui doxygen-doc graphviz sudo apt install doxygen doxygen-gui doxygen-doc graphviz
``` ```
## Usage ## Usage
@ -92,9 +92,9 @@ touch main.c
#include "libcproject/libcproject.h" #include "libcproject/libcproject.h"
int main() { int main() {
string_t string_value = "Hello, world!"; // `string_t` is a typedef from `libcproject` string_t string = "Hello, world!"; // `string_t` is a typedef from `libcproject`
printf("%s\n", string_value); printf("%s\n", string);
printf("string_length = %ld\n", string_get_length(string_value)); // `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;
} }
``` ```

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

View File

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

View File

@ -1,7 +1,9 @@
#ifndef __LIBCPROJECT_ARRAY_LIST__ #ifndef __LIBCPROJECT_ARRAY_LIST__
#define __LIBCPROJECT_ARRAY_LIST__ #define __LIBCPROJECT_ARRAY_LIST__
#include <errno.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include "types.h" #include "types.h"
@ -16,6 +18,7 @@ struct array_list {
void** data; void** data;
size_t size; size_t size;
size_t capacity; size_t capacity;
size_t capacity_step;
}; };
/** /**
@ -24,26 +27,44 @@ struct array_list {
*/ */
struct array_list* array_list_initialization(); 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. * @brief Adds an element to the end of the array list.
*
* @param list
* @param element
* @since v1.2.0 * @since v1.2.0
*/ */
void array_list_add(struct array_list* list, void* element); void array_list_add(struct array_list* list, void* element);
/** /**
* @brief Removes an element from the array list. * @brief Removes an element from the array list.
*
* @param list
* @param index
* @since v1.2.0 * @since v1.2.0
*/ */
void array_list_remove(struct array_list* list, size_t index); void array_list_remove(struct array_list* list, size_t index);
/** /**
* @brief Gets an element from the array list. * @brief Gets an element from the array list.
*
* @param list
* @param index
* @return void*
* @since v1.2.0 * @since v1.2.0
*/ */
void* array_list_get(struct array_list* list, size_t index); void* array_list_get(struct array_list* list, size_t index);
/** /**
* @brief Frees the array list. * @brief Frees the array list.
*
* @param list
* @since v3.0.0 * @since v3.0.0
*/ */
void array_list_free(struct array_list* list); void array_list_free(struct array_list* list);

View File

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

30
lib/assert.h Normal file
View File

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

View File

@ -1,6 +1,7 @@
#ifndef __LIBCPROJECT_CHARACTER__ #ifndef __LIBCPROJECT_CHARACTER__
#define __LIBCPROJECT_CHARACTER__ #define __LIBCPROJECT_CHARACTER__
#include <errno.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdlib.h> #include <stdlib.h>
@ -11,21 +12,21 @@
* @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_value * @param string
* @param character * @param character
* @since v1.0.0 * @since v1.0.0
*/ */
void character_append(string_t string_value, char character); void character_append(string_t 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.
* *
* @param string_value * @param string
* @param character * @param character
* @param index * @param index
* @since v1.0.0 * @since v1.0.0
*/ */
void character_append_at(string_t string_value, const char character, const size_t index); void character_append_at(string_t string, const char character, const size_t index);
/** /**
* @brief Converts the character to uppercase. * @brief Converts the character to uppercase.
@ -46,7 +47,8 @@ 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').
* *
* @return true if the character is a digit, false otherwise * @param character
* @return bool
* @since v1.0.0 * @since v1.0.0
*/ */
bool character_get_is_digit(const char character); bool character_get_is_digit(const char character);
@ -56,8 +58,9 @@ 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
* @since v1.0.0 * @since v1.0.0
*/ */
unsigned char character_get_alphabet_position(const char character); uint8_t character_get_alphabet_position(const char character);
#endif #endif

View File

@ -3,6 +3,7 @@
string_t convert_character_to_string(const char character) { string_t convert_character_to_string(const char character) {
string_t string = malloc(sizeof(char) * 2); string_t 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; string[0] = character;
@ -18,23 +19,23 @@ char convert_digit_to_character(const char digit) {
return digit + '0'; return digit + '0';
} }
long long convert_string_to_number(const string_t string_value) { int64_t convert_string_to_number(const string_t string) {
bool is_negative = string_value[0] == '-'; bool is_negative = string[0] == '-';
long long integer = 0; int64_t integer = 0;
size_t length = string_get_length(string_value); 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_value[index]); integer = integer * 10 + convert_character_to_digit(string[index]);
} }
return is_negative ? integer * -1 : integer; return is_negative ? integer * -1 : integer;
} }
string_t convert_number_to_string(const long long integer) { string_t convert_number_to_string(const int64_t 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;
long long current = mathematics_absolute_value(integer); int64_t current = mathematics_absolute_value(integer);
while (current != 0) { while (current != 0) {
current = current / 10; current = current / 10;
length++; length++;
@ -42,40 +43,40 @@ string_t convert_number_to_string(const long long integer) {
if (is_negative) { if (is_negative) {
length++; length++;
} }
string_t string_value = malloc(sizeof(char) * length); string_t string = malloc(sizeof(char) * length);
if (string_value == NULL) { if (string == NULL) {
perror("Error (convert_number_to_string)");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
current = mathematics_absolute_value(integer); current = mathematics_absolute_value(integer);
size_t index = 0; size_t index = 0;
while (current != 0) { while (current != 0) {
string_value[index++] = convert_digit_to_character(current % 10); string[index++] = convert_digit_to_character(current % 10);
current = current / 10; current = current / 10;
} }
if (is_negative) { if (is_negative) {
string_value[index++] = '-'; string[index++] = '-';
} }
string_value[index] = '\0'; string[index] = '\0';
char* result = string_reverse(string_value); string_reverse(string);
free(string_value); return string;
return result;
} }
string_t convert_number_from_base_10_to_base(unsigned long long number, unsigned int base) { string_t convert_number_from_base_10_to_base(uint64_t number, uint64_t base) {
if (number == 0) { if (number == 0) {
return "0"; return "0";
} }
int remainders[64]; int64_t remainders[64];
int index = 0; int64_t 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)); string_t result = malloc(sizeof(char) * (index + 1));
int index_result = 0; int64_t index_result = 0;
for (int iteration = index - 1; iteration >= 0; iteration--) { for (int64_t iteration = index - 1; iteration >= 0; iteration--) {
int remainder = remainders[iteration]; int64_t 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 {
@ -87,17 +88,17 @@ string_t convert_number_from_base_10_to_base(unsigned long long number, unsigned
return result; return result;
} }
int convert_number_from_base_to_base_10(string_t number, unsigned int base) { uint64_t convert_number_from_base_to_base_10(string_t number, uint64_t base) {
int length = string_get_length(number); size_t length = string_get_length(number);
int exponent = length - 1; int64_t exponent = length - 1;
int result = 0; uint64_t result = 0;
int index = 0; int64_t index = 0;
while (exponent >= 0) { while (exponent >= 0) {
int current_number = (int)(number[index] - '0'); int64_t current_number = (int64_t)(number[index] - '0');
if (current_number >= 10) { if (current_number >= 10) {
current_number = (int)(number[index] - 'A') + 10; current_number = (int64_t)(number[index] - 'A') + 10;
} else { } else {
current_number = (int)(number[index] - '0'); current_number = (int64_t)(number[index] - '0');
} }
result = result + current_number * mathematics_pow(base, exponent); result = result + current_number * mathematics_pow(base, exponent);
exponent--; exponent--;
@ -106,6 +107,6 @@ int convert_number_from_base_to_base_10(string_t number, unsigned int base) {
return result; return result;
} }
string_t convert_number_from_base_to_another(string_t number, int base_from, int base_target) { string_t convert_number_from_base_to_another(string_t number, uint64_t base_from, uint64_t 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,6 +1,7 @@
#ifndef __LIBCPROJECT_CONVERT__ #ifndef __LIBCPROJECT_CONVERT__
#define __LIBCPROJECT_CONVERT__ #define __LIBCPROJECT_CONVERT__
#include <errno.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -14,6 +15,7 @@
* @brief Convert a character to a string. * @brief Convert a character to a string.
* *
* @param character * @param character
* @return string_t
* @since v1.0.0 * @since v1.0.0
*/ */
string_t convert_character_to_string(const char character); string_t convert_character_to_string(const char character);
@ -22,6 +24,7 @@ string_t convert_character_to_string(const char character);
* @brief Convert a character to a digit. * @brief Convert a character to a digit.
* *
* @param character * @param character
* @return char
* @since v1.0.0 * @since v1.0.0
*/ */
char convert_character_to_digit(const char character); char convert_character_to_digit(const char character);
@ -30,6 +33,7 @@ char convert_character_to_digit(const char character);
* @brief Convert a digit to a character. * @brief Convert a digit to a character.
* *
* @param digit * @param digit
* @return char
* @since v1.0.0 * @since v1.0.0
*/ */
char convert_digit_to_character(const char digit); char convert_digit_to_character(const char digit);
@ -37,36 +41,40 @@ char convert_digit_to_character(const char digit);
/** /**
* @brief Convert a string to a number. * @brief Convert a string to a number.
* *
* @param string_value * @param string
* @return int64_t
* @since v1.0.0 * @since v1.0.0
*/ */
long long convert_string_to_number(const string_t string_value); int64_t convert_string_to_number(const string_t string);
/** /**
* @brief Convert a number to a string. * @brief Convert a number to a string.
* *
* @param integer * @param integer
* @return string_t
* @since v1.0.0 * @since v1.0.0
*/ */
string_t convert_number_to_string(const long long integer); string_t convert_number_to_string(const int64_t integer);
/** /**
* @brief Convert a number (base 10) to a string with a specific base. * @brief Convert a number (base 10) to a string with a specific base.
* *
* @param number * @param number
* @param base * @param base
* @return string_t
* @since v1.0.0 * @since v1.0.0
*/ */
string_t convert_number_from_base_10_to_base(unsigned long long number, unsigned int base); string_t convert_number_from_base_10_to_base(uint64_t number, uint64_t base);
/** /**
* @brief Convert a number with a specific base to a number base 10. * @brief Convert a number with a specific base to a number base 10.
* *
* @param number * @param number
* @param base * @param base
* @return uint64_t
* @since v1.0.0 * @since v1.0.0
*/ */
int convert_number_from_base_to_base_10(string_t number, unsigned int base); uint64_t convert_number_from_base_to_base_10(string_t number, uint64_t base);
/** /**
* @brief Convert a number with a specific base to a number of specific base. * @brief Convert a number with a specific base to a number of specific base.
@ -74,8 +82,9 @@ int convert_number_from_base_to_base_10(string_t number, unsigned int base);
* @param number * @param number
* @param base_from * @param base_from
* @param base_target * @param base_target
* @return string_t
* @since v1.0.0 * @since v1.0.0
*/ */
string_t convert_number_from_base_to_another(string_t number, int base_from, int base_target); string_t convert_number_from_base_to_another(string_t number, uint64_t base_from, uint64_t base_target);
#endif #endif

339
lib/date.c Normal file
View File

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

350
lib/date.h Normal file
View File

@ -0,0 +1,350 @@
#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

View File

@ -1,6 +1,6 @@
#include "filesystem.h" #include "filesystem.h"
int filesystem_read(string_t path, byte_t **file_content, off_t *file_size) { int filesystem_read(string_t path, byte_t **file_content, size_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;
@ -15,7 +15,7 @@ int filesystem_read(string_t path, byte_t **file_content, off_t *file_size) {
return 0; return 0;
} }
int filesystem_write(string_t path, byte_t *file_content, off_t file_size) { int filesystem_write(string_t path, byte_t *file_content, size_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;

View File

@ -18,12 +18,13 @@
* *
* @param path * @param path
* @param file_content * @param file_content
* @param file_size * @param file_size The size of the file that was read (mutated by the function).
* @retval -1 if the file does not exist or if there is an error. * @retval -1 if the file does not exist or if there is an error.
* @retval 0 for success. * @retval 0 for success.
* @return int
* @since v1.0.0 * @since v1.0.0
*/ */
int filesystem_read(string_t path, byte_t **file_content, off_t *file_size); int filesystem_read(string_t path, byte_t **file_content, size_t *file_size);
/** /**
* @brief Write the content to a file. * @brief Write the content to a file.
@ -33,16 +34,16 @@ int filesystem_read(string_t path, byte_t **file_content, off_t *file_size);
* @param file_size * @param file_size
* @retval -1 if there is an error. * @retval -1 if there is an error.
* @retval 0 for success. * @retval 0 for success.
* @return int
* @since v1.0.0 * @since v1.0.0
*/ */
int filesystem_write(string_t path, byte_t *file_content, off_t file_size); int filesystem_write(string_t path, byte_t *file_content, size_t file_size);
/** /**
* @brief Check if a path exists. * @brief Check if a path exists.
* *
* @param path * @param path
* @retval true if the path exists. * @return bool
* @retval false if the path does not exist.
* @since v3.1.0 * @since v3.1.0
*/ */
bool filesystem_exists(string_t path); bool filesystem_exists(string_t path);
@ -54,6 +55,7 @@ bool filesystem_exists(string_t path);
* @return int * @return int
* @retval -1 if there is an error. * @retval -1 if there is an error.
* @retval 0 for success. * @retval 0 for success.
* @return int
* @since v3.1.0 * @since v3.1.0
*/ */
int filesystem_remove(string_t path); int filesystem_remove(string_t path);
@ -64,6 +66,7 @@ int filesystem_remove(string_t path);
* @param path * @param path
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types * @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 * @see https://www.iana.org/assignments/media-types/media-types.xhtml
* @return string_t
* @since v1.0.0 * @since v1.0.0
*/ */
string_t filesystem_get_mimetype(string_t path); string_t filesystem_get_mimetype(string_t path);

View File

@ -40,7 +40,7 @@ uint64_t hash(string_t key, size_t capacity) {
memcpy(&m, message + offset, sizeof(uint64_t)); memcpy(&m, message + offset, sizeof(uint64_t));
v3 ^= m; v3 ^= m;
for (int i = 0; i < 2; i++) { for (uint8_t i = 0; i < 2; i++) {
v0 = sip_round(v0, v1, v2, v3); v0 = sip_round(v0, v1, v2, v3);
v1 = ROTATE_LEFT(v1, 13); v1 = ROTATE_LEFT(v1, 13);
v2 = ROTATE_LEFT(v2, 16); v2 = ROTATE_LEFT(v2, 16);
@ -49,7 +49,7 @@ uint64_t hash(string_t key, size_t capacity) {
} }
v2 ^= 0xff; v2 ^= 0xff;
for (int i = 0; i < 4; i++) { for (uint8_t i = 0; i < 4; i++) {
v0 = sip_round(v0, v1, v2, v3); v0 = sip_round(v0, v1, v2, v3);
v1 = ROTATE_LEFT(v1, 13); v1 = ROTATE_LEFT(v1, 13);
v2 = ROTATE_LEFT(v2, 16); v2 = ROTATE_LEFT(v2, 16);
@ -90,7 +90,7 @@ uint64_t hash(string_t key, size_t capacity) {
v3 ^= m; v3 ^= m;
for (int i = 0; i < 2; i++) { for (uint8_t i = 0; i < 2; i++) {
v0 = sip_round(v0, v1, v2, v3); v0 = sip_round(v0, v1, v2, v3);
v1 = ROTATE_LEFT(v1, 13); v1 = ROTATE_LEFT(v1, 13);
v2 = ROTATE_LEFT(v2, 16); v2 = ROTATE_LEFT(v2, 16);
@ -100,7 +100,7 @@ uint64_t hash(string_t key, size_t capacity) {
v0 ^= m; v0 ^= m;
v2 ^= 0xff; v2 ^= 0xff;
for (int i = 0; i < 4; i++) { for (uint8_t i = 0; i < 4; i++) {
v0 = sip_round(v0, v1, v2, v3); v0 = sip_round(v0, v1, v2, v3);
v1 = ROTATE_LEFT(v1, 13); v1 = ROTATE_LEFT(v1, 13);
v2 = ROTATE_LEFT(v2, 16); v2 = ROTATE_LEFT(v2, 16);

View File

@ -1,6 +1,7 @@
#ifndef __LIBCPROJECT_HASH_MAP__ #ifndef __LIBCPROJECT_HASH_MAP__
#define __LIBCPROJECT_HASH_MAP__ #define __LIBCPROJECT_HASH_MAP__
#include <errno.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
@ -34,22 +35,27 @@ struct hash_map_item {
/** /**
* @brief Hash function (using SipHash 1-3 algorithm). * @brief Hash function (using SipHash 1-3 algorithm).
* @param key
* @param capacity
* @see https://en.wikipedia.org/wiki/SipHash * @see https://en.wikipedia.org/wiki/SipHash
* @see https://github.com/veorq/SipHash * @see https://github.com/veorq/SipHash
*
* @param key
* @param capacity
* @return uint64_t
* @since v2.0.0 * @since v2.0.0
*/ */
uint64_t hash(string_t key, size_t capacity); uint64_t hash(string_t key, size_t capacity);
/** /**
* @brief Hash map initialization. * @brief Hash map initialization.
*
* @return struct hash_map*
* @since v2.0.0 * @since v2.0.0
*/ */
struct hash_map *hash_map_initialization(); struct hash_map *hash_map_initialization();
/** /**
* @brief Add an item to the hash map. * @brief Add an item to the hash map.
*
* @param hash_map * @param hash_map
* @param key * @param key
* @param data * @param data
@ -69,14 +75,17 @@ void hash_map_remove(struct hash_map *hash_map, string_t key);
* @brief Get an item from the hash map. * @brief Get an item from the hash map.
* @param hash_map * @param hash_map
* @param key * @param key
* @return void*
* @since v2.0.0 * @since v2.0.0
*/ */
void *hash_map_get(struct hash_map *hash_map, string_t key); void *hash_map_get(struct hash_map *hash_map, string_t key);
/** /**
* @brief Check if the hash map contains a key. * @brief Check if the hash map contains a key.
*
* @param hash_map * @param hash_map
* @param key * @param key
* @return bool
* @since v2.0.0 * @since v2.0.0
*/ */
bool hash_map_contains_key(struct hash_map *hash_map, string_t key); bool hash_map_contains_key(struct hash_map *hash_map, string_t key);
@ -85,12 +94,15 @@ bool hash_map_contains_key(struct hash_map *hash_map, string_t key);
* @brief Get the hash map keys. * @brief Get the hash map keys.
* *
* @param hash_map * @param hash_map
* @return string_t*
* @since v2.0.0 * @since v2.0.0
*/ */
string_t *hash_map_get_keys(struct hash_map *hash_map); string_t *hash_map_get_keys(struct hash_map *hash_map);
/** /**
* @brief Frees the hash map. * @brief Frees the hash map.
*
* @param hash_map
* @since v3.0.0 * @since v3.0.0
*/ */
void hash_map_free(struct hash_map *hash_map); void hash_map_free(struct hash_map *hash_map);

View File

@ -1,8 +1,9 @@
#include "linked_list.h" #include "linked_list.h"
struct linked_list *linked_list_initialization() { struct linked_list *linked_list_initialization() {
struct linked_list *list = malloc(sizeof(*list)); struct linked_list *list = malloc(sizeof(struct linked_list));
if (list == NULL) { if (list == NULL) {
perror("Error (linked_list_initialization)");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
list->head = NULL; list->head = NULL;
@ -11,8 +12,14 @@ 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) {
struct linked_list_node *node_new = malloc(sizeof(*node_new)); if (list == NULL) {
if (list == NULL || node_new == NULL) { errno = EINVAL;
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;
@ -24,6 +31,8 @@ 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) {
@ -35,11 +44,17 @@ 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(*node_new)); struct linked_list_node *node_new = malloc(sizeof(struct linked_list_node));
if (list == NULL || node_new == NULL) { if (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;

View File

@ -1,6 +1,7 @@
#ifndef __LIBCPROJECT_LINKED_LIST__ #ifndef __LIBCPROJECT_LINKED_LIST__
#define __LIBCPROJECT_LINKED_LIST__ #define __LIBCPROJECT_LINKED_LIST__
#include <errno.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdlib.h> #include <stdlib.h>
@ -13,7 +14,6 @@
*/ */
struct linked_list { struct linked_list {
struct linked_list_node *head; struct linked_list_node *head;
size_t length; size_t length;
}; };
@ -28,42 +28,61 @@ struct linked_list_node {
/** /**
* @brief Linked list initialization. * @brief Linked list initialization.
*
* @return struct linked_list*
* @since v1.0.0 * @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. * @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 * @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. * @brief Delete node in the head of the linked list.
*
* @param list
* @since v1.0.0 * @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. * @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 * @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. * @brief Reverse the linked list by creating a new one.
*
* @param list
* @return struct linked_list*
* @since v1.0.0 * @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. * @brief Reverse the linked list by mutating it.
*
* @param list
* @since v1.0.0 * @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. * @brief Frees the linked list.
*
* @param list
* @since v3.0.0 * @since v3.0.0
*/ */
void linked_list_free(struct linked_list *list); void linked_list_free(struct linked_list *list);

View File

@ -1,23 +1,23 @@
#include "mathematics.h" #include "mathematics.h"
bool mathematics_equals(const float number1, const float number2) { bool mathematics_equals(const float64_t number1, const float64_t number2) {
return (number1 - number2) < MATHEMATICS_FLOAT_PRECISION; return (number1 - number2) < MATHEMATICS_DOUBLE_PRECISION;
} }
unsigned long long mathematics_absolute_value(const long long number) { uint64_t mathematics_absolute_value(const int64_t number) {
if (number >= 0) { if (number >= 0) {
return number; return number;
} }
return -number; return -number;
} }
unsigned long long mathematics_pow(unsigned long long base, unsigned long long exponent) { uint64_t mathematics_pow(uint64_t base, uint64_t exponent) {
return exponent == 0 ? 1 : base * mathematics_pow(base, exponent - 1); return exponent == 0 ? 1 : base * mathematics_pow(base, exponent - 1);
} }
float mathematics_root(float number, unsigned int nth_root) { float64_t mathematics_root(float64_t number, uint64_t nth_root) {
float result = number; float64_t result = number;
float previous_result = 0; float64_t 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,10 +25,46 @@ float mathematics_root(float number, unsigned int nth_root) {
return result; return result;
} }
float mathematics_square_root(float number) { float64_t mathematics_square_root(float64_t number) {
return mathematics_root(number, 2); return mathematics_root(number, 2);
} }
unsigned long long mathematics_factorial(unsigned long long number) { uint64_t mathematics_factorial(uint64_t 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,9 +1,11 @@
#ifndef __LIBCPROJECT_MATHEMATICS__ #ifndef __LIBCPROJECT_MATHEMATICS__
#define __LIBCPROJECT_MATHEMATICS__ #define __LIBCPROJECT_MATHEMATICS__
#define MATHEMATICS_FLOAT_PRECISION 0.00000001 #define MATHEMATICS_DOUBLE_PRECISION 0.0000000001
#include <errno.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdlib.h>
#include "types.h" #include "types.h"
@ -12,50 +14,111 @@
* *
* @param number1 * @param number1
* @param number2 * @param number2
* @return bool
* @since v1.0.0 * @since v1.0.0
*/ */
bool mathematics_equals(const float number1, const float number2); bool mathematics_equals(const float64_t number1, const float64_t number2);
/** /**
* @brief Get the absolute value of a number. * @brief Get the absolute value of a number.
* *
* @param number * @param number
* @return uint64_t
* @since v1.0.0 * @since v1.0.0
*/ */
unsigned long long mathematics_absolute_value(const long long number); uint64_t mathematics_absolute_value(const int64_t number);
/** /**
* @brief Calculates the power of a number. * @brief Calculates the power of a number.
* *
* @param base * @param base
* @param exponent * @param exponent
* @return uint64_t
* @since v1.0.0 * @since v1.0.0
*/ */
unsigned long long mathematics_pow(unsigned long long base, unsigned long long exponent); uint64_t mathematics_pow(uint64_t base, uint64_t exponent);
/** /**
* @brief Calculates the nth root of a number using Heron's method. * @brief Calculates the nth root of a number.
* *
* @param number * @param number
* @param nth_root * @param nth_root
* @return float64_t
* @since v1.0.0 * @since v1.0.0
*/ */
float mathematics_root(float number, unsigned int nth_root); float64_t mathematics_root(float64_t number, uint64_t nth_root);
/** /**
* @brief Calculates the square root of a number using Heron's method. * @brief Calculates the square root of a number using Heron's method.
* *
* @param number * @param number
* @return float64_t
* @since v1.0.0 * @since v1.0.0
*/ */
float mathematics_square_root(float number); float64_t mathematics_square_root(float64_t number);
/** /**
* @brief Calculates the factorial of a number. * @brief Calculates the factorial of a number.
* *
* @param number * @param number
* @return uint64_t
* @since v1.0.0 * @since v1.0.0
*/ */
unsigned long long mathematics_factorial(unsigned long long number); 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,8 +1,9 @@
#include "queue.h" #include "queue.h"
struct queue *queue_initialization() { struct queue *queue_initialization() {
struct queue *queue = malloc(sizeof(*queue)); struct queue *queue = malloc(sizeof(struct queue));
if (queue == NULL) { if (queue == NULL) {
perror("Error (queue_initialization)");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
queue->first = NULL; queue->first = NULL;
@ -11,8 +12,14 @@ struct queue *queue_initialization() {
} }
void queue_push(struct queue *queue, void *data) { void queue_push(struct queue *queue, void *data) {
struct queue_node *node_new = malloc(sizeof(*node_new)); if (queue == NULL) {
if (queue == NULL || node_new == NULL) { errno = EINVAL;
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;
@ -31,6 +38,8 @@ 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;
@ -46,6 +55,8 @@ void *queue_pop(struct queue *queue) {
void queue_free(struct queue *queue) { void queue_free(struct queue *queue) {
if (queue == NULL) { if (queue == NULL) {
errno = EINVAL;
perror("Error (queue_free)");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
struct queue_node *node = queue->first; struct queue_node *node = queue->first;

View File

@ -1,6 +1,7 @@
#ifndef __LIBCPROJECT_QUEUE__ #ifndef __LIBCPROJECT_QUEUE__
#define __LIBCPROJECT_QUEUE__ #define __LIBCPROJECT_QUEUE__
#include <errno.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -26,24 +27,34 @@ struct queue_node {
/** /**
* @brief Queue initialization. * @brief Queue initialization.
*
* @return struct queue*
* @since v1.0.0 * @since v1.0.0
*/ */
struct queue *queue_initialization(); struct queue *queue_initialization();
/** /**
* @brief Push data to queue. * @brief Push data to queue.
*
* @param queue
* @param data
* @since v1.0.0 * @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. * @brief Pop data from queue.
*
* @param queue
* @return void*
* @since v1.0.0 * @since v1.0.0
*/ */
void *queue_pop(struct queue *queue); void *queue_pop(struct queue *queue);
/** /**
* @brief Frees the queue. * @brief Frees the queue.
*
* @param queue
* @since v3.0.0 * @since v3.0.0
*/ */
void queue_free(struct queue *queue); void queue_free(struct queue *queue);

View File

@ -1,8 +1,9 @@
#include "stack.h" #include "stack.h"
struct stack *stack_initialization() { struct stack *stack_initialization() {
struct stack *stack = malloc(sizeof(*stack)); struct stack *stack = malloc(sizeof(struct stack));
if (stack == NULL) { if (stack == NULL) {
perror("Error (stack_initialization)");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
stack->first = NULL; stack->first = NULL;
@ -11,8 +12,14 @@ struct stack *stack_initialization() {
} }
void stack_push(struct stack *stack, void *data) { void stack_push(struct stack *stack, void *data) {
struct stack_node *node_new = malloc(sizeof(*node_new)); if (stack == NULL) {
if (stack == NULL || data == NULL) { errno = EINVAL;
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;
@ -23,6 +30,8 @@ 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;
@ -38,6 +47,8 @@ void *stack_pop(struct stack *stack) {
void stack_free(struct stack *stack) { void stack_free(struct stack *stack) {
if (stack == NULL) { if (stack == NULL) {
errno = EINVAL;
perror("Error (stack_free)");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
struct stack_node *node = stack->first; struct stack_node *node = stack->first;

View File

@ -1,6 +1,7 @@
#ifndef __LIBCPROJECT_STACK__ #ifndef __LIBCPROJECT_STACK__
#define __LIBCPROJECT_STACK__ #define __LIBCPROJECT_STACK__
#include <errno.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -26,24 +27,34 @@ struct stack_node {
/** /**
* @brief Stack initialization. * @brief Stack initialization.
*
* @return struct stack*
* @since v1.0.0 * @since v1.0.0
*/ */
struct stack *stack_initialization(); struct stack *stack_initialization();
/** /**
* @brief Push data to stack. * @brief Push data to stack.
*
* @param stack
* @param data
* @since v1.0.0 * @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. * @brief Pop data from stack.
*
* @param stack
* @return void*
* @since v1.0.0 * @since v1.0.0
*/ */
void *stack_pop(struct stack *stack); void *stack_pop(struct stack *stack);
/** /**
* @brief Frees the stack. * @brief Frees the stack.
*
* @param stack
* @since v3.0.0 * @since v3.0.0
*/ */
void stack_free(struct stack *stack); void stack_free(struct stack *stack);

View File

@ -1,135 +1,110 @@
#include "string.h" #include "string.h"
size_t string_get_length(const string_t string_value) { size_t string_get_length(const string_t string) {
size_t length = 0; size_t length = 0;
while (string_value[length] != '\0') { while (string[length] != '\0') {
length++; length++;
} }
return length; return length;
} }
string_t string_to_uppercase(string_t string_value) { void string_to_uppercase(string_t string) {
size_t string_length = string_get_length(string_value); size_t string_length = string_get_length(string);
string_t result = malloc(sizeof(char) * (string_length + 1));
if (result == NULL) {
exit(EXIT_FAILURE);
}
for (size_t index = 0; index < string_length; index++) { for (size_t index = 0; index < string_length; index++) {
result[index] = character_to_upper(string_value[index]); string[index] = character_to_upper(string[index]);
} }
result[string_length] = '\0'; string[string_length] = '\0';
return result;
} }
string_t string_to_lowercase(string_t string_value) { void string_to_lowercase(string_t string) {
size_t string_length = string_get_length(string_value); size_t string_length = string_get_length(string);
string_t result = malloc(sizeof(char) * (string_length + 1));
if (result == NULL) {
exit(EXIT_FAILURE);
}
for (size_t index = 0; index < string_length; index++) { for (size_t index = 0; index < string_length; index++) {
result[index] = character_to_lower(string_value[index]); string[index] = character_to_lower(string[index]);
} }
result[string_length] = '\0'; string[string_length] = '\0';
return result;
} }
string_t string_replace(string_t string_value, char search, char replace) { void string_replace(string_t string, char search, char replace) {
size_t string_length = string_get_length(string_value); size_t string_length = string_get_length(string);
string_t result = malloc(sizeof(char) * (string_length + 1));
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_value[index]; bool is_search_value = search == string[index];
if (is_search_value) { if (is_search_value) {
result[index] = replace; string[index] = replace;
} else { } else {
result[index] = string_value[index]; string[index] = string[index];
} }
} }
result[string_length] = '\0'; string[string_length] = '\0';
return result;
} }
string_t string_trim_start(string_t string_value, char character) { void string_remove_character(string_t string, char search) {
size_t string_length = string_get_length(string_value); size_t string_length = string_get_length(string);
string_t result = malloc(sizeof(char) * (string_length + 1)); for (size_t index = 0; index < string_length; index++) {
if (result == NULL) { if (string[index] == search) {
exit(EXIT_FAILURE); 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; size_t index_space = 0;
while (string_value[index_space] == character) { while (string[index_space] == character) {
index_space++; index_space++;
} }
for (size_t index = index_space; index < string_length; index++) { for (size_t index = 0; index < string_length - index_space; index++) {
result[index - index_space] = string_value[index]; string[index] = string[index + index_space];
} }
result[string_length - index_space] = '\0'; string[string_length - index_space] = '\0';
return result;
} }
string_t string_trim_end(string_t string_value, char character) { void string_trim_end(string_t string, char character) {
size_t string_length = string_get_length(string_value); size_t string_length = string_get_length(string);
string_t result = malloc(sizeof(char) * (string_length + 1));
if (result == NULL) {
exit(EXIT_FAILURE);
}
size_t index_space = string_length - 1; size_t index_space = string_length - 1;
while (string_value[index_space] == character) { while (string[index_space] == character) {
index_space--; index_space--;
} }
for (size_t index = 0; index < index_space + 1; index++) { string[index_space + 1] = '\0';
result[index] = string_value[index];
}
result[index_space + 1] = '\0';
return result;
} }
string_t string_trim(string_t string_value, char character) { void string_trim(string_t string, char character) {
string_t result_start = string_trim_start(string_value, character); string_trim_start(string, character);
string_t result = string_trim_end(result_start, character); string_trim_end(string, character);
free(result_start);
return result;
} }
string_t string_copy(const string_t source) { string_t string_copy(const string_t string) {
size_t source_length = string_get_length(source); size_t source_length = string_get_length(string);
string_t copy = malloc(sizeof(char) * (source_length + 1)); string_t copy = malloc(sizeof(char) * (source_length + 1));
if (copy == NULL) { if (copy == NULL) {
perror("Error (string_copy)");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
size_t index; size_t index;
for (index = 0; index < source_length; index++) { for (index = 0; index < source_length; index++) {
copy[index] = source[index]; copy[index] = string[index];
} }
copy[index] = '\0'; copy[index] = '\0';
return copy; return copy;
} }
string_t string_capitalize(string_t string_value) { void string_capitalize(string_t string) {
size_t string_length = string_get_length(string_value); size_t string_length = string_get_length(string);
string_t result = malloc(sizeof(char) * (string_length + 1)); if (string_length == 0) {
if (result == NULL) { return;
exit(EXIT_FAILURE);
} }
for (size_t index = 0; index < string_length; index++) { string[0] = character_to_upper(string[0]);
bool is_first_character = index == 0;
if (is_first_character) {
result[index] = character_to_upper(string_value[index]);
} else {
result[index] = string_value[index];
}
}
result[string_length] = '\0';
return result;
} }
size_t string_total_occurrences_of_character(string_t string_value, char character) { size_t string_total_occurrences_of_character(string_t string, char character) {
size_t result = 0; size_t result = 0;
size_t string_length = string_get_length(string_value); 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++) {
char current_character = string_value[index]; char current_character = string[index];
if (current_character == character) { if (current_character == character) {
result += 1; result += 1;
} }
@ -137,21 +112,17 @@ size_t string_total_occurrences_of_character(string_t string_value, char charact
return result; return result;
} }
string_t string_reverse(const string_t string_value) { void string_reverse(const string_t string) {
size_t string_length = string_get_length(string_value); size_t string_length = string_get_length(string);
size_t index = 0; size_t index_start = 0;
string_t result = malloc(sizeof(char) * (string_length + 1)); size_t index_end = string_length - 1;
if (result == NULL) { while (index_start < index_end) {
exit(EXIT_FAILURE); char temporary = string[index_start];
string[index_start] = string[index_end];
string[index_end] = temporary;
index_start++;
index_end--;
} }
size_t result_index = 0;
for (index = string_length - 1; index > 0; index--) {
result[result_index] = string_value[index];
result_index++;
}
result[result_index] = string_value[index];
result[string_length] = '\0';
return result;
} }
bool string_equals(const string_t string1, const string_t string2) { bool string_equals(const string_t string1, const string_t string2) {
@ -166,11 +137,11 @@ 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_value) { bool string_get_is_integer(const string_t string) {
size_t index = 0; size_t index = 0;
size_t string_length = string_get_length(string_value); size_t string_length = string_get_length(string);
bool is_integer = string_length >= 1; bool is_integer = string_length >= 1;
if (is_integer && string_value[0] == '-') { if (is_integer && string[0] == '-') {
if (string_length == 1) { if (string_length == 1) {
is_integer = false; is_integer = false;
} else { } else {
@ -178,7 +149,7 @@ bool string_get_is_integer(const string_t string_value) {
} }
} }
while (index < string_length && is_integer) { while (index < string_length && is_integer) {
if (!character_get_is_digit(string_value[index])) { if (!character_get_is_digit(string[index])) {
is_integer = false; is_integer = false;
} }
index++; index++;
@ -186,36 +157,38 @@ bool string_get_is_integer(const string_t string_value) {
return is_integer; return is_integer;
} }
string_t* string_split(const string_t string_value, char separator, size_t* result_size) { string_t* string_split(const string_t string, char separator, size_t* result_size) {
size_t string_length = string_get_length(string_value); 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)); string_t current = malloc(sizeof(char) * (string_length + 1));
string_t* result = NULL; string_t* result = NULL;
if (current == NULL) { if (current == NULL) {
perror("Error (string_split)");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
while (index_string < string_length) { while (index_string < string_length) {
if (string_value[index_string] == separator) { if (string[index_string] == separator) {
current[index_current] = '\0'; current[index_current] = '\0';
result = realloc(result, sizeof(string_t) * (index_result + 1)); result = realloc(result, sizeof(string_t) * (index_result + 1));
if (result == NULL) { if (result == NULL) {
perror("Error (string_split)");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
result[index_result] = string_copy(current); result[index_result] = string_copy(current);
index_result++; index_result++;
index_current = 0; index_current = 0;
} else { } else {
current[index_current] = string_value[index_string]; current[index_current] = string[index_string];
index_current++; index_current++;
} }
index_string++; index_string++;
} }
current[index_current] = '\0'; current[index_current] = '\0';
result = realloc(result, sizeof(string_t) * (index_result + 1)); result = realloc(result, sizeof(string_t) * (index_result + 1));
if (result == NULL) { if (result == NULL) {
perror("Error (string_split)");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
result[index_result] = string_copy(current); result[index_result] = string_copy(current);
@ -230,8 +203,9 @@ string_t string_join(string_t* array, const char separator, size_t array_length)
total_length += string_get_length(array[index_array]); total_length += string_get_length(array[index_array]);
} }
size_t string_length = total_length + (array_length - 1); size_t string_length = total_length + (array_length - 1);
string_t string_value = malloc(sizeof(char) * (string_length + 1)); string_t string = malloc(sizeof(char) * (string_length + 1));
if (string_value == NULL) { if (string == NULL) {
perror("Error (string_join)");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
size_t current_index = 0; size_t current_index = 0;
@ -239,48 +213,45 @@ string_t string_join(string_t* array, const char separator, size_t array_length)
string_t substring = array[index_array]; string_t substring = array[index_array];
size_t substring_length = string_get_length(substring); size_t substring_length = string_get_length(substring);
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_value[current_index] = substring[index_substring]; string[current_index] = substring[index_substring];
current_index++; 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_value[current_index] = separator; string[current_index] = separator;
current_index++; current_index++;
} }
} }
string_value[string_length] = '\0'; string[string_length] = '\0';
return string_value; return string;
} }
string_t string_concatenate(string_t string1, string_t string2) { void string_concatenate(string_t* destination, string_t source) {
size_t string1_length = string_get_length(string1); size_t destination_length = string_get_length(*destination);
size_t string2_length = string_get_length(string2); size_t source_length = string_get_length(source);
size_t result_length = string1_length + string2_length; size_t new_length = destination_length + source_length;
string_t result = malloc(sizeof(char) * (result_length + 1)); *destination = realloc(*destination, sizeof(char) * (new_length + 1));
if (result == NULL) { if (*destination == NULL) {
perror("Error (string_concatenate)");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
size_t index_string1 = 0; size_t index_destination = destination_length;
for (; index_string1 < string1_length; index_string1++) { for (size_t index_source = 0; index_source < source_length; index_source++) {
result[index_string1] = string1[index_string1]; (*destination)[index_destination++] = source[index_source];
} }
for (size_t index_string2 = 0; index_string2 < string2_length; index_string2++) { (*destination)[index_destination] = '\0';
result[index_string1 + index_string2] = string2[index_string2];
}
result[result_length] = '\0';
return result;
} }
bool string_get_has_unique_characters(const string_t string_value) { bool string_get_has_unique_characters(const string_t string) {
bool has_unique = true; bool has_unique = true;
size_t string_length = string_get_length(string_value); size_t string_length = string_get_length(string);
struct hash_map* characters_already_seen = hash_map_initialization(); struct hash_map* characters_already_seen = hash_map_initialization();
string_t* keys = malloc(sizeof(string_t) * string_length); string_t* keys = malloc(sizeof(string_t) * string_length);
for (size_t index = 0; index < string_length; index++) { for (size_t index = 0; index < string_length; index++) {
keys[index] = NULL; keys[index] = NULL;
} }
for (size_t index = 0; index < string_length && has_unique; index++) { for (size_t index = 0; index < string_length && has_unique; index++) {
char character = string_value[index]; char character = string[index];
keys[index] = convert_character_to_string(character); keys[index] = convert_character_to_string(character);
string_t key = keys[index]; string_t key = keys[index];
if (hash_map_contains_key(characters_already_seen, key)) { if (hash_map_contains_key(characters_already_seen, key)) {
@ -299,24 +270,24 @@ bool string_get_has_unique_characters(const string_t string_value) {
return has_unique; return has_unique;
} }
string_t string_substring(const string_t string_value, size_t index_start, size_t index_end) { 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; size_t substring_length = index_end - index_start + 1;
string_t result = malloc(sizeof(char) * (substring_length + 1)); string_t result = malloc(sizeof(char) * (substring_length + 1));
for (size_t index = 0; index < substring_length; index++) { for (size_t index = 0; index < substring_length; index++) {
result[index] = string_value[index_start + index]; result[index] = string[index_start + index];
} }
result[substring_length] = '\0'; result[substring_length] = '\0';
return result; return result;
} }
bool string_get_is_substring(const string_t string_value, const string_t substring) { bool string_get_is_substring(const string_t string, const string_t substring) {
bool is_substring = false; bool is_substring = false;
size_t string_length = string_get_length(string_value); size_t string_length = string_get_length(string);
size_t substring_length = string_get_length(substring); size_t substring_length = string_get_length(substring);
for (size_t index_string = 0; index_string < string_length && !is_substring; index_string++) { for (size_t index_string = 0; index_string < string_length && !is_substring; index_string++) {
size_t index_substring = 0; size_t index_substring = 0;
size_t index_considered = index_string; size_t index_considered = index_string;
while (index_substring < substring_length && string_value[index_considered] == substring[index_substring]) { while (index_substring < substring_length && string[index_considered] == substring[index_substring]) {
index_substring++; index_substring++;
index_considered++; index_considered++;
} }
@ -325,7 +296,7 @@ bool string_get_is_substring(const string_t string_value, const string_t substri
return is_substring; return is_substring;
} }
string_t string_get_formatted_number(const long long number, string_t separator) { string_t string_get_formatted_number(const int64_t number, string_t separator) {
string_t number_string_temp = convert_number_to_string(number); string_t number_string_temp = convert_number_to_string(number);
string_t number_string = number_string_temp; string_t number_string = number_string_temp;
bool is_negative = number_string_temp[0] == '-'; bool is_negative = number_string_temp[0] == '-';
@ -337,6 +308,7 @@ string_t string_get_formatted_number(const long long number, string_t separator)
size_t formatted_length = number_string_length + (number_string_length - 1) / 3; size_t formatted_length = number_string_length + (number_string_length - 1) / 3;
string_t result = malloc(sizeof(char) * (formatted_length + 1)); 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;
@ -356,23 +328,21 @@ string_t string_get_formatted_number(const long long number, string_t separator)
} }
free(number_string); free(number_string);
result[formatted_length] = '\0'; result[formatted_length] = '\0';
string_t new_result = string_reverse(result); string_reverse(result);
free(result);
if (is_negative) { if (is_negative) {
string_t dash = convert_character_to_string('-'); string_t negative_result = convert_character_to_string('-');
string_t negative_result = string_concatenate(dash, new_result); string_concatenate(&negative_result, result);
free(new_result); free(result);
free(dash);
return negative_result; return negative_result;
} }
return new_result; return result;
} }
string_t string_get_last_occurence_of_character(const string_t string_value, char character) { string_t string_get_last_occurence_of_character(const string_t string, char character) {
size_t string_length = string_get_length(string_value); size_t string_length = string_get_length(string);
size_t index_last_occurrence = SIZE_MAX; size_t index_last_occurrence = SIZE_MAX;
for (size_t index = 0; index < string_length; index++) { for (size_t index = 0; index < string_length; index++) {
if (string_value[index] == character) { if (string[index] == character) {
index_last_occurrence = index; index_last_occurrence = index;
} }
} }
@ -381,35 +351,92 @@ string_t string_get_last_occurence_of_character(const string_t string_value, cha
} }
string_t result = malloc(sizeof(char) * (string_length - index_last_occurrence + 1)); 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 = index_last_occurrence; index < string_length; index++) {
result[index_result++] = string_value[index]; result[index_result++] = string[index];
} }
result[index_result] = '\0'; result[index_result] = '\0';
return result; return result;
} }
bool string_starts_with(const string_t string_value, const string_t prefix) { bool string_starts_with(const string_t string, const string_t prefix) {
bool starts_with = true; bool starts_with = true;
size_t prefix_length = string_get_length(prefix); size_t prefix_length = string_get_length(prefix);
for (size_t index = 0; index < prefix_length && starts_with; index++) { for (size_t index = 0; index < prefix_length && starts_with; index++) {
starts_with = string_value[index] == prefix[index]; starts_with = string[index] == prefix[index];
} }
return starts_with; return starts_with;
} }
bool string_ends_with(const string_t string_value, const string_t prefix) { bool string_ends_with(const string_t string, const string_t prefix) {
bool ends_with = true; bool ends_with = true;
size_t string_length = string_get_length(string_value); size_t string_length = string_get_length(string);
size_t prefix_length = string_get_length(prefix); size_t prefix_length = string_get_length(prefix);
size_t index_string = string_length - 1; size_t index_string = string_length - 1;
size_t index_prefix = prefix_length - 1; size_t index_prefix = prefix_length - 1;
while (index_prefix > 0 && ends_with) { while (index_prefix > 0 && ends_with) {
ends_with = string_value[index_string] == prefix[index_prefix]; ends_with = string[index_string] == prefix[index_prefix];
index_string--; index_string--;
index_prefix--; index_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,6 +1,7 @@
#ifndef __LIBCPROJECT_STRING__ #ifndef __LIBCPROJECT_STRING__
#define __LIBCPROJECT_STRING__ #define __LIBCPROJECT_STRING__
#include <errno.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -13,122 +14,155 @@
/** /**
* @brief Return the length of a string (excluding '\0'). * @brief Return the length of a string (excluding '\0').
* *
* @param string_value * @param string
* @return size_t
* @since v1.0.0 * @since v1.0.0
*/ */
size_t string_get_length(const string_t string_value); size_t string_get_length(const string_t string);
/** /**
* @brief Converts all the alphabetic characters in a string to uppercase. * @brief Converts all the alphabetic characters in a string to uppercase.
* *
* @param string_value * NOTE: Mutates the string.
*
* @param string
* @since v1.0.0 * @since v1.0.0
*/ */
string_t string_to_uppercase(string_t string_value); void string_to_uppercase(string_t string);
/** /**
* @brief Converts all the alphabetic characters in a string to lowercase. * @brief Converts all the alphabetic characters in a string to lowercase.
* *
* @param string_value * NOTE: Mutates the string.
*
* @param string
* @since v1.0.0 * @since v1.0.0
*/ */
string_t string_to_lowercase(string_t string_value); void string_to_lowercase(string_t 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.
* *
* @param string_value * NOTE: Mutates the string.
*
* @param string
* @param search A character search value. * @param search A character search value.
* @param replace A character containing the text to replace for match. * @param replace A character containing the text to replace for match.
* @since v1.0.0 * @since v1.0.0
*/ */
string_t string_replace(string_t string_value, char search, char replace); void string_replace(string_t string, char search, char replace);
/**
* @brief Removes all the occurrences of a character in a string.
*
* NOTE: Mutates the string.
*
* @param string
* @param search A character search value.
* @since v4.1.0
*/
void string_remove_character(string_t string, char search);
/** /**
* @brief Removes all `character` from the start of a string. * @brief Removes all `character` from the start of a string.
* *
* @param string_value * NOTE: Mutates the string.
*
* @param string
* @since v1.0.0 * @since v1.0.0
*/ */
string_t string_trim_start(string_t string_value, char character); void string_trim_start(string_t string, char character);
/** /**
* @brief Removes all `character` from the end of a string. * @brief Removes all `character` from the end of a string.
* *
* @param string_value * NOTE: Mutates the string.
*
* @param string
* @since v1.0.0 * @since v1.0.0
*/ */
string_t string_trim_end(string_t string_value, char character); void string_trim_end(string_t string, char character);
/** /**
* @brief Removes all `character` from the start and end of a string. * @brief Removes all `character` from the start and end of a string.
* *
* @param string_value * NOTE: Mutates the string.
*
* @param string
* @since v1.0.0 * @since v1.0.0
*/ */
string_t string_trim(string_t string_value, char character); void string_trim(string_t string, char character);
/** /**
* @brief Return the copy of a string. * @brief Return the copy of a string.
* *
* @param string_value * @param string
* @return string_t
* @since v1.0.0 * @since v1.0.0
*/ */
string_t string_copy(const string_t string_value); string_t string_copy(const string_t string);
/** /**
* @brief Capitalizes the string. * @brief Capitalizes the string.
* *
* @param string_value * NOTE: Mutates the string.
*
* @param string
* @since v1.0.0 * @since v1.0.0
*/ */
string_t string_capitalize(string_t string_value); void string_capitalize(string_t 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.
* *
* @param string_value * @param string
* @param character * @param character
* @return size_t
* @since v1.0.0 * @since v1.0.0
*/ */
size_t string_total_occurrences_of_character(string_t string_value, char character); size_t string_total_occurrences_of_character(string_t string, char character);
/** /**
* @brief Reverse the characters in an array. * @brief Reverse the characters in a string.
* *
* @param string_value * NOTE: Mutates the string.
*
* @param string
* @since v1.0.0 * @since v1.0.0
*/ */
string_t string_reverse(const string_t string_value); void string_reverse(const string_t 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, false otherwise. * @return true if the strings are equals.
* @return false if the strings are not equals.
* @since v1.0.0 * @since v1.0.0
*/ */
bool string_equals(const string_t string1, const string_t string2); bool string_equals(const string_t string1, const string_t string2);
/** /**
* @brief Check if the string is a integer. * @brief Check if the string is an integer.
* *
* @param string_value * @param string
* @return true if the string is a integer, false otherwise. * @return true if the string is an integer.
* @return false if the string is not an integer.
* @since v1.0.0 * @since v1.0.0
*/ */
bool string_get_is_integer(const string_t string_value); bool string_get_is_integer(const string_t 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_value * @param string
* @param separator * @param separator
* @param result_size * @param result_size
* @return string_t*
* @since v1.0.0 * @since v1.0.0
*/ */
string_t* string_split(const string_t string_value, char separator, size_t* result_size); string_t* string_split(const string_t 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.
@ -136,6 +170,7 @@ string_t* string_split(const string_t string_value, char separator, size_t* resu
* @param array * @param array
* @param separator * @param separator
* @param array_length * @param array_length
* @return string_t
* @since v1.0.0 * @since v1.0.0
*/ */
string_t string_join(string_t* array, const char separator, size_t array_length); string_t string_join(string_t* array, const char separator, size_t array_length);
@ -143,17 +178,20 @@ string_t string_join(string_t* array, const char separator, size_t array_length)
/** /**
* @brief Concatenate two strings. * @brief Concatenate two strings.
* *
* @param string1 * NOTE: Mutates the string `destination`.
* @param string2 *
* @param destination
* @param source
* @since v1.0.0 * @since v1.0.0
*/ */
string_t string_concatenate(string_t string1, string_t string2); void string_concatenate(string_t* destination, string_t source);
/** /**
* @brief Check if a string contains only unique characters. * @brief Check if a string contains only unique characters.
* *
* @param string * @param string
* @return true if string contains only unique characters, false otherwise. * @return true if string contains only unique characters.
* @return false if string contains duplicate characters.
* @since v1.0.0 * @since v1.0.0
*/ */
bool string_get_has_unique_characters(const string_t string); bool string_get_has_unique_characters(const string_t string);
@ -161,63 +199,130 @@ bool string_get_has_unique_characters(const string_t string);
/** /**
* @brief Returns the part of the string between the start and end indexes (both included). * @brief Returns the part of the string between the start and end indexes (both included).
* *
* @param string_value * @param string
* @param index_start * @param index_start
* @param index_end * @param index_end
* @return string_t
* @since v1.0.0 * @since v1.0.0
*/ */
string_t string_substring(const string_t string_value, size_t index_start, size_t index_end); string_t string_substring(const string_t 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_value * @param string
* @param substring * @param substring
* @return true if the string contains the substring, false otherwise. * @return true if the string contains the substring.
* @return false if the string does not contain the substring.
* @since v1.0.0 * @since v1.0.0
*/ */
bool string_get_is_substring(const string_t string_value, const string_t substring); bool string_get_is_substring(const string_t string, const string_t substring);
/** /**
* @brief Format a number to a string with specified separator. * @brief Format a number to a string with specified separator.
* *
* @param number * @param number
* @param separator * @param separator
* @since v1.0.0 * @return string_t
*
* @code * @code
* string_get_formatted_number(1000, " ") // "1 000" * string_get_formatted_number(1000, " ") // "1 000"
*
* string_get_formatted_number(1000, ",") // "1,000" * string_get_formatted_number(1000, ",") // "1,000"
* @endcode * @endcode
* @since v1.0.0
*/ */
string_t string_get_formatted_number(const long long number, string_t separator); string_t string_get_formatted_number(const int64_t number, string_t separator);
/** /**
* @brief Returns a pointer to the last occurrence of character in the string. * @brief Returns a pointer to the last occurrence of character in the string.
* *
* @param string_value * @param string
* @param character * @param character
* @return string_t
* @since v1.0.0 * @since v1.0.0
*/ */
string_t string_get_last_occurence_of_character(const string_t string_value, char character); string_t string_get_last_occurence_of_character(const string_t string, char character);
/** /**
* @brief Check if a string starts with a substring. * @brief Check if a string starts with a substring.
* *
* @param string_value * @param string
* @param prefix * @param prefix
* @return true if the string starts with the substring, false otherwise. * @return true if the string starts with the substring.
* @return false if the string does not start with the substring.
* @since v1.0.0 * @since v1.0.0
*/ */
bool string_starts_with(const string_t string_value, const string_t prefix); bool string_starts_with(const string_t string, const string_t prefix);
/** /**
* @brief Check if a string ends with a substring. * @brief Check if a string ends with a substring.
* *
* @param string_value * @param string
* @param prefix * @param prefix
* @return true if the string ends with the substring, false otherwise. * @return true if the string ends with the substring.
* @return false if the string does not end with the substring.
* @since v1.0.0 * @since v1.0.0
*/ */
bool string_ends_with(const string_t string_value, const string_t prefix); bool string_ends_with(const string_t string, const string_t 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

@ -3,39 +3,32 @@
string_t terminal_input() { string_t terminal_input() {
char character; char character;
size_t length = 1; size_t length = 1;
string_t string_value = malloc(length * sizeof(char)); string_t string = malloc(length * sizeof(char));
if (string_value == NULL) { if (string == NULL) {
perror("Error (terminal_input)");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
*string_value = '\0'; *string = '\0';
while ((character = getchar()) != '\n' && character != EOF) { while ((character = getchar()) != '\n' && character != EOF) {
length++; length++;
string_value = realloc(string_value, length * sizeof(char)); string = realloc(string, length * sizeof(char));
if (string_value == NULL) { if (string == NULL) {
perror("Error (terminal_input)");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
character_append(string_value, character); character_append(string, character);
} }
return string_value; return string;
}
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 = (char*)array + index * element_size;
print_element(element);
bool is_last = index == array_size - 1;
if (!is_last) {
printf(", ");
}
}
printf("]\n");
} }
void terminal_print_int(void* value) { void terminal_print_int(void* value) {
printf("%d", *(int*)value); printf("%d", *(int*)value);
} }
void terminal_print_bool(void* value) {
printf("%s", *(bool*)value ? "true" : "false");
}
void terminal_print_long(void* value) { void terminal_print_long(void* value) {
printf("%ld", *(long*)value); printf("%ld", *(long*)value);
} }
@ -44,23 +37,78 @@ 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", *(char*)value); printf("%c", *(string_t)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", (char*)value); printf("%s", (string_t)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 = (char*)node_current->data; void* element = 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");
} }
@ -68,13 +116,15 @@ 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 = (char*)node_current->data; void* element = 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");
} }
@ -82,13 +132,15 @@ 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 = (char*)node_current->data; void* element = (string_t)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");
@ -96,6 +148,8 @@ void terminal_print_linked_list(struct linked_list* linked_list, void (*print_el
void terminal_print_hash_map(struct hash_map* hash_map, void (*print_element)(void*)) { void terminal_print_hash_map(struct hash_map* hash_map, void (*print_element)(void*)) {
if (hash_map == NULL) { if (hash_map == NULL) {
errno = EINVAL;
perror("Error (terminal_print_hash_map)");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
printf("{\n"); printf("{\n");
@ -106,12 +160,21 @@ void terminal_print_hash_map(struct hash_map* hash_map, void (*print_element)(vo
printf("\t\""); printf("\t\"");
terminal_print_string(key); terminal_print_string(key);
printf("\" -> "); printf("\" -> ");
print_element(&value); print_element(value);
printf("\n"); printf("\n");
} }
printf("}\n"); printf("}\n");
free(keys);
} }
void terminal_print_array_list(struct array_list* list, void (*print_element)(void*)) { void terminal_print_array_list(struct array_list* list, void (*print_element)(void*)) {
terminal_print_array(list->data, list->size, sizeof(void*), print_element); 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,6 +1,7 @@
#ifndef __LIBCPROJECT_TERMINAL__ #ifndef __LIBCPROJECT_TERMINAL__
#define __LIBCPROJECT_TERMINAL__ #define __LIBCPROJECT_TERMINAL__
#include <errno.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
@ -16,21 +17,12 @@
/** /**
* @brief Read a line from stdin. * @brief Read a line from stdin.
*
* @return string_t
* @since v1.0.0 * @since v1.0.0
*/ */
string_t terminal_input(); string_t terminal_input();
/**
* @brief Print an array.
*
* @param array
* @param array_size
* @param element_size
* @param print_element
* @since v1.0.0
*/
void terminal_print_array(void* array, size_t array_size, size_t element_size, void (*print_element)(void*));
/** /**
* @brief Print a int. * @brief Print a int.
* *
@ -39,6 +31,14 @@ void terminal_print_array(void* array, size_t array_size, size_t element_size, v
*/ */
void terminal_print_int(void* value); 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. * @brief Print a long.
* *
@ -55,6 +55,86 @@ void terminal_print_long(void* value);
*/ */
void terminal_print_unsigned_long(void* value); 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. * @brief Print a char.
* *
@ -63,6 +143,17 @@ void terminal_print_unsigned_long(void* value);
*/ */
void terminal_print_char(void* value); 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*));
/** /**
* @brief Print a string. * @brief Print a string.
* *
@ -110,7 +201,7 @@ void terminal_print_hash_map(struct hash_map* hash_map, void (*print_element)(vo
/** /**
* @brief Print an array list. * @brief Print an array list.
* *
* @param array_list * @param list
* @param print_element * @param print_element
* @since v3.0.0 * @since v3.0.0
*/ */

View File

@ -7,4 +7,7 @@ typedef uint8_t byte_t;
typedef char* string_t; typedef char* string_t;
typedef float float32_t;
typedef double float64_t;
#endif #endif

View File

@ -2,8 +2,10 @@
#define __LIBCPROJECT__ #define __LIBCPROJECT__
#include "lib/array_list.h" #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/filesystem.h" #include "lib/filesystem.h"
#include "lib/hash_map.h" #include "lib/hash_map.h"
#include "lib/linked_list.h" #include "lib/linked_list.h"

133
main.c
View File

@ -4,8 +4,135 @@
#include "libcproject.h" #include "libcproject.h"
int main() { int main() {
string_t string_value = "Hello, world!"; int integer = 5;
printf("%s\n", string_value); terminal_print_int(&integer);
printf("string_length = %ld\n", string_get_length(string_value)); printf("\n");
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

@ -8,14 +8,15 @@ int main(int argc, string_t* argv) {
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 = "#ifndef __LIBCPROJECT_VERSION__\n"; string_t content = string_copy("#ifndef __LIBCPROJECT_VERSION__\n");
content = string_concatenate(content, "#define __LIBCPROJECT_VERSION__ \""); string_concatenate(&content, "#define __LIBCPROJECT_VERSION__ \"");
content = string_concatenate(content, argv[1]); string_concatenate(&content, argv[1]);
content = string_concatenate(content, "\"\n\n"); string_concatenate(&content, "\"\n\n");
content = string_concatenate(content, "#endif\n"); string_concatenate(&content, "#endif\n");
int result = filesystem_write("./version.h", (byte_t*)content, string_get_length(content)); int result = filesystem_write("./version.h", (byte_t*)content, string_get_length(content));
if (result == -1) { if (result == -1) {
fprintf(stderr, "Error: Could not write to file.\n"); fprintf(stderr, "Error: Could not write to file.\n");
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]);

View File

@ -34,4 +34,15 @@ void array_list_test() {
assert(array_list_get(list, 100) == (void *)95); assert(array_list_get(list, 100) == (void *)95);
array_list_free(list); 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

@ -6,7 +6,6 @@
#include <stdlib.h> #include <stdlib.h>
#include "libcproject.h" #include "libcproject.h"
#include "test.h"
void character_test(); void character_test();

View File

@ -10,7 +10,7 @@ void convert_test() {
} }
void convert_character_to_string_test() { void convert_character_to_string_test() {
char* result = convert_character_to_string('a'); string_t result = convert_character_to_string('a');
assert(assert_string_equal(result, "a")); assert(assert_string_equal(result, "a"));
free(result); free(result);
@ -77,7 +77,7 @@ void convert_string_to_number_test() {
} }
void convert_number_to_string_test() { void convert_number_to_string_test() {
char* result = convert_number_to_string(0); string_t result = convert_number_to_string(0);
assert(assert_string_equal(result, "0")); assert(assert_string_equal(result, "0"));
free(result); free(result);
@ -143,7 +143,7 @@ void convert_number_to_string_test() {
} }
void convert_number_from_base_to_another_test() { void convert_number_from_base_to_another_test() {
char* result = convert_number_from_base_to_another("15", 10, 16); string_t result = convert_number_from_base_to_another("15", 10, 16);
assert(assert_string_equal(result, "F")); assert(assert_string_equal(result, "F"));
free(result); free(result);

View File

@ -6,7 +6,6 @@
#include <stdlib.h> #include <stdlib.h>
#include "libcproject.h" #include "libcproject.h"
#include "test.h"
void convert_test(); void convert_test();

191
test/date_test.c Normal file
View File

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

26
test/date_test.h Normal file
View File

@ -0,0 +1,26 @@
#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

View File

@ -4,6 +4,7 @@
#include "array_list_test.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 "hash_map_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"
@ -15,6 +16,7 @@ int main() {
array_list_test(); array_list_test();
character_test(); character_test();
convert_test(); convert_test();
date_test();
hash_map_test(); hash_map_test();
linked_list_test(); linked_list_test();
mathematics_test(); mathematics_test();

View File

@ -6,6 +6,11 @@ void mathematics_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() {
@ -56,3 +61,38 @@ 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

@ -17,4 +17,14 @@ 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

@ -5,6 +5,7 @@ void string_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();
@ -24,52 +25,64 @@ 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!"; string_t string = "Hello World!";
size_t string_length = string_get_length(string); size_t string_length = string_get_length(string);
assert(string_length == 12); assert(string_length == 12);
assert(strlen(string) == string_length);
} }
void string_to_uppercase_test() { void string_to_uppercase_test() {
string_t string = "heLlO world"; string_t string = string_copy("heLlO world");
string = string_to_uppercase(string); string_to_uppercase(string);
assert(assert_string_equal(string, "HELLO WORLD")); assert(assert_string_equal(string, "HELLO WORLD"));
free(string); free(string);
} }
void string_to_lowercase_test() { void string_to_lowercase_test() {
string_t string = "HellO WoRLd"; string_t string = string_copy("HellO WoRLd");
string = string_to_lowercase(string); string_to_lowercase(string);
assert(assert_string_equal(string, "hello world")); assert(assert_string_equal(string, "hello world"));
free(string); free(string);
} }
void string_replace_test() { void string_replace_test() {
string_t string = "hello world"; string_t string = string_copy("hello world");
string = string_replace(string, 'l', 'z'); string_replace(string, 'l', 'z');
assert(assert_string_equal(string, "hezzo worzd")); assert(assert_string_equal(string, "hezzo worzd"));
free(string); 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 = " hello world "; string_t string = string_copy(" hello world ");
string = string_trim_start(string, ' '); string_trim_start(string, ' ');
assert(assert_string_equal(string, "hello world ")); assert(assert_string_equal(string, "hello world "));
free(string); free(string);
} }
void string_trim_end_test() { void string_trim_end_test() {
string_t string = " hello world "; string_t string = string_copy(" hello world ");
string = string_trim_end(string, ' '); string_trim_end(string, ' ');
assert(assert_string_equal(string, " hello world")); assert(assert_string_equal(string, " hello world"));
free(string); free(string);
} }
void string_trim_test() { void string_trim_test() {
string_t string = " hello world "; string_t string = string_copy(" hello world ");
string = string_trim(string, ' '); string_trim(string, ' ');
assert(assert_string_equal(string, "hello world")); assert(assert_string_equal(string, "hello world"));
free(string); free(string);
} }
@ -86,8 +99,8 @@ void string_copy_test() {
} }
void string_capitalize_test() { void string_capitalize_test() {
string_t string = "hello world"; string_t string = string_copy("hello world");
string = string_capitalize(string); string_capitalize(string);
assert(assert_string_equal(string, "Hello world")); assert(assert_string_equal(string, "Hello world"));
free(string); free(string);
} }
@ -98,8 +111,8 @@ void string_total_occurrences_of_character_test() {
} }
void string_reverse_test() { void string_reverse_test() {
string_t string = "hello world"; string_t string = string_copy("hello world");
string = string_reverse(string); string_reverse(string);
assert(assert_string_equal(string, "dlrow olleh")); assert(assert_string_equal(string, "dlrow olleh"));
free(string); free(string);
} }
@ -157,12 +170,14 @@ void string_join_test() {
} }
void string_concatenate_test() { void string_concatenate_test() {
char* result = string_concatenate("abc", "def"); string_t result = string_copy("abc");
string_concatenate(&result, "def");
assert(assert_string_equal(result, "abcdef")); assert(assert_string_equal(result, "abcdef"));
free(result); free(result);
result = string_concatenate("abc", " defghi"); result = string_copy("abcz");
assert(assert_string_equal(result, "abc defghi")); string_concatenate(&result, " defghi");
assert(assert_string_equal(result, "abcz defghi"));
free(result); free(result);
} }
@ -192,7 +207,7 @@ void string_get_is_substring_test() {
} }
void string_get_formatted_number_test() { void string_get_formatted_number_test() {
char* result = string_get_formatted_number(1000, " "); string_t result = string_get_formatted_number(1000, " ");
assert(assert_string_equal(result, "1 000")); assert(assert_string_equal(result, "1 000"));
free(result); free(result);
@ -224,7 +239,7 @@ void string_get_formatted_number_test() {
void string_get_last_occurence_of_character_test() { void string_get_last_occurence_of_character_test() {
string_t string = "abcdef"; string_t string = "abcdef";
char* result = string_get_last_occurence_of_character(string, 'a'); string_t result = string_get_last_occurence_of_character(string, 'a');
assert(assert_string_equal(result, "abcdef")); assert(assert_string_equal(result, "abcdef"));
free(result); free(result);
@ -266,3 +281,55 @@ 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

@ -6,7 +6,6 @@
#include <stdlib.h> #include <stdlib.h>
#include "libcproject.h" #include "libcproject.h"
#include "test.h"
void string_test(); void string_test();
@ -18,6 +17,8 @@ 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();
@ -56,4 +57,12 @@ 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

View File

@ -1,14 +0,0 @@
#ifndef __TEST__
#define __TEST__
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include "libcproject.h"
bool assert_string_equal(const string_t actual, const string_t expected);
bool assert_string_not_equal(const string_t actual, const string_t expected);
#endif

View File

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