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

25 Commits

Author SHA1 Message Date
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
01e9b71402 chore(release): 3.1.0 [skip ci] 2023-08-06 14:43:01 +00:00
5c6f4d8192 feat: improvements to filesystem_get_mimetype 2023-08-06 16:39:33 +02:00
d604288365 docs: improve usage explanations 2023-08-06 16:12:10 +02:00
dff2836bfc feat: add filesystem_remove 2023-08-06 12:14:13 +02:00
ad0a460923 feat: add filesystem_exists 2023-08-06 12:06:43 +02:00
be8a63ca8a chore(release): 3.0.0 [skip ci] 2023-08-05 13:40:47 +00:00
693cab7a34 chore: only use sanitizer flags in test 2023-08-05 15:33:19 +02:00
3220c0e26b chore: update @since version 2023-08-05 15:03:53 +02:00
06b34b115b feat: support giving a custom character for string_trim, string_trim_start, string_trim_end
BREAKING CHANGE: Functions signatures changed.
If you want to preserve the same behavior, you should pass explictly the space character to trim:
Example: `string_trim(" Hello ")` => `string_trim(" Hello ", ' ')`
2023-08-05 14:19:44 +02:00
316dfa10e7 chore: improve Makefile to use -fsanitize=address -fsanitize=undefined gcc flags
Fixes #5
2023-08-04 19:58:41 +02:00
145dfcf546 fix: more memory issues thanks to -fsanitize=address flag
Work In Progress #5
2023-08-04 19:20:00 +02:00
d345c90ba3 style: fix linting 2023-08-04 00:02:35 +02:00
209440588d fix: more memory issues thanks to -fsanitize=address flag
Work In Progress #5
2023-08-03 23:55:14 +02:00
a0a1310f53 feat: add hash_map_free 2023-08-03 23:17:54 +02:00
8b6f06dc6e feat: add stack_free 2023-08-03 23:01:19 +02:00
1e475a59b1 feat: add queue_free 2023-08-03 22:57:32 +02:00
6a40df3ad1 feat: add linked_list_free 2023-08-03 19:48:02 +02:00
d231a0f055 feat: add array_list_free 2023-08-03 19:42:50 +02:00
2796dec0c7 fix: memory issues thanks to -fsanitize=address flag
Work In Progress #5
2023-08-03 19:35:44 +02:00
9717cff35a feat: add terminal_print_array_list 2023-07-31 23:51:37 +02:00
368c07c57a fix: char* issues with memory allocation
Work In progress #5
2023-06-26 22:32:26 +02:00
37 changed files with 1031 additions and 472 deletions

View File

@ -12,6 +12,8 @@ jobs:
steps:
- uses: 'actions/checkout@v3.5.3'
- run: 'sudo apt update'
- name: 'Install Build Tools'
run: 'sudo apt-get install --yes build-essential gcc make clang-format'

View File

@ -21,18 +21,23 @@ jobs:
git_user_signingkey: true
git_commit_gpgsign: true
- run: 'sudo apt update'
- name: 'Install Build Tools'
run: 'sudo apt-get install --yes build-essential gcc make clang-format doxygen doxygen-gui doxygen-doc graphviz'
run: 'sudo apt-get install --yes build-essential gcc make clang-format'
- name: 'Install Documentation Tools'
run: 'sudo apt-get install --yes doxygen doxygen-gui doxygen-doc graphviz'
- run: 'make set_version'
- name: 'Use Node.js'
uses: 'actions/setup-node@v3.6.0'
uses: 'actions/setup-node@v3.7.0'
with:
node-version: '18.16.1'
node-version: '18.17.0'
- name: 'Install Release Tools'
run: 'npm install --save-dev semantic-release@21.0.5 @commitlint/cli@17.6.6 @commitlint/config-conventional@17.6.6 @semantic-release/git@10.0.1 @semantic-release/exec@6.0.3 @saithodev/semantic-release-backmerge@3.2.0 vercel@30.2.3'
run: 'npm install --save-dev semantic-release@21.0.7 @commitlint/cli@17.6.7 @commitlint/config-conventional@17.6.7 @semantic-release/git@10.0.1 @semantic-release/exec@6.0.3 @saithodev/semantic-release-backmerge@3.2.0 vercel@31.2.2'
- run: 'rm --force package.json package-lock.json'

2
.gitignore vendored
View File

@ -6,3 +6,5 @@ documentation
*.o
*.a
node_modules
package.json
package-lock.json

View File

@ -1,6 +1,7 @@
LIBRARY_NAME = libcproject
CC = gcc
CC_FLAGS = -Wall -Wextra -Wfloat-equal -Wundef -Werror -std=c17 -pedantic -pedantic-errors -O3 -I./
CC_SANITIZER_FLAGS = -fsanitize=address -fsanitize=undefined
LIB = ./build/${LIBRARY_NAME}.a
LIB_CC_FLAGS = -L. -l:${LIB}
LIB_SOURCES = $(wildcard lib/*.c)
@ -31,18 +32,18 @@ build/test/%.o: test/%.c ${HEADER_FILES} | build/test
.PHONY: run
run: ${LIB} ./main.c
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}
.PHONY: set_version
set_version: ${LIB} ./set_version.c
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
test: ${LIB} $(addprefix build/, ${TEST_OBJECTS})
mkdir --parents ./bin
${CC} ${CC_FLAGS} -o ${TEST_EXECUTABLE} $(addprefix build/, ${TEST_OBJECTS}) ${LIB_CC_FLAGS}
${CC} ${CC_FLAGS} ${CC_SANITIZER_FLAGS} -o ${TEST_EXECUTABLE} $(addprefix build/, ${TEST_OBJECTS}) ${LIB_CC_FLAGS}
./${TEST_EXECUTABLE} ${ARGS}
.PHONY: lint

View File

@ -20,7 +20,7 @@
C is a low-level programming language and we often end up reinventing the wheel as the C standard library (`libc`) is quite small and in my humble opinion, not well designed.
**libcproject** solve this by providing common functions or data structures (`hash_map`, `array_list`, `linked_list`, `queue`, `stack`, etc.) we might need in our C projects.
**libcproject** solve this by providing common functions or data structures (`hash_map`, `array_list`, `linked_list`, `queue`, `stack`, etc.), we might need in our C projects.
[Online documentation](https://libcproject.vercel.app/).
@ -36,7 +36,10 @@ C is a low-level programming language and we often end up reinventing the wheel
For example on GNU/Linux Ubuntu:
```sh
# Install Build Tools
sudo apt-get install build-essential gcc make clang-format
# Install Documentation Tools
sudo apt-get install doxygen doxygen-gui doxygen-doc graphviz
```
@ -55,7 +58,14 @@ nm ./build/libcproject.a # to see the symbols
Steps to create a new C project that uses `libcproject`:
### Step 1: Install and Compile `libcproject`
### Step 1: Create a new project
```sh
mkdir my-project
cd my-project
```
### Step 2: Install and Compile `libcproject` in the project
```sh
# Clone the repository
@ -68,25 +78,10 @@ cd libcproject
make
```
### Step 2: Create a new project
```sh
mkdir my-project
cd my-project
```
### Step 3: Install `libcproject` in the project
```sh
mkdir libcproject
cp --recursive <path-to-libcproject> ./ # copy
# or
ln -s <path-to-libcproject> ./ # symbolic link
```
### Step 4: Create a new C file
### Step 3: Create a new C file
```sh
cd ..
touch main.c
```
@ -97,14 +92,14 @@ touch main.c
#include "libcproject/libcproject.h"
int main() {
string_t string_value = "Hello, world!"; // `string_t` is a typedef from `libcproject`
printf("%s\n", string_value);
printf("string_length = %ld\n", string_get_length(string_value)); // `string_get_length` is a function from `libcproject`
string_t string = "Hello, world!"; // `string_t` is a typedef from `libcproject`
printf("%s\n", string);
printf("string_length = %ld\n", string_get_length(string)); // `string_get_length` is a function from `libcproject`
return EXIT_SUCCESS;
}
```
### Step 5: Compile your project and link it with the library
### Step 4: Compile your project and link it with the library
```sh
gcc -o ./main ./main.c -L. -l:./libcproject/build/libcproject.a

View File

@ -37,3 +37,8 @@ void* array_list_get(struct array_list* list, size_t index) {
}
return list->data[index];
}
void array_list_free(struct array_list* list) {
free(list->data);
free(list);
}

View File

@ -1,6 +1,7 @@
#ifndef __LIBCPROJECT_ARRAY_LIST__
#define __LIBCPROJECT_ARRAY_LIST__
#include <errno.h>
#include <stdbool.h>
#include <stdlib.h>
@ -42,4 +43,10 @@ void array_list_remove(struct array_list* list, size_t index);
*/
void* array_list_get(struct array_list* list, size_t index);
/**
* @brief Frees the array list.
* @since v3.0.0
*/
void array_list_free(struct array_list* list);
#endif

View File

@ -1,17 +1,17 @@
#include "character.h"
void character_append(string_t string_value, const char character) {
size_t length = string_get_length(string_value);
character_append_at(string_value, character, length);
void character_append(string_t string, const char character) {
size_t length = string_get_length(string);
character_append_at(string, character, length);
}
void character_append_at(string_t string_value, const char character, const size_t index) {
size_t length = string_get_length(string_value);
void character_append_at(string_t string, const char character, const size_t index) {
size_t length = string_get_length(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_value[length + 1] = '\0';
string[index] = character;
string[length + 1] = '\0';
}
char character_to_upper(const char character) {

View File

@ -1,6 +1,7 @@
#ifndef __LIBCPROJECT_CHARACTER__
#define __LIBCPROJECT_CHARACTER__
#include <errno.h>
#include <stdbool.h>
#include <stdlib.h>
@ -11,21 +12,21 @@
* @brief Append a character to a string, assuming string points to an array
* with enough space.
*
* @param string_value
* @p
* @param character
* @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.
*
* @param string_value
* @param string
* @param character
* @param index
* @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.

View File

@ -1,11 +1,13 @@
#include "convert.h"
string_t convert_character_to_string(const char character) {
string_t string = malloc(sizeof(string) * 2);
string_t string = malloc(sizeof(char) * 2);
if (string == NULL) {
perror("Error (convert_character_to_string)");
exit(EXIT_FAILURE);
}
character_append(string, character);
string[0] = character;
string[1] = '\0';
return string;
}
@ -17,12 +19,12 @@ char convert_digit_to_character(const char digit) {
return digit + '0';
}
long long convert_string_to_number(const string_t string_value) {
bool is_negative = string_value[0] == '-';
long long convert_string_to_number(const string_t string) {
bool is_negative = string[0] == '-';
long long 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++) {
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;
}
@ -33,23 +35,31 @@ string_t convert_number_to_string(const long long integer) {
}
bool is_negative = integer < 0;
size_t length = 1;
string_t string_value = malloc(sizeof(string_t) * length);
if (string_value == NULL) {
exit(EXIT_FAILURE);
}
long long current = mathematics_absolute_value(integer);
while (current != 0) {
character_append(string_value, convert_digit_to_character(current % 10));
current = current / 10;
length++;
string_value = realloc(string_value, sizeof(string_t) * length);
}
if (is_negative) {
character_append(string_value, '-');
length++;
string_value = realloc(string_value, sizeof(string_t) * length);
}
return string_reverse(string_value);
string_t string = malloc(sizeof(char) * length);
if (string == NULL) {
perror("Error (convert_number_to_string)");
exit(EXIT_FAILURE);
}
current = mathematics_absolute_value(integer);
size_t index = 0;
while (current != 0) {
string[index++] = convert_digit_to_character(current % 10);
current = current / 10;
}
if (is_negative) {
string[index++] = '-';
}
string[index] = '\0';
string_reverse(string);
return string;
}
string_t convert_number_from_base_10_to_base(unsigned long long number, unsigned int base) {
@ -63,7 +73,7 @@ string_t convert_number_from_base_10_to_base(unsigned long long number, unsigned
number = number / base;
index++;
}
string_t result = malloc(sizeof(string_t) * (index + 1));
string_t result = malloc(sizeof(char) * (index + 1));
int index_result = 0;
for (int iteration = index - 1; iteration >= 0; iteration--) {
int remainder = remainders[iteration];
@ -74,6 +84,7 @@ string_t convert_number_from_base_10_to_base(unsigned long long number, unsigned
}
index_result++;
}
result[index_result] = '\0';
return result;
}

View File

@ -1,6 +1,7 @@
#ifndef __LIBCPROJECT_CONVERT__
#define __LIBCPROJECT_CONVERT__
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
@ -37,10 +38,10 @@ char convert_digit_to_character(const char digit);
/**
* @brief Convert a string to a number.
*
* @param string_value
* @param string
* @since v1.0.0
*/
long long convert_string_to_number(const string_t string_value);
long long convert_string_to_number(const string_t string);
/**
* @brief Convert a number to a string.

View File

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

View File

@ -38,9 +38,32 @@ int filesystem_read(string_t path, byte_t **file_content, off_t *file_size);
int filesystem_write(string_t path, byte_t *file_content, off_t file_size);
/**
* @brief Get the mimetype of a file.
* @brief Check if a path exists.
*
* @param path
* @retval true if the path exists.
* @retval false if the path does not exist.
* @since v3.1.0
*/
bool filesystem_exists(string_t path);
/**
* @brief Removes a path.
*
* @param path
* @return int
* @retval -1 if there is an error.
* @retval 0 for success.
* @since v3.1.0
*/
int filesystem_remove(string_t path);
/**
* @brief Get the mimetype of a file based on its extension.
*
* @param path
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types
* @see https://www.iana.org/assignments/media-types/media-types.xhtml
* @since v1.0.0
*/
string_t filesystem_get_mimetype(string_t path);

View File

@ -2,31 +2,7 @@
#define ROTATE_LEFT(x, b) (((x) << (b)) | ((x) >> (64 - (b))))
uint64_t hash(string_t key, size_t capacity) {
size_t key_length = string_get_length(key);
const uint64_t c = 0x736f6d6570736575;
uint64_t v0 = 0x736f6d6570736575 ^ c;
uint64_t v1 = 0x646f72616e646f6d ^ c;
uint64_t v2 = 0x6c7967656e657261 ^ c;
uint64_t v3 = 0x7465646279746573 ^ c;
uint64_t k1;
uint64_t m;
uint8_t *message = (uint8_t *)key;
size_t remaining = key_length;
uint64_t hash;
message += sizeof(uint64_t);
k1 = *(uint64_t *)message;
if (key_length % sizeof(uint64_t) != 0) {
memcpy(&k1, key + (key_length - sizeof(uint64_t)), sizeof(uint64_t));
}
while (remaining >= 8) {
memcpy(&m, message, sizeof(uint64_t));
v3 ^= m;
for (int i = 0; i < 2; i++) {
uint64_t sip_round(uint64_t v0, uint64_t v1, uint64_t v2, uint64_t v3) {
v0 += v1;
v2 += v3;
v1 = ROTATE_LEFT(v1, 13);
@ -41,36 +17,72 @@ uint64_t hash(string_t key, size_t capacity) {
v1 ^= v2;
v3 ^= v0;
v2 = ROTATE_LEFT(v2, 32);
return v0;
}
uint64_t hash(string_t key, size_t capacity) {
size_t key_length = string_get_length(key);
const uint64_t c = 0x736f6d6570736575;
uint64_t v0 = c ^ 0x736f6d6570736575;
uint64_t v1 = c ^ 0x646f72616e646f6d;
uint64_t v2 = c ^ 0x6c7967656e657261;
uint64_t v3 = c ^ 0x7465646279746573;
uint64_t m;
uint64_t hash;
uint8_t *message = (uint8_t *)key;
size_t remaining = key_length;
size_t offset = 0;
while (remaining >= 8) {
memcpy(&m, message + offset, sizeof(uint64_t));
v3 ^= m;
for (int i = 0; i < 2; i++) {
v0 = sip_round(v0, v1, v2, v3);
v1 = ROTATE_LEFT(v1, 13);
v2 = ROTATE_LEFT(v2, 16);
v3 = ROTATE_LEFT(v3, 32);
v0 ^= m;
}
v0 ^= m;
v2 ^= 0xff;
for (int i = 0; i < 4; i++) {
v0 = sip_round(v0, v1, v2, v3);
v1 = ROTATE_LEFT(v1, 13);
v2 = ROTATE_LEFT(v2, 16);
v3 = ROTATE_LEFT(v3, 32);
}
hash = v0 ^ v1 ^ v2 ^ v3;
remaining -= sizeof(uint64_t);
message += sizeof(uint64_t);
offset += sizeof(uint64_t);
}
m = (uint64_t)remaining << 56;
switch (remaining) {
case 7:
m |= (uint64_t)message[6] << 48;
m |= (uint64_t)message[offset + 6] << 48;
break;
case 6:
m |= (uint64_t)message[5] << 40;
m |= (uint64_t)message[offset + 5] << 40;
break;
case 5:
m |= (uint64_t)message[4] << 32;
m |= (uint64_t)message[offset + 4] << 32;
break;
case 4:
m |= (uint64_t)message[3] << 24;
m |= (uint64_t)message[offset + 3] << 24;
break;
case 3:
m |= (uint64_t)message[2] << 16;
m |= (uint64_t)message[offset + 2] << 16;
break;
case 2:
m |= (uint64_t)message[1] << 8;
m |= (uint64_t)message[offset + 1] << 8;
break;
case 1:
m |= (uint64_t)message[0];
m |= (uint64_t)message[offset];
break;
default:
break;
@ -79,40 +91,20 @@ uint64_t hash(string_t key, size_t capacity) {
v3 ^= m;
for (int i = 0; i < 2; i++) {
v0 += v1;
v2 += v3;
v0 = sip_round(v0, v1, v2, v3);
v1 = ROTATE_LEFT(v1, 13);
v3 = ROTATE_LEFT(v3, 16);
v1 ^= v0;
v3 ^= v2;
v0 = ROTATE_LEFT(v0, 32);
v2 += v1;
v0 += v3;
v1 = ROTATE_LEFT(v1, 17);
v3 = ROTATE_LEFT(v3, 21);
v1 ^= v2;
v3 ^= v0;
v2 = ROTATE_LEFT(v2, 32);
v2 = ROTATE_LEFT(v2, 16);
v3 = ROTATE_LEFT(v3, 32);
}
v0 ^= m;
v2 ^= 0xff;
for (int i = 0; i < 4; i++) {
v0 += v1;
v2 += v3;
v0 = sip_round(v0, v1, v2, v3);
v1 = ROTATE_LEFT(v1, 13);
v3 = ROTATE_LEFT(v3, 16);
v1 ^= v0;
v3 ^= v2;
v0 = ROTATE_LEFT(v0, 32);
v2 += v1;
v0 += v3;
v1 = ROTATE_LEFT(v1, 17);
v3 = ROTATE_LEFT(v3, 21);
v1 ^= v2;
v3 ^= v0;
v2 = ROTATE_LEFT(v2, 32);
v2 = ROTATE_LEFT(v2, 16);
v3 = ROTATE_LEFT(v3, 32);
}
hash = v0 ^ v1 ^ v2 ^ v3;
@ -131,7 +123,7 @@ struct hash_map *hash_map_initialization() {
return hash_map;
}
void hash_map_add(struct hash_map *hash_map, string_t key, void *data) {
void hash_map_add(struct hash_map *hash_map, string_t key_value, void *data) {
if (hash_map->length == hash_map->capacity) {
size_t previous_capacity = hash_map->capacity;
hash_map->capacity += HASH_MAP_INITIAL_CAPACITY;
@ -140,6 +132,7 @@ void hash_map_add(struct hash_map *hash_map, string_t key, void *data) {
hash_map->items[index] = NULL;
}
}
string_t key = string_copy(key_value);
uint64_t hash_value = hash(key, hash_map->capacity);
struct linked_list *list = hash_map->items[hash_value];
struct hash_map_item *item = malloc(sizeof(struct hash_map_item));
@ -164,6 +157,9 @@ void hash_map_add(struct hash_map *hash_map, string_t key, void *data) {
if (!found) {
linked_list_add_in_head(list, (void *)item);
hash_map->length++;
} else {
free(key);
free(item);
}
}
}
@ -180,10 +176,13 @@ void hash_map_remove(struct hash_map *hash_map, string_t key) {
struct hash_map_item *item = (struct hash_map_item *)node->data;
if (!string_equals(key, item->key)) {
linked_list_add_in_head(new_list, item);
} else {
free(item->key);
free(item);
}
node = node->next;
}
free(list);
linked_list_free(list);
hash_map->items[hash_value] = new_list;
hash_map->length--;
}
@ -225,3 +224,21 @@ string_t *hash_map_get_keys(struct hash_map *hash_map) {
}
return keys;
}
void hash_map_free(struct hash_map *hash_map) {
for (size_t index = 0; index < hash_map->capacity; index++) {
struct linked_list *list = hash_map->items[index];
if (list != NULL) {
struct linked_list_node *node = list->head;
while (node != NULL) {
struct hash_map_item *item = (struct hash_map_item *)node->data;
free(item->key);
free(item);
node = node->next;
}
linked_list_free(list);
}
}
free(hash_map->items);
free(hash_map);
}

View File

@ -1,6 +1,7 @@
#ifndef __LIBCPROJECT_HASH_MAP__
#define __LIBCPROJECT_HASH_MAP__
#include <errno.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
@ -89,4 +90,10 @@ bool hash_map_contains_key(struct hash_map *hash_map, string_t key);
*/
string_t *hash_map_get_keys(struct hash_map *hash_map);
/**
* @brief Frees the hash map.
* @since v3.0.0
*/
void hash_map_free(struct hash_map *hash_map);
#endif

View File

@ -3,6 +3,7 @@
struct linked_list *linked_list_initialization() {
struct linked_list *list = malloc(sizeof(*list));
if (list == NULL) {
perror("Error (linked_list_initialization)");
exit(EXIT_FAILURE);
}
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) {
if (list == NULL) {
errno = EINVAL;
perror("Error (linked_list_add_in_head)");
exit(EXIT_FAILURE);
}
struct linked_list_node *node_new = malloc(sizeof(*node_new));
if (list == NULL || node_new == NULL) {
if (node_new == NULL) {
perror("Error (linked_list_add_in_head)");
exit(EXIT_FAILURE);
}
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) {
if (list == NULL) {
errno = EINVAL;
perror("Error (linked_list_delete_in_head)");
exit(EXIT_FAILURE);
}
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) {
if (list == NULL) {
errno = EINVAL;
perror("Error (linked_list_add_after_last)");
exit(EXIT_FAILURE);
}
if (list->head == NULL) {
return linked_list_add_in_head(list, new_data);
}
struct linked_list_node *node_new = malloc(sizeof(*node_new));
if (list == NULL || node_new == NULL) {
if (node_new == NULL) {
perror("Error (linked_list_add_after_last)");
exit(EXIT_FAILURE);
}
node_new->data = new_data;
@ -68,6 +83,7 @@ struct linked_list *linked_list_reverse(struct linked_list *list) {
linked_list_add_after_last(linked_list_reversed, stack_node_current->data);
stack_node_current = stack_node_current->next;
}
stack_free(stack);
return linked_list_reversed;
}
@ -84,3 +100,14 @@ void linked_list_reverse_mutate(struct linked_list *list) {
(*current) = temporary_current;
}
}
void linked_list_free(struct linked_list *list) {
struct linked_list_node *node_current = list->head;
while (node_current != NULL) {
struct linked_list_node *node_to_remove = node_current;
node_current = node_current->next;
free(node_to_remove);
}
list->head = NULL;
free(list);
}

View File

@ -1,6 +1,7 @@
#ifndef __LIBCPROJECT_LINKED_LIST__
#define __LIBCPROJECT_LINKED_LIST__
#include <errno.h>
#include <stdbool.h>
#include <stdlib.h>
@ -62,4 +63,10 @@ struct linked_list *linked_list_reverse(struct linked_list *list);
*/
void linked_list_reverse_mutate(struct linked_list *list);
/**
* @brief Frees the linked list.
* @since v3.0.0
*/
void linked_list_free(struct linked_list *list);
#endif

View File

@ -3,6 +3,7 @@
#define MATHEMATICS_FLOAT_PRECISION 0.00000001
#include <errno.h>
#include <stdbool.h>
#include "types.h"

View File

@ -3,6 +3,7 @@
struct queue *queue_initialization() {
struct queue *queue = malloc(sizeof(*queue));
if (queue == NULL) {
perror("Error (queue_initialization)");
exit(EXIT_FAILURE);
}
queue->first = NULL;
@ -11,8 +12,14 @@ struct queue *queue_initialization() {
}
void queue_push(struct queue *queue, void *data) {
if (queue == NULL) {
errno = EINVAL;
perror("Error (queue_push)");
exit(EXIT_FAILURE);
}
struct queue_node *node_new = malloc(sizeof(*node_new));
if (queue == NULL || node_new == NULL) {
if (node_new == NULL) {
perror("Error (queue_push)");
exit(EXIT_FAILURE);
}
node_new->data = data;
@ -31,6 +38,8 @@ void queue_push(struct queue *queue, void *data) {
void *queue_pop(struct queue *queue) {
if (queue == NULL) {
errno = EINVAL;
perror("Error (queue_pop)");
exit(EXIT_FAILURE);
}
struct queue_node *node = queue->first;
@ -43,3 +52,18 @@ void *queue_pop(struct queue *queue) {
queue->length = queue->length - 1;
return data;
}
void queue_free(struct queue *queue) {
if (queue == NULL) {
errno = EINVAL;
perror("Error (queue_free)");
exit(EXIT_FAILURE);
}
struct queue_node *node = queue->first;
while (node != NULL) {
struct queue_node *node_next = node->next;
free(node);
node = node_next;
}
free(queue);
}

View File

@ -1,6 +1,7 @@
#ifndef __LIBCPROJECT_QUEUE__
#define __LIBCPROJECT_QUEUE__
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
@ -42,4 +43,10 @@ void queue_push(struct queue *queue, void *data);
*/
void *queue_pop(struct queue *queue);
/**
* @brief Frees the queue.
* @since v3.0.0
*/
void queue_free(struct queue *queue);
#endif

View File

@ -3,6 +3,7 @@
struct stack *stack_initialization() {
struct stack *stack = malloc(sizeof(*stack));
if (stack == NULL) {
perror("Error (stack_initialization)");
exit(EXIT_FAILURE);
}
stack->first = NULL;
@ -11,8 +12,14 @@ struct stack *stack_initialization() {
}
void stack_push(struct stack *stack, void *data) {
if (stack == NULL) {
errno = EINVAL;
perror("Error (stack_push)");
exit(EXIT_FAILURE);
}
struct stack_node *node_new = malloc(sizeof(*node_new));
if (stack == NULL || data == NULL) {
if (data == NULL) {
perror("Error (stack_push)");
exit(EXIT_FAILURE);
}
node_new->data = data;
@ -23,6 +30,8 @@ void stack_push(struct stack *stack, void *data) {
void *stack_pop(struct stack *stack) {
if (stack == NULL) {
errno = EINVAL;
perror("Error (stack_pop)");
exit(EXIT_FAILURE);
}
struct stack_node *node = stack->first;
@ -35,3 +44,18 @@ void *stack_pop(struct stack *stack) {
stack->length = stack->length - 1;
return data;
}
void stack_free(struct stack *stack) {
if (stack == NULL) {
errno = EINVAL;
perror("Error (stack_free)");
exit(EXIT_FAILURE);
}
struct stack_node *node = stack->first;
while (node != NULL) {
struct stack_node *node_next = node->next;
free(node);
node = node_next;
}
free(stack);
}

View File

@ -1,6 +1,7 @@
#ifndef __LIBCPROJECT_STACK__
#define __LIBCPROJECT_STACK__
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
@ -42,4 +43,10 @@ void stack_push(struct stack *stack, void *data);
*/
void *stack_pop(struct stack *stack);
/**
* @brief Frees the stack.
* @since v3.0.0
*/
void stack_free(struct stack *stack);
#endif

View File

@ -1,118 +1,96 @@
#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;
while (string_value[length] != '\0') {
while (string[length] != '\0') {
length++;
}
return length;
}
string_t string_to_uppercase(string_t string_value) {
size_t string_length = string_get_length(string_value);
string_t result = malloc(sizeof(string_t) * string_length);
if (result == NULL) {
exit(EXIT_FAILURE);
}
void string_to_uppercase(string_t string) {
size_t string_length = string_get_length(string);
for (size_t index = 0; index < string_length; index++) {
character_append(result, character_to_upper(string_value[index]));
string[index] = character_to_upper(string[index]);
}
return result;
string[string_length] = '\0';
}
string_t string_to_lowercase(string_t string_value) {
size_t string_length = string_get_length(string_value);
string_t result = malloc(sizeof(string_t) * string_length);
if (result == NULL) {
exit(EXIT_FAILURE);
}
void string_to_lowercase(string_t string) {
size_t string_length = string_get_length(string);
for (size_t index = 0; index < string_length; index++) {
character_append(result, character_to_lower(string_value[index]));
string[index] = character_to_lower(string[index]);
}
return result;
string[string_length] = '\0';
}
string_t string_replace(string_t string_value, char search, char replace) {
size_t string_length = string_get_length(string_value);
string_t result = malloc(sizeof(string_t) * string_length);
if (result == NULL) {
exit(EXIT_FAILURE);
}
void string_replace(string_t string, char search, char replace) {
size_t string_length = string_get_length(string);
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) {
character_append(result, replace);
string[index] = replace;
} else {
character_append(result, string_value[index]);
string[index] = string[index];
}
}
return result;
string[string_length] = '\0';
}
string_t string_trim_start(string_t string_value) {
size_t string_length = string_get_length(string_value);
string_t result = malloc(sizeof(string_t) * string_length);
if (result == NULL) {
exit(EXIT_FAILURE);
}
void string_trim_start(string_t string, char character) {
size_t string_length = string_get_length(string);
size_t index_space = 0;
while (string_value[index_space] == ' ') {
while (string[index_space] == character) {
index_space++;
}
for (size_t index = index_space; index < string_length; index++) {
character_append(result, string_value[index]);
for (size_t index = 0; index < string_length - index_space; index++) {
string[index] = string[index + index_space];
}
return result;
string[string_length - index_space] = '\0';
}
string_t string_trim_end(string_t string_value) {
size_t string_length = string_get_length(string_value);
string_t result = malloc(sizeof(string_t) * string_length);
if (result == NULL) {
exit(EXIT_FAILURE);
}
void string_trim_end(string_t string, char character) {
size_t string_length = string_get_length(string);
size_t index_space = string_length - 1;
while (string_value[index_space] == ' ') {
while (string[index_space] == character) {
index_space--;
}
for (size_t index = 0; index < index_space + 1; index++) {
character_append(result, string_value[index]);
}
return result;
string[index_space + 1] = '\0';
}
string_t string_trim(string_t string_value) {
string_t result = string_trim_start(string_value);
result = string_trim_end(result);
return result;
void string_trim(string_t string, char character) {
string_trim_start(string, character);
string_trim_end(string, character);
}
string_t string_copy(const string_t string_value) {
return string_substring(string_value, 0, string_get_length(string_value));
}
string_t string_capitalize(string_t string_value) {
size_t string_length = string_get_length(string_value);
string_t result = malloc(sizeof(string_t) * string_length);
if (result == NULL) {
string_t string_copy(const string_t string) {
size_t source_length = string_get_length(string);
string_t copy = malloc(sizeof(char) * (source_length + 1));
if (copy == NULL) {
perror("Error (string_copy)");
exit(EXIT_FAILURE);
}
for (size_t index = 0; index < string_length; index++) {
bool is_first_character = index == 0;
if (is_first_character) {
character_append(result, character_to_upper(string_value[index]));
} else {
character_append(result, string_value[index]);
size_t index;
for (index = 0; index < source_length; index++) {
copy[index] = string[index];
}
}
return result;
copy[index] = '\0';
return copy;
}
size_t string_total_occurrences_of_character(string_t string_value, char character) {
void string_capitalize(string_t string) {
size_t string_length = string_get_length(string);
if (string_length == 0) {
return;
}
string[0] = character_to_upper(string[0]);
}
size_t string_total_occurrences_of_character(string_t string, char character) {
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++) {
char current_character = string_value[index];
char current_character = string[index];
if (current_character == character) {
result += 1;
}
@ -120,18 +98,17 @@ size_t string_total_occurrences_of_character(string_t string_value, char charact
return result;
}
string_t string_reverse(const string_t string_value) {
size_t string_length = string_get_length(string_value);
size_t index = 0;
string_t result = malloc(sizeof(string_t) * string_length);
if (result == NULL) {
exit(EXIT_FAILURE);
void string_reverse(const string_t string) {
size_t string_length = string_get_length(string);
size_t index_start = 0;
size_t index_end = string_length - 1;
while (index_start < index_end) {
char temporary = string[index_start];
string[index_start] = string[index_end];
string[index_end] = temporary;
index_start++;
index_end--;
}
for (index = string_length - 1; index > 0; index--) {
character_append(result, string_value[index]);
}
character_append(result, string_value[index]);
return result;
}
bool string_equals(const string_t string1, const string_t string2) {
@ -146,11 +123,11 @@ bool string_equals(const string_t string1, const string_t string2) {
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 string_length = string_get_length(string_value);
size_t string_length = string_get_length(string);
bool is_integer = string_length >= 1;
if (is_integer && string_value[0] == '-') {
if (is_integer && string[0] == '-') {
if (string_length == 1) {
is_integer = false;
} else {
@ -158,7 +135,7 @@ bool string_get_is_integer(const string_t string_value) {
}
}
while (index < string_length && is_integer) {
if (!character_get_is_digit(string_value[index])) {
if (!character_get_is_digit(string[index])) {
is_integer = false;
}
index++;
@ -166,32 +143,40 @@ bool string_get_is_integer(const string_t string_value) {
return is_integer;
}
string_t* string_split(const string_t string_value, char separator, size_t* result_size) {
size_t string_length = string_get_length(string_value);
string_t* string_split(const string_t string, char separator, size_t* result_size) {
size_t string_length = string_get_length(string);
size_t index_string = 0;
size_t index_current = 0;
size_t index_result = 0;
string_t current = malloc(sizeof(string_t) * string_length);
string_t* result = malloc(sizeof(string_t*) * index_result);
if (result == NULL || current == NULL) {
string_t current = malloc(sizeof(char) * (string_length + 1));
string_t* result = NULL;
if (current == NULL) {
perror("Error (string_split)");
exit(EXIT_FAILURE);
}
while (index_string < string_length) {
if (string_value[index_string] == separator) {
result[index_result] = string_copy(current);
index_result++;
result = realloc(result, sizeof(string_value) * index_result);
if (string[index_string] == separator) {
current[index_current] = '\0';
result = realloc(result, sizeof(string_t) * (index_result + 1));
if (result == NULL) {
perror("Error (string_split)");
exit(EXIT_FAILURE);
}
result[index_result] = string_copy(current);
index_result++;
index_current = 0;
current = string_copy("");
} else {
character_append(current, string_value[index_string]);
current[index_current] = string[index_string];
index_current++;
}
index_string++;
}
current[index_current] = '\0';
result = realloc(result, sizeof(string_t) * (index_result + 1));
if (result == NULL) {
perror("Error (string_split)");
exit(EXIT_FAILURE);
}
result[index_result] = string_copy(current);
free(current);
*result_size = index_result + 1;
@ -199,80 +184,96 @@ string_t* string_split(const string_t string_value, char separator, size_t* resu
}
string_t string_join(string_t* array, const char separator, size_t array_length) {
size_t string_length = array_length;
string_t string_value = malloc(sizeof(string_value) * string_length);
if (string_value == NULL) {
size_t total_length = 0;
for (size_t index_array = 0; index_array < array_length; index_array++) {
total_length += string_get_length(array[index_array]);
}
size_t string_length = total_length + (array_length - 1);
string_t string = malloc(sizeof(char) * (string_length + 1));
if (string == NULL) {
perror("Error (string_join)");
exit(EXIT_FAILURE);
}
size_t current_index = 0;
for (size_t index_array = 0; index_array < array_length; index_array++) {
string_t substring = array[index_array];
size_t substring_length = string_get_length(substring);
string_length += substring_length;
string_value = realloc(string_value, sizeof(string_value) * string_length);
if (string_value == NULL) {
exit(EXIT_FAILURE);
}
for (size_t index_substring = 0; index_substring < substring_length; index_substring++) {
character_append(string_value, substring[index_substring]);
string[current_index] = substring[index_substring];
current_index++;
}
bool is_last_character = index_array == (array_length - 1);
if (!is_last_character) {
character_append(string_value, separator);
string[current_index] = separator;
current_index++;
}
}
return string_value;
string[string_length] = '\0';
return string;
}
string_t string_concatenate(string_t string1, string_t string2) {
size_t string1_length = string_get_length(string1);
size_t string2_length = string_get_length(string2);
size_t result_length = string1_length + string2_length;
string_t result = malloc(sizeof(string_t) * result_length);
if (result == NULL) {
void string_concatenate(string_t* destination, string_t source) {
size_t destination_length = string_get_length(*destination);
size_t source_length = string_get_length(source);
size_t new_length = destination_length + source_length;
*destination = realloc(*destination, sizeof(char) * (new_length + 1));
if (*destination == NULL) {
perror("Error (string_concatenate)");
exit(EXIT_FAILURE);
}
for (size_t index_string1 = 0; index_string1 < string1_length; index_string1++) {
character_append(result, string1[index_string1]);
size_t index_destination = destination_length;
for (size_t index_source = 0; index_source < source_length; index_source++) {
(*destination)[index_destination++] = source[index_source];
}
for (size_t index_string2 = 0; index_string2 < string2_length; index_string2++) {
character_append(result, string2[index_string2]);
}
return result;
(*destination)[index_destination] = '\0';
}
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;
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();
string_t* keys = malloc(sizeof(string_t) * string_length);
for (size_t index = 0; index < string_length; index++) {
keys[index] = NULL;
}
for (size_t index = 0; index < string_length && has_unique; index++) {
char character = string_value[index];
string_t key = convert_character_to_string(character);
char character = string[index];
keys[index] = convert_character_to_string(character);
string_t key = keys[index];
if (hash_map_contains_key(characters_already_seen, key)) {
has_unique = false;
} else {
hash_map_add(characters_already_seen, key, (void*)true);
}
}
for (size_t index = 0; index < string_length; index++) {
if (keys[index] != NULL) {
free(keys[index]);
}
}
free(keys);
hash_map_free(characters_already_seen);
return has_unique;
}
string_t string_substring(const string_t string_value, size_t index_start, size_t index_end) {
size_t string_length = string_get_length(string_value);
string_t result = malloc(sizeof(string_t) * string_length);
for (size_t index = index_start; index <= index_end; index++) {
character_append(result, string_value[index]);
string_t string_substring(const string_t string, size_t index_start, size_t index_end) {
size_t substring_length = index_end - index_start + 1;
string_t result = malloc(sizeof(char) * (substring_length + 1));
for (size_t index = 0; index < substring_length; index++) {
result[index] = string[index_start + index];
}
result[substring_length] = '\0';
return result;
}
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;
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);
for (size_t index_string = 0; index_string < string_length && !is_substring; index_string++) {
size_t index_substring = 0;
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_considered++;
}
@ -282,72 +283,88 @@ bool string_get_is_substring(const string_t string_value, const string_t substri
}
string_t string_get_formatted_number(const long long number, string_t separator) {
string_t number_string = convert_number_to_string(number);
bool is_negative = number_string[0] == '-';
string_t number_string_temp = convert_number_to_string(number);
string_t number_string = number_string_temp;
bool is_negative = number_string_temp[0] == '-';
if (is_negative) {
number_string = string_substring(number_string, 1, string_get_length(number_string));
number_string = string_substring(number_string_temp, 1, string_get_length(number_string_temp));
free(number_string_temp);
}
size_t number_string_length = string_get_length(number_string);
string_t result = malloc(sizeof(string_t) * number_string_length);
size_t formatted_length = number_string_length + (number_string_length - 1) / 3;
string_t result = malloc(sizeof(char) * (formatted_length + 1));
if (result == NULL) {
perror("Error (string_get_formatted_number)");
exit(EXIT_FAILURE);
}
size_t count = 0;
size_t result_index = 0;
for (size_t index = 0; index < number_string_length; index++) {
size_t index_reversed = number_string_length - index - 1;
result[result_index] = number_string[index_reversed];
count++;
result = string_concatenate(result, convert_character_to_string(number_string[index_reversed]));
if (count == 3) {
result = string_concatenate(result, separator);
result_index++;
if (count == 3 && index != number_string_length - 1) {
for (size_t sep_index = 0; sep_index < string_get_length(separator); sep_index++) {
result[result_index] = separator[sep_index];
result_index++;
}
count = 0;
}
}
result = string_reverse(result);
size_t result_length = string_get_length(result);
if (result_length % 4 == 0) {
result = string_substring(result, 1, result_length);
}
free(number_string);
result[formatted_length] = '\0';
string_reverse(result);
if (is_negative) {
result = string_concatenate(convert_character_to_string('-'), result);
string_t negative_result = convert_character_to_string('-');
string_concatenate(&negative_result, result);
free(result);
return negative_result;
}
return result;
}
string_t string_get_last_occurence_of_character(const string_t string_value, char character) {
size_t string_length = string_get_length(string_value);
string_t result = malloc(sizeof(string_t) * string_length);
string_t string_get_last_occurence_of_character(const string_t string, char character) {
size_t string_length = string_get_length(string);
size_t index_last_occurrence = SIZE_MAX;
for (size_t index = 0; index < string_length; index++) {
if (string[index] == character) {
index_last_occurrence = index;
}
}
if (index_last_occurrence == SIZE_MAX) {
return "";
}
string_t result = malloc(sizeof(char) * (string_length - index_last_occurrence + 1));
if (result == NULL) {
perror("Error (string_get_last_occurence_of_character)");
exit(EXIT_FAILURE);
}
size_t index_result = 0;
for (size_t index = 0; index < string_length; index++) {
if (string_value[index] == character) {
index_result = 0;
result = string_copy("");
}
character_append(result, string_value[index]);
index_result++;
for (size_t index = index_last_occurrence; index < string_length; index++) {
result[index_result++] = string[index];
}
result[index_result] = '\0';
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;
size_t prefix_length = string_get_length(prefix);
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;
}
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;
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 index_string = string_length - 1;
size_t index_prefix = prefix_length - 1;
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_prefix--;
}

View File

@ -1,6 +1,7 @@
#ifndef __LIBCPROJECT_STRING__
#define __LIBCPROJECT_STRING__
#include <errno.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
@ -13,93 +14,109 @@
/**
* @brief Return the length of a string (excluding '\0').
*
* @param string_value
* @param string
* @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.
*
* @param string_value
* NOTE: Mutates the string.
*
* @param string
* @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.
*
* @param string_value
* NOTE: Mutates the string.
*
* @param string
* @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.
*
* @param string_value
* NOTE: Mutates the string.
*
* @param string
* @param search A character search value.
* @param replace A character containing the text to replace for match.
* @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 whitespace 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
*/
string_t string_trim_start(string_t string_value);
void string_trim_start(string_t string, char character);
/**
* @brief Removes all whitespace 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
*/
string_t string_trim_end(string_t string_value);
void string_trim_end(string_t string, char character);
/**
* @brief Removes all whitespace from the start and end of a string.
* @brief Removes all `character` from the start and end of a string.
*
* @param string_value
* NOTE: Mutates the string.
*
* @param string
* @since v1.0.0
*/
string_t string_trim(string_t string_value);
void string_trim(string_t string, char character);
/**
* @brief Return the copy of a string.
*
* @param string_value
* @param string
* @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.
*
* @param string_value
* NOTE: Mutates the string.
*
* @param string
* @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.
*
* @param string_value
* @param string
* @param character
* @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
*/
string_t string_reverse(const string_t string_value);
void string_reverse(const string_t string);
/**
* @brief Check if two strings are equals.
@ -114,21 +131,21 @@ bool string_equals(const string_t string1, const string_t string2);
/**
* @brief Check if the string is a integer.
*
* @param string_value
* @param string
* @return true if the string is a integer, false otherwise.
* @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.
*
* @param string_value
* @param string
* @param separator
* @param result_size
* @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.
@ -143,11 +160,13 @@ string_t string_join(string_t* array, const char separator, size_t array_length)
/**
* @brief Concatenate two strings.
*
* @param string1
* @param string2
* NOTE: Mutates the string `destination`.
*
* @param destination
* @param source
* @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.
@ -161,22 +180,22 @@ 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).
*
* @param string_value
* @param string
* @param index_start
* @param index_end
* @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.
*
* @param string_value
* @param string
* @param substring
* @return true if the string contains the substring, false otherwise.
* @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.
@ -194,30 +213,30 @@ string_t string_get_formatted_number(const long long number, string_t separator)
/**
* @brief Returns a pointer to the last occurrence of character in the string.
*
* @param string_value
* @param string
* @param character
* @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.
*
* @param string_value
* @param string
* @param prefix
* @return true if the string starts with the substring, false otherwise.
* @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.
*
* @param string_value
* @param string
* @param prefix
* @return true if the string ends with the substring, false otherwise.
* @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);
#endif

View File

@ -3,20 +3,22 @@
string_t terminal_input() {
char character;
size_t length = 1;
string_t string_value = malloc(length * sizeof(char));
if (string_value == NULL) {
string_t string = malloc(length * sizeof(char));
if (string == NULL) {
perror("Error (terminal_input)");
exit(EXIT_FAILURE);
}
*string_value = '\0';
*string = '\0';
while ((character = getchar()) != '\n' && character != EOF) {
length++;
string_value = realloc(string_value, length * sizeof(char));
if (string_value == NULL) {
string = realloc(string, length * sizeof(char));
if (string == NULL) {
perror("Error (terminal_input)");
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*)) {
@ -54,6 +56,8 @@ void terminal_print_string(void* value) {
void terminal_print_stack(struct stack* stack, void (*print_element)(void*)) {
if (stack == NULL) {
errno = EINVAL;
perror("Error (terminal_print_stack)");
exit(EXIT_FAILURE);
}
struct stack_node* node_current = stack->first;
@ -68,6 +72,8 @@ void terminal_print_stack(struct stack* stack, void (*print_element)(void*)) {
void terminal_print_queue(struct queue* queue, void (*print_element)(void*)) {
if (queue == NULL) {
errno = EINVAL;
perror("Error (terminal_print_queue)");
exit(EXIT_FAILURE);
}
struct queue_node* node_current = queue->first;
@ -82,6 +88,8 @@ 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*)) {
if (linked_list == NULL) {
errno = EINVAL;
perror("Error (terminal_print_linked_list)");
exit(EXIT_FAILURE);
}
struct linked_list_node* node_current = linked_list->head;
@ -96,6 +104,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*)) {
if (hash_map == NULL) {
errno = EINVAL;
perror("Error (terminal_print_hash_map)");
exit(EXIT_FAILURE);
}
printf("{\n");
@ -111,3 +121,7 @@ void terminal_print_hash_map(struct hash_map* hash_map, void (*print_element)(vo
}
printf("}\n");
}
void terminal_print_array_list(struct array_list* list, void (*print_element)(void*)) {
terminal_print_array(list->data, list->size, sizeof(void*), print_element);
}

View File

@ -1,11 +1,13 @@
#ifndef __LIBCPROJECT_TERMINAL__
#define __LIBCPROJECT_TERMINAL__
#include <errno.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "array_list.h"
#include "character.h"
#include "hash_map.h"
#include "linked_list.h"
@ -106,4 +108,13 @@ 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*));
/**
* @brief Print an array list.
*
* @param array_list
* @param print_element
* @since v3.0.0
*/
void terminal_print_array_list(struct array_list* list, void (*print_element)(void*));
#endif

6
main.c
View File

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

View File

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

View File

@ -32,4 +32,6 @@ void array_list_test() {
array_list_remove(list, 100);
assert(list->size == 105);
assert(array_list_get(list, 100) == (void *)95);
array_list_free(list);
}

View File

@ -20,7 +20,7 @@ void character_append_at_test() {
character_append_at(string, 'd', 1);
assert(assert_string_equal(string, "adbc"));
char string2[5] = "abcd";
char string2[6] = "abcd";
character_append_at(string2, 'e', 4);
assert(assert_string_equal(string2, "abcde"));
}

View File

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

View File

@ -24,4 +24,5 @@ void hash_map_test() {
hash_map_remove(hash_map, "key5");
assert(hash_map->length == 5);
assert(!hash_map_contains_key(hash_map, "key5"));
hash_map_free(hash_map);
}

View File

@ -13,6 +13,7 @@ void linked_list_initialization_test() {
struct linked_list *list = linked_list_initialization();
assert(list->length == 0);
assert(list->head == NULL);
linked_list_free(list);
}
void linked_list_add_in_head_test() {
@ -25,6 +26,7 @@ void linked_list_add_in_head_test() {
assert(((uintptr_t)list->head->next->data) == 8);
assert(((uintptr_t)list->head->next->next->data) == 4);
assert(list->head->next->next->next == NULL);
linked_list_free(list);
}
void linked_list_delete_in_head_test() {
@ -37,6 +39,7 @@ void linked_list_delete_in_head_test() {
assert(((uintptr_t)list->head->data) == 8);
assert(((uintptr_t)list->head->next->data) == 4);
assert(list->head->next->next == NULL);
linked_list_free(list);
}
void linked_list_add_after_last_test() {
@ -54,6 +57,7 @@ void linked_list_add_after_last_test() {
assert(((uintptr_t)list->head->next->data) == 8);
assert(((uintptr_t)list->head->next->next->data) == 4);
assert(((uintptr_t)list->head->next->next->next->data) == 18);
linked_list_free(list);
}
void linked_list_reverse_test() {
@ -74,6 +78,8 @@ void linked_list_reverse_test() {
assert((list_reversed->head->next->data) == (void *)'C');
assert((list_reversed->head->next->next->data) == (void *)'B');
assert((list_reversed->head->next->next->next->data) == (void *)'A');
linked_list_free(list);
linked_list_free(list_reversed);
}
void linked_list_reverse_mutate_test() {
@ -89,4 +95,5 @@ void linked_list_reverse_mutate_test() {
assert((list->head->next->data) == (void *)'C');
assert((list->head->next->next->data) == (void *)'B');
assert((list->head->next->next->next->data) == (void *)'A');
linked_list_free(list);
}

View File

@ -10,6 +10,7 @@ void queue_initialization_test() {
struct queue *queue = queue_initialization();
assert(queue->length == 0);
assert(queue->first == NULL);
queue_free(queue);
}
void queue_push_test() {
@ -22,6 +23,7 @@ void queue_push_test() {
assert(((uintptr_t)queue->first->next->data) == 8);
assert(((uintptr_t)queue->first->next->next->data) == 15);
assert(queue->first->next->next->next == NULL);
queue_free(queue);
}
void queue_pop_test() {
@ -35,4 +37,5 @@ void queue_pop_test() {
assert(((uintptr_t)queue->first->data) == 8);
assert(((uintptr_t)queue->first->next->data) == 15);
assert(queue->first->next->next == NULL);
queue_free(queue);
}

View File

@ -10,6 +10,7 @@ void stack_initialization_test() {
struct stack *stack = stack_initialization();
assert(stack->length == 0);
assert(stack->first == NULL);
stack_free(stack);
}
void stack_push_test() {
@ -22,6 +23,7 @@ void stack_push_test() {
assert(((uintptr_t)stack->first->next->data) == 8);
assert(((uintptr_t)stack->first->next->next->data) == 4);
assert(stack->first->next->next->next == NULL);
stack_free(stack);
}
void stack_pop_test() {
@ -35,4 +37,5 @@ void stack_pop_test() {
assert(((uintptr_t)stack->first->data) == 8);
assert(((uintptr_t)stack->first->next->data) == 4);
assert(stack->first->next->next == NULL);
stack_free(stack);
}

View File

@ -30,42 +30,49 @@ void string_get_length_test() {
string_t string = "Hello World!";
size_t string_length = string_get_length(string);
assert(string_length == 12);
assert(strlen(string) == string_length);
}
void string_to_uppercase_test() {
string_t string = "heLlO world";
string = string_to_uppercase(string);
string_t string = string_copy("heLlO world");
string_to_uppercase(string);
assert(assert_string_equal(string, "HELLO WORLD"));
free(string);
}
void string_to_lowercase_test() {
string_t string = "HellO WoRLd";
string = string_to_lowercase(string);
string_t string = string_copy("HellO WoRLd");
string_to_lowercase(string);
assert(assert_string_equal(string, "hello world"));
free(string);
}
void string_replace_test() {
string_t string = "hello world";
string = string_replace(string, 'l', 'z');
string_t string = string_copy("hello world");
string_replace(string, 'l', 'z');
assert(assert_string_equal(string, "hezzo worzd"));
free(string);
}
void string_trim_start_test() {
string_t string = " hello world ";
string = string_trim_start(string);
string_t string = string_copy(" hello world ");
string_trim_start(string, ' ');
assert(assert_string_equal(string, "hello world "));
free(string);
}
void string_trim_end_test() {
string_t string = " hello world ";
string = string_trim_end(string);
string_t string = string_copy(" hello world ");
string_trim_end(string, ' ');
assert(assert_string_equal(string, " hello world"));
free(string);
}
void string_trim_test() {
string_t string = " hello world ";
string = string_trim(string);
string_t string = string_copy(" hello world ");
string_trim(string, ' ');
assert(assert_string_equal(string, "hello world"));
free(string);
}
void string_copy_test() {
@ -76,12 +83,14 @@ void string_copy_test() {
assert(assert_string_not_equal(string, string2));
assert(assert_string_equal(string, "hello world"));
assert(assert_string_equal(string2, "aello world"));
free(string2);
}
void string_capitalize_test() {
string_t string = "hello world";
string = string_capitalize(string);
string_t string = string_copy("hello world");
string_capitalize(string);
assert(assert_string_equal(string, "Hello world"));
free(string);
}
void string_total_occurrences_of_character_test() {
@ -90,9 +99,10 @@ void string_total_occurrences_of_character_test() {
}
void string_reverse_test() {
string_t string = "hello world";
string = string_reverse(string);
string_t string = string_copy("hello world");
string_reverse(string);
assert(assert_string_equal(string, "dlrow olleh"));
free(string);
}
void string_equals_test() {
@ -125,6 +135,10 @@ void string_split_test() {
assert(assert_string_equal(result[1], "def"));
assert(assert_string_equal(result[2], "ghij"));
assert(assert_string_equal(result[3], "kl"));
for (size_t index = 0; index < result_length; index++) {
free(result[index]);
}
free(result);
}
void string_join_test() {
@ -135,11 +149,24 @@ void string_join_test() {
string_t new_string2 = string_join(result, '+', result_length);
assert(assert_string_equal(new_string, string));
assert(assert_string_equal(new_string2, "abc+def+ghij+kl"));
free(new_string);
free(new_string2);
for (size_t index = 0; index < result_length; index++) {
free(result[index]);
}
free(result);
}
void string_concatenate_test() {
assert(assert_string_equal(string_concatenate("abc", "def"), "abcdef"));
assert(assert_string_equal(string_concatenate("abc ", " defghi"), "abc defghi"));
string_t result = string_copy("abc");
string_concatenate(&result, "def");
assert(assert_string_equal(result, "abcdef"));
free(result);
result = string_copy("abcz");
string_concatenate(&result, " defghi");
assert(assert_string_equal(result, "abcz defghi"));
free(result);
}
void string_get_has_unique_characters_test() {
@ -152,6 +179,7 @@ void string_substring_test() {
string_t string = "abcdef";
string_t substring = string_substring(string, 1, 3);
assert(assert_string_equal(substring, "bcd"));
free(substring);
}
void string_get_is_substring_test() {
@ -167,33 +195,61 @@ void string_get_is_substring_test() {
}
void string_get_formatted_number_test() {
assert(assert_string_equal(string_get_formatted_number(1000, " "), "1 000"));
assert(assert_string_equal(string_get_formatted_number(123, ","), "123"));
assert(assert_string_equal(string_get_formatted_number(1234, ","), "1,234"));
assert(assert_string_equal(string_get_formatted_number(12345, ","), "12,345"));
assert(assert_string_equal(string_get_formatted_number(123456, ","), "123,456"));
assert(assert_string_equal(string_get_formatted_number(1234567, ","), "1,234,567"));
assert(assert_string_equal(string_get_formatted_number(12345678, ","), "12,345,678"));
assert(assert_string_equal(string_get_formatted_number(123456789, ","), "123,456,789"));
assert(assert_string_equal(string_get_formatted_number(1234567890, ","), "1,234,567,890"));
assert(assert_string_equal(string_get_formatted_number(-123, ","), "-123"));
assert(assert_string_equal(string_get_formatted_number(-1234, ","), "-1,234"));
assert(assert_string_equal(string_get_formatted_number(-12345, ","), "-12,345"));
assert(assert_string_equal(string_get_formatted_number(-123456, ","), "-123,456"));
assert(assert_string_equal(string_get_formatted_number(-1234567, ","), "-1,234,567"));
assert(assert_string_equal(string_get_formatted_number(-12345678, ","), "-12,345,678"));
assert(assert_string_equal(string_get_formatted_number(-123456789, ","), "-123,456,789"));
assert(assert_string_equal(string_get_formatted_number(-1234567890, ","), "-1,234,567,890"));
char* result = string_get_formatted_number(1000, " ");
assert(assert_string_equal(result, "1 000"));
free(result);
result = string_get_formatted_number(123, ",");
assert(assert_string_equal(result, "123"));
free(result);
result = string_get_formatted_number(1234, ",");
assert(assert_string_equal(result, "1,234"));
free(result);
result = string_get_formatted_number(12345, ",");
assert(assert_string_equal(result, "12,345"));
free(result);
result = string_get_formatted_number(-123, ",");
assert(assert_string_equal(result, "-123"));
free(result);
result = string_get_formatted_number(-1234, ",");
assert(assert_string_equal(result, "-1,234"));
free(result);
result = string_get_formatted_number(-1234567890, ",");
assert(assert_string_equal(result, "-1,234,567,890"));
free(result);
}
void string_get_last_occurence_of_character_test() {
string_t string = "abcdef";
assert(assert_string_equal(string_get_last_occurence_of_character(string, 'a'), "abcdef"));
assert(assert_string_equal(string_get_last_occurence_of_character(string, 'b'), "bcdef"));
assert(assert_string_equal(string_get_last_occurence_of_character(string, 'c'), "cdef"));
assert(assert_string_equal(string_get_last_occurence_of_character(string, 'd'), "def"));
assert(assert_string_equal(string_get_last_occurence_of_character(string, 'e'), "ef"));
assert(assert_string_equal(string_get_last_occurence_of_character(string, 'f'), "f"));
char* result = string_get_last_occurence_of_character(string, 'a');
assert(assert_string_equal(result, "abcdef"));
free(result);
result = string_get_last_occurence_of_character(string, 'b');
assert(assert_string_equal(result, "bcdef"));
free(result);
result = string_get_last_occurence_of_character(string, 'c');
assert(assert_string_equal(result, "cdef"));
free(result);
result = string_get_last_occurence_of_character(string, 'd');
assert(assert_string_equal(result, "def"));
free(result);
result = string_get_last_occurence_of_character(string, 'e');
assert(assert_string_equal(result, "ef"));
free(result);
result = string_get_last_occurence_of_character(string, 'f');
assert(assert_string_equal(result, "f"));
free(result);
}
void string_starts_with_test() {

View File

@ -1,4 +1,4 @@
#ifndef __LIBCPROJECT_VERSION__
#define __LIBCPROJECT_VERSION__ "2.0.0"
#define __LIBCPROJECT_VERSION__ "4.0.0"
#endif