commit 0fa82c5772bbecc2d6a7c42c8e51f3eb197a0a59 Author: Divlo Date: Thu Jan 5 19:28:05 2023 +0100 chore: initial commit diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..af980a0 --- /dev/null +++ b/.clang-format @@ -0,0 +1,2 @@ +BasedOnStyle: 'Google' +ColumnLimit: 0 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0b40fca --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +build +bin +.vscode +*.out +*.o +*.exe +*.a diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..04e85c3 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) Divlo + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..ed2eb4c --- /dev/null +++ b/Makefile @@ -0,0 +1,37 @@ +LIBRARY_NAME = libcproject +CC = gcc +CC_FLAGS = -Wall -Wextra -Wfloat-equal -Wundef -Werror -std=c17 -pedantic -pedantic-errors -I./ +LIB_CC_FLAGS = -L. -l:./build/${LIBRARY_NAME}.a +LIB_SOURCES = $(wildcard lib/*.c) +TEST_SOURCES = $(wildcard test/*.c) +HEADER_FILES = $(wildcard lib/*.h) $(wildcard test/*.h) ./${LIBRARY_NAME}.h +MAIN_EXECUTABLE = bin/main.exe +TEST_EXECUTABLE = bin/test.exe + +.PHONY: all +all: ${LIB_SOURCES} + mkdir --parents ./build + ${CC} ${CC_FLAGS} -c ${LIB_SOURCES} + rm --force ./build/${LIBRARY_NAME}.a + ar -rcs ./build/${LIBRARY_NAME}.a *.o + rm --recursive --force *.o + +.PHONY: run +run: all ./main.c + mkdir --parents ./bin + ${CC} ${CC_FLAGS} -o ${MAIN_EXECUTABLE} ./main.c ${LIB_CC_FLAGS} + ./${MAIN_EXECUTABLE} ${ARGS} + +.PHONY: test +test: all ${TEST_SOURCES} + mkdir --parents ./bin + ${CC} ${CC_FLAGS} -o ${TEST_EXECUTABLE} ${TEST_SOURCES} ${LIB_CC_FLAGS} + ./${TEST_EXECUTABLE} + +.PHONY: lint +lint: + clang-format --Werror --dry-run ${LIB_SOURCES} ${TEST_SOURCES} ${HEADER_FILES} ./main.c + +.PHONY: clean +clean: + rm --recursive --force ./build ./bin *.out *.o *.exe *.a diff --git a/README.md b/README.md new file mode 100644 index 0000000..74b4a85 --- /dev/null +++ b/README.md @@ -0,0 +1,83 @@ +# libcproject + +## About + +`libcproject` is a C static library for learning purposes. It tries to implement useful functions/data structures while being easier to use than `libc` (C standard library) as much as possible. + +## Prerequisites + +- [GNU coreutils](https://www.gnu.org/software/coreutils/) +- [GNU binutils](https://www.gnu.org/software/binutils/) +- [GNU gcc](https://gcc.gnu.org/) +- [GNU make](https://www.gnu.org/software/make/) +- [clang-format](https://clang.llvm.org/docs/ClangFormat.html) + +For example on GNU/Linux Ubuntu: + +```sh +sudo apt-get install build-essential gcc make clang-format +``` + +## Usage + +Steps to create a new C project that uses `libcproject`: + +### Step 1: Compile `libcproject` + +```sh +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 ./ # copy +# or +ln -s ./ # symbolic link +``` + +### Step 4: Create a new C file + +```sh +touch main.c +``` + +```cpp +#include +#include + +#include "libcproject/libcproject.h" + +int main() { + char* string = "Hello, world!"; + 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 + +```sh +gcc -o ./main.exe ./main.c -L. -l:./libcproject/build/libcproject.a +``` + +## Contributing + +```sh +make # to compile +make run # to run main +make test # to run unit tests +make lint # to lint the code +make clean # to clean up + +nm ./build/libcproject.a # to see the symbols +``` diff --git a/lib/character.c b/lib/character.c new file mode 100644 index 0000000..cca0bed --- /dev/null +++ b/lib/character.c @@ -0,0 +1,47 @@ +#include "character.h" + +#include +#include + +#include "string.h" + +void character_append(char* string, const char character) { + size_t length = string_get_length(string); + character_append_at(string, character, length); +} + +void character_append_at(char* string, const char character, const size_t index) { + size_t length = string_get_length(string); + for (size_t index_string = length; index_string > index; index_string--) { + string[index_string] = string[index_string - 1]; + } + string[index] = character; + string[length + 1] = '\0'; +} + +char character_to_upper(const char character) { + if (character >= 'a' && character <= 'z') { + return character + ('A' - 'a'); + } + return character; +} + +char character_to_lower(const char character) { + if (character >= 'A' && character <= 'Z') { + return character - ('A' - 'a'); + } + return character; +} + +bool character_get_is_digit(const char character) { + return character >= '0' && character <= '9'; +} + +unsigned char character_get_alphabet_position(const char character) { + const char letter = character_to_lower(character); + unsigned char position = 0; + if (letter >= 'a' && letter <= 'z') { + position = (letter - 'a') + 1; + } + return position; +} diff --git a/lib/character.h b/lib/character.h new file mode 100644 index 0000000..47caa65 --- /dev/null +++ b/lib/character.h @@ -0,0 +1,59 @@ +#ifndef __CHARACTER__ +#define __CHARACTER__ + +#include +#include + +/** + * @brief Append a character to a string, assuming string points to an array + * with enough space. + * + * @param string + * @param character + */ +void character_append(char* string, char character); + +/** + * @brief Append a character to a string at a specific index, assuming string points to an array with enough space. + * + * @param string + * @param character + * @param index + */ +void character_append_at(char* string, const char character, const size_t index); + +/** + * @brief Converts the character to uppercase. + * + * @param character + * @return const char + */ +char character_to_upper(const char character); + +/** + * @brief Converts the character to lowercase. + * + * @param character + * @return const char + */ +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'). + * + * @param string1 + * @param string2 + * @return true if the character is a digit, false otherwise + */ +bool character_get_is_digit(const char character); + +/** + * @brief Get the position in latin alphabet of the letter (case-insensitive) from 1 to 26. + * Return 0 if the character is not a letter. + * + * @param character + * @return char + */ +unsigned char character_get_alphabet_position(const char character); + +#endif diff --git a/lib/convert.c b/lib/convert.c new file mode 100644 index 0000000..2de1233 --- /dev/null +++ b/lib/convert.c @@ -0,0 +1,109 @@ +#include "convert.h" + +#include +#include + +#include "character.h" +#include "mathematics.h" +#include "stdbool.h" +#include "string.h" + +char* convert_character_to_string(const char character) { + char* string = malloc(sizeof(char*) * 2); + if (string == NULL) { + exit(EXIT_FAILURE); + } + character_append(string, character); + return string; +} + +char convert_character_to_digit(const char character) { + return character - '0'; +} + +char convert_digit_to_character(const char digit) { + return digit + '0'; +} + +long long convert_string_to_number(const char* string) { + bool is_negative = string[0] == '-'; + long long integer = 0; + 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[index]); + } + return is_negative ? integer * -1 : integer; +} + +char* convert_number_to_string(const long long integer) { + if (integer == 0) { + return convert_character_to_string('0'); + } + bool is_negative = integer < 0; + size_t length = 1; + char* string = malloc(sizeof(char*) * length); + if (string == NULL) { + exit(EXIT_FAILURE); + } + long long current = mathematics_absolute_value(integer); + while (current != 0) { + character_append(string, convert_digit_to_character(current % 10)); + current = current / 10; + length++; + string = realloc(string, sizeof(char*) * length); + } + if (is_negative) { + character_append(string, '-'); + length++; + string = realloc(string, sizeof(char*) * length); + } + return string_reverse(string); +} + +char* convert_number_from_base_10_to_base(unsigned long long number, unsigned int base) { + if (number == 0) { + return "0"; + } + int remainders[64]; + int index = 0; + while (number > 0) { + remainders[index] = number % base; + number = number / base; + index++; + } + char* result = malloc(sizeof(char) * (index + 1)); + int index_result = 0; + for (int iteration = index - 1; iteration >= 0; iteration--) { + int remainder = remainders[iteration]; + if (remainder >= 10) { + result[index_result] = (char)((remainder - 10) + 'A'); + } else { + result[index_result] = (char)(remainder + '0'); + } + index_result++; + } + return result; +} + +int convert_number_from_base_to_base_10(char* number, unsigned int base) { + int length = string_get_length(number); + int exponent = length - 1; + int result = 0; + int index = 0; + while (exponent >= 0) { + int current_number = (int)(number[index] - '0'); + if (current_number >= 10) { + current_number = (int)(number[index] - 'A') + 10; + } else { + current_number = (int)(number[index] - '0'); + } + result = result + current_number * mathematics_pow(base, exponent); + exponent--; + index++; + } + return result; +} + +char* convert_number_from_base_to_another(char* number, int base_from, int base_target) { + return convert_number_from_base_10_to_base(convert_number_from_base_to_base_10(number, base_from), base_target); +} diff --git a/lib/convert.h b/lib/convert.h new file mode 100644 index 0000000..f218dbb --- /dev/null +++ b/lib/convert.h @@ -0,0 +1,20 @@ +#ifndef __CONVERT__ +#define __CONVERT__ + +char* convert_character_to_string(const char character); + +char convert_character_to_digit(const char character); + +char convert_digit_to_character(const char digit); + +long long convert_string_to_number(const char* string); + +char* convert_number_to_string(const long long integer); + +char* convert_number_from_base_10_to_base(unsigned long long number, unsigned int base); + +int convert_number_from_base_to_base_10(char* number, unsigned int base); + +char* convert_number_from_base_to_another(char* number, int base_from, int base_target); + +#endif diff --git a/lib/dictionary.c b/lib/dictionary.c new file mode 100644 index 0000000..7c9cb20 --- /dev/null +++ b/lib/dictionary.c @@ -0,0 +1,68 @@ +#include "dictionary.h" + +#include + +#include "string.h" + +struct dictionary *dictionary_initialization() { + struct dictionary *dictionary = malloc(sizeof(struct dictionary)); + dictionary->items = malloc(sizeof(struct dictionary_item *) * DICTIONARY_INITIAL_CAPACITY); + dictionary->length = 0; + dictionary->capacity = DICTIONARY_INITIAL_CAPACITY; + for (size_t index = 0; index < dictionary->capacity; index++) { + dictionary->items[index] = NULL; + } + return dictionary; +} + +void dictionary_add(struct dictionary *dictionary, char *key, void *data) { + if (dictionary->length == dictionary->capacity) { + size_t previous_capacity = dictionary->capacity; + dictionary->capacity += DICTIONARY_INITIAL_CAPACITY; + dictionary->items = realloc(dictionary->items, sizeof(struct dictionary_item *) * dictionary->capacity); + for (size_t index = previous_capacity; index < dictionary->capacity; index++) { + dictionary->items[index] = NULL; + } + } + struct dictionary_item *item = NULL; + for (size_t index = 0; index < dictionary->length && item == NULL; index++) { + if (string_get_is_equal(key, dictionary->items[index]->key)) { + item = dictionary->items[index]; + } + } + if (item == NULL) { + item = malloc(sizeof(struct dictionary_item)); + item->key = key; + item->data = data; + dictionary->items[dictionary->length] = item; + dictionary->length++; + } else { + item->data = data; + } +} + +void dictionary_remove(struct dictionary *dictionary, char *key) { + bool found = false; + for (size_t index = 0; index < dictionary->length && !found; index++) { + if (string_get_is_equal(key, dictionary->items[index]->key)) { + free(dictionary->items[index]); + dictionary->items[index] = dictionary->items[dictionary->length - 1]; + dictionary->length--; + found = true; + } + } +} + +struct dictionary_item *dictionary_get(struct dictionary *dictionary, char *key) { + for (size_t index = 0; index < dictionary->length; index++) { + struct dictionary_item *item = dictionary->items[index]; + if (string_get_is_equal(key, item->key)) { + return item; + } + } + return NULL; +} + +bool dictionary_contains_key(struct dictionary *dictionary, char *key) { + return dictionary_get(dictionary, key) != NULL; +} diff --git a/lib/dictionary.h b/lib/dictionary.h new file mode 100644 index 0000000..f02c376 --- /dev/null +++ b/lib/dictionary.h @@ -0,0 +1,34 @@ +#ifndef __DICTIONARY__ +#define __DICTIONARY__ + +#include +#include + +#include "linked_list.h" + +#define DICTIONARY_INITIAL_CAPACITY 10 + +// Dictionary implementation with O(n) lookup complexity. +struct dictionary { + struct dictionary_item **items; + + size_t length; + size_t capacity; +}; + +struct dictionary_item { + void *data; + char *key; +}; + +struct dictionary *dictionary_initialization(); + +void dictionary_add(struct dictionary *dictionary, char *key, void *data); + +void dictionary_remove(struct dictionary *dictionary, char *key); + +struct dictionary_item *dictionary_get(struct dictionary *dictionary, char *key); + +bool dictionary_contains_key(struct dictionary *dictionary, char *key); + +#endif diff --git a/lib/filesystem.c b/lib/filesystem.c new file mode 100644 index 0000000..c6f479c --- /dev/null +++ b/lib/filesystem.c @@ -0,0 +1,57 @@ +#include "filesystem.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "string.h" + +int filesystem_read(char *path, char **file_content, off_t *file_size) { + int file_descriptor = open(path, O_RDONLY); + if (file_descriptor == -1) { + return -1; + } + (*file_size) = lseek(file_descriptor, 0, SEEK_END); + lseek(file_descriptor, 0, SEEK_SET); + (*file_content) = malloc(*file_size); + read(file_descriptor, *file_content, *file_size); + close(file_descriptor); + return 0; +} + +int filesystem_write(char *path, char *file_content, off_t file_size) { + int file_descriptor = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (file_descriptor == -1) { + return -1; + } + write(file_descriptor, file_content, file_size); + close(file_descriptor); + return 0; +} + +char *filesystem_get_mimetype(char *path) { + if (string_ends_with(path, ".html")) { + return "text/html"; + } + if (string_ends_with(path, ".css")) { + return "text/css"; + } + if (string_ends_with(path, ".js")) { + return "text/javascript"; + } + if (string_ends_with(path, ".png")) { + return "image/png"; + } + if (string_ends_with(path, ".jpg") || string_ends_with(path, ".jpeg")) { + return "image/jpeg"; + } + if (string_ends_with(path, ".gif")) { + return "image/gif"; + } + return "text/plain"; +} diff --git a/lib/filesystem.h b/lib/filesystem.h new file mode 100644 index 0000000..60482a3 --- /dev/null +++ b/lib/filesystem.h @@ -0,0 +1,38 @@ +#ifndef __FILESYSTEM__ +#define __FILESYSTEM__ + +#include + +/** + * @brief Read the content of a file. + * + * @param path + * @param file_content + * @param file_size + * @return int + * @retval -1 if the file does not exist + * @retval 0 for success + */ +int filesystem_read(char *path, char **file_content, off_t *file_size); + +/** + * @brief Write the content to a file. + * + * @param path + * @param file_content + * @param file_size + * @return int + * @retval -1 if errors + * @retval 0 for success + */ +int filesystem_write(char *path, char *file_content, off_t file_size); + +/** + * @brief Get the mimetype of a file. + * + * @param path + * @return char* + */ +char *filesystem_get_mimetype(char *path); + +#endif diff --git a/lib/linked_list.c b/lib/linked_list.c new file mode 100644 index 0000000..d2e5c22 --- /dev/null +++ b/lib/linked_list.c @@ -0,0 +1,91 @@ +#include "linked_list.h" + +#include +#include + +#include "stack.h" + +struct linked_list *linked_list_initialization() { + struct linked_list *list = malloc(sizeof(*list)); + if (list == NULL) { + exit(EXIT_FAILURE); + } + list->head = NULL; + list->length = 0; + return list; +} + +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 || node_new == NULL) { + exit(EXIT_FAILURE); + } + node_new->data = new_data; + node_new->next = list->head; + list->head = node_new; + list->length = list->length + 1; + return node_new; +} + +void linked_list_delete_in_head(struct linked_list *list) { + if (list == NULL) { + exit(EXIT_FAILURE); + } + if (list->head != NULL) { + struct linked_list_node *node_to_remove = list->head; + list->head = list->head->next; + list->length = list->length - 1; + free(node_to_remove); + } +} + +struct linked_list_node *linked_list_add_after_last(struct linked_list *list, void *new_data) { + 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) { + exit(EXIT_FAILURE); + } + node_new->data = new_data; + node_new->next = NULL; + struct linked_list_node *node_current_last = list->head; + size_t index = 0; + while (index < list->length - 1) { + node_current_last = node_current_last->next; + index++; + } + node_current_last->next = node_new; + list->length = list->length + 1; + return node_new; +} + +struct linked_list *linked_list_reverse(struct linked_list *list) { + struct stack *stack = stack_initialization(); + struct linked_list_node *linked_list_node_current = list->head; + while (linked_list_node_current != NULL) { + stack_push(stack, linked_list_node_current->data); + linked_list_node_current = linked_list_node_current->next; + } + struct linked_list *linked_list_reversed = linked_list_initialization(); + struct stack_node *stack_node_current = stack->first; + while (stack_node_current != NULL) { + linked_list_add_after_last(linked_list_reversed, stack_node_current->data); + stack_node_current = stack_node_current->next; + } + return linked_list_reversed; +} + +void linked_list_reverse_mutate(struct linked_list *list) { + struct linked_list_node **current = &list->head; + struct linked_list_node *previous = NULL; + while (true) { + struct linked_list_node *temporary_current = (*current)->next; + (*current)->next = previous; + previous = *current; + if (temporary_current == NULL) { + break; + } + (*current) = temporary_current; + } +} diff --git a/lib/linked_list.h b/lib/linked_list.h new file mode 100644 index 0000000..8aada1e --- /dev/null +++ b/lib/linked_list.h @@ -0,0 +1,30 @@ +#ifndef __LINKED_LIST__ +#define __LINKED_LIST__ + +#include + +struct linked_list { + // first node of the list + struct linked_list_node *head; + + size_t length; +}; + +struct linked_list_node { + void *data; + struct linked_list_node *next; +}; + +struct linked_list *linked_list_initialization(); + +struct linked_list_node *linked_list_add_in_head(struct linked_list *list, void *new_value); + +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 *linked_list_reverse(struct linked_list *list); + +void linked_list_reverse_mutate(struct linked_list *list); + +#endif diff --git a/lib/mathematics.c b/lib/mathematics.c new file mode 100644 index 0000000..e19ec9e --- /dev/null +++ b/lib/mathematics.c @@ -0,0 +1,36 @@ +#include "mathematics.h" + +#include + +bool mathematics_get_is_equal(const float number1, const float number2) { + return (number1 - number2) < MATHEMATICS_FLOAT_PRECISION; +} + +unsigned long long mathematics_absolute_value(const long long number) { + if (number >= 0) { + return number; + } + return -number; +} + +unsigned long long mathematics_pow(unsigned long long base, unsigned long long exponent) { + return exponent == 0 ? 1 : base * mathematics_pow(base, exponent - 1); +} + +float mathematics_root(float number, unsigned int nth_root) { + float result = number; + float previous_result = 0; + while (!mathematics_get_is_equal(result, previous_result)) { + result = (((nth_root - 1) * previous_result) + (number / mathematics_pow(result, nth_root - 1))) / nth_root; + previous_result = result; + } + return result; +} + +float mathematics_square_root(float number) { + return mathematics_root(number, 2); +} + +unsigned long long mathematics_factorial(unsigned long long number) { + return number == 0 ? 1 : number * mathematics_factorial(number - 1); +} diff --git a/lib/mathematics.h b/lib/mathematics.h new file mode 100644 index 0000000..51957bd --- /dev/null +++ b/lib/mathematics.h @@ -0,0 +1,27 @@ +#ifndef __MATHEMATICS__ +#define __MATHEMATICS__ + +#define MATHEMATICS_FLOAT_PRECISION 0.00000001 + +#include + +bool mathematics_get_is_equal(const float number1, const float number2); + +unsigned long long mathematics_absolute_value(const long long number); + +unsigned long long mathematics_pow(unsigned long long base, unsigned long long exponent); + +/** + * @brief Calculates the nth root of a number using Heron's method. + * + * @param number + * @param nth_root + * @return float + */ +float mathematics_root(float number, unsigned int nth_root); + +float mathematics_square_root(float number); + +unsigned long long mathematics_factorial(unsigned long long number); + +#endif diff --git a/lib/queue.c b/lib/queue.c new file mode 100644 index 0000000..3c0becd --- /dev/null +++ b/lib/queue.c @@ -0,0 +1,48 @@ +#include "queue.h" + +#include +#include + +struct queue *queue_initialization() { + struct queue *queue = malloc(sizeof(*queue)); + if (queue == NULL) { + exit(EXIT_FAILURE); + } + queue->first = NULL; + queue->length = 0; + return queue; +} + +void queue_push(struct queue *queue, void *data) { + struct queue_node *node_new = malloc(sizeof(*node_new)); + if (queue == NULL || node_new == NULL) { + exit(EXIT_FAILURE); + } + node_new->data = data; + node_new->next = NULL; + if (queue->first != NULL) { + struct queue_node *node_current = queue->first; + while (node_current->next != NULL) { + node_current = node_current->next; + } + node_current->next = node_new; + } else { + queue->first = node_new; + } + queue->length = queue->length + 1; +} + +void *queue_pop(struct queue *queue) { + if (queue == NULL) { + exit(EXIT_FAILURE); + } + struct queue_node *node = queue->first; + void *data = NULL; + if (node != NULL) { + queue->first = node->next; + data = node->data; + free(node); + } + queue->length = queue->length - 1; + return data; +} diff --git a/lib/queue.h b/lib/queue.h new file mode 100644 index 0000000..b8ecf79 --- /dev/null +++ b/lib/queue.h @@ -0,0 +1,23 @@ +#ifndef __QUEUE__ +#define __QUEUE__ + +#include + +// FIFO = First In First Out +struct queue { + struct queue_node *first; + size_t length; +}; + +struct queue_node { + void *data; + struct queue_node *next; +}; + +struct queue *queue_initialization(); + +void queue_push(struct queue *queue, void *data); + +void *queue_pop(struct queue *queue); + +#endif diff --git a/lib/stack.c b/lib/stack.c new file mode 100644 index 0000000..c04b073 --- /dev/null +++ b/lib/stack.c @@ -0,0 +1,40 @@ +#include "stack.h" + +#include +#include + +struct stack *stack_initialization() { + struct stack *stack = malloc(sizeof(*stack)); + if (stack == NULL) { + exit(EXIT_FAILURE); + } + stack->first = NULL; + stack->length = 0; + return stack; +} + +void stack_push(struct stack *stack, void *data) { + struct stack_node *node_new = malloc(sizeof(*node_new)); + if (stack == NULL || data == NULL) { + exit(EXIT_FAILURE); + } + node_new->data = data; + node_new->next = stack->first; + stack->first = node_new; + stack->length = stack->length + 1; +} + +void *stack_pop(struct stack *stack) { + if (stack == NULL) { + exit(EXIT_FAILURE); + } + struct stack_node *node = stack->first; + void *data = NULL; + if (node != NULL) { + stack->first = node->next; + data = node->data; + free(node); + } + stack->length = stack->length - 1; + return data; +} diff --git a/lib/stack.h b/lib/stack.h new file mode 100644 index 0000000..26d367c --- /dev/null +++ b/lib/stack.h @@ -0,0 +1,23 @@ +#ifndef __STACK__ +#define __STACK__ + +#include + +// LIFO = Last In First Out +struct stack { + struct stack_node *first; + size_t length; +}; + +struct stack_node { + void *data; + struct stack_node *next; +}; + +struct stack *stack_initialization(); + +void stack_push(struct stack *stack, void *data); + +void *stack_pop(struct stack *stack); + +#endif diff --git a/lib/string.c b/lib/string.c new file mode 100644 index 0000000..884015a --- /dev/null +++ b/lib/string.c @@ -0,0 +1,363 @@ +#include "string.h" + +#include +#include +#include + +#include "character.h" +#include "convert.h" +#include "dictionary.h" + +size_t string_get_length(const char* string) { + size_t length = 0; + while (string[length] != '\0') { + length++; + } + return length; +} + +char* string_to_uppercase(char* string) { + size_t string_length = string_get_length(string); + char* result = malloc(sizeof(char*) * string_length); + if (result == NULL) { + exit(EXIT_FAILURE); + } + for (size_t index = 0; index < string_length; index++) { + character_append(result, character_to_upper(string[index])); + } + return result; +} + +char* string_to_lowercase(char* string) { + size_t string_length = string_get_length(string); + char* result = malloc(sizeof(char*) * string_length); + if (result == NULL) { + exit(EXIT_FAILURE); + } + for (size_t index = 0; index < string_length; index++) { + character_append(result, character_to_lower(string[index])); + } + return result; +} + +char* string_replace(char* string, char search, char replace) { + size_t string_length = string_get_length(string); + char* result = malloc(sizeof(char*) * string_length); + if (result == NULL) { + exit(EXIT_FAILURE); + } + for (size_t index = 0; index < string_length; index++) { + bool is_search_value = search == string[index]; + if (is_search_value) { + character_append(result, replace); + } else { + character_append(result, string[index]); + } + } + return result; +} + +char* string_trim_start(char* string) { + size_t string_length = string_get_length(string); + char* result = malloc(sizeof(char*) * string_length); + if (result == NULL) { + exit(EXIT_FAILURE); + } + size_t index_space = 0; + while (string[index_space] == ' ') { + index_space++; + } + for (size_t index = index_space; index < string_length; index++) { + character_append(result, string[index]); + } + return result; +} + +char* string_trim_end(char* string) { + size_t string_length = string_get_length(string); + char* result = malloc(sizeof(char*) * string_length); + if (result == NULL) { + exit(EXIT_FAILURE); + } + size_t index_space = string_length - 1; + while (string[index_space] == ' ') { + index_space--; + } + for (size_t index = 0; index < index_space + 1; index++) { + character_append(result, string[index]); + } + return result; +} + +char* string_trim(char* string) { + char* result = string_trim_start(string); + result = string_trim_end(result); + return result; +} + +char* string_copy(const char* string) { + return string_substring(string, 0, string_get_length(string)); +} + +char* string_capitalize(char* string) { + size_t string_length = string_get_length(string); + char* result = malloc(sizeof(char*) * string_length); + if (result == NULL) { + exit(EXIT_FAILURE); + } + for (size_t index = 0; index < string_length; index++) { + bool is_first_character = index == 0; + if (is_first_character) { + character_append(result, character_to_upper(string[index])); + } else { + character_append(result, string[index]); + } + } + return result; +} + +size_t string_total_occurrences_of_character(char* string, char character) { + size_t result = 0; + size_t string_length = string_get_length(string); + for (size_t index = 0; index < string_length; index++) { + char current_character = string[index]; + if (current_character == character) { + result += 1; + } + } + return result; +} + +char* string_reverse(const char* string) { + size_t string_length = string_get_length(string); + size_t index = 0; + char* result = malloc(sizeof(char*) * string_length); + if (result == NULL) { + exit(EXIT_FAILURE); + } + for (index = string_length - 1; index > 0; index--) { + character_append(result, string[index]); + } + character_append(result, string[index]); + return result; +} + +bool string_get_is_equal(const char* string1, const char* string2) { + size_t string1_length = string_get_length(string1); + size_t string2_length = string_get_length(string2); + bool is_equal = string1_length == string2_length; + for (size_t index = 0; index < string1_length && is_equal; index++) { + if (string1[index] != string2[index]) { + is_equal = false; + } + } + return is_equal; +} + +bool string_get_is_integer(const char* string) { + size_t index = 0; + size_t string_length = string_get_length(string); + bool is_integer = string_length >= 1; + if (is_integer && string[0] == '-') { + if (string_length == 1) { + is_integer = false; + } else { + index++; + } + } + while (index < string_length && is_integer) { + if (!character_get_is_digit(string[index])) { + is_integer = false; + } + index++; + } + return is_integer; +} + +char** string_split(const char* 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; + char* current = malloc(sizeof(char*) * string_length); + char** result = malloc(sizeof(char**) * index_result); + if (result == NULL || current == NULL) { + exit(EXIT_FAILURE); + } + while (index_string < string_length) { + if (string[index_string] == separator) { + result[index_result] = string_copy(current); + index_result++; + result = realloc(result, sizeof(char*) * index_result); + if (result == NULL) { + exit(EXIT_FAILURE); + } + index_current = 0; + current = string_copy(""); + } else { + character_append(current, string[index_string]); + index_current++; + } + index_string++; + } + result[index_result] = string_copy(current); + free(current); + *result_size = index_result + 1; + return result; +} + +char* string_join(char** array, const char separator, size_t array_length) { + size_t string_length = array_length; + char* string = malloc(sizeof(char*) * string_length); + if (string == NULL) { + exit(EXIT_FAILURE); + } + for (size_t index_array = 0; index_array < array_length; index_array++) { + char* substring = array[index_array]; + size_t substring_length = string_get_length(substring); + string_length += substring_length; + string = realloc(string, sizeof(char*) * string_length); + if (string == NULL) { + exit(EXIT_FAILURE); + } + for (size_t index_substring = 0; index_substring < substring_length; index_substring++) { + character_append(string, substring[index_substring]); + } + bool is_last_character = index_array == (array_length - 1); + if (!is_last_character) { + character_append(string, separator); + } + } + return string; +} + +char* string_concatenate(char* string1, char* 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; + char* result = malloc(sizeof(char*) * result_length); + if (result == NULL) { + exit(EXIT_FAILURE); + } + for (size_t index_string1 = 0; index_string1 < string1_length; index_string1++) { + character_append(result, string1[index_string1]); + } + for (size_t index_string2 = 0; index_string2 < string2_length; index_string2++) { + character_append(result, string2[index_string2]); + } + return result; +} + +bool string_get_has_unique_characters(const char* string) { + bool has_unique = true; + size_t string_length = string_get_length(string); + struct dictionary* characters_already_seen = dictionary_initialization(); + for (size_t index = 0; index < string_length && has_unique; index++) { + char character = string[index]; + char* key = convert_character_to_string(character); + if (dictionary_contains_key(characters_already_seen, key)) { + has_unique = false; + } else { + dictionary_add(characters_already_seen, key, (void*)true); + } + } + return has_unique; +} + +char* string_substring(const char* string, size_t index_start, size_t index_end) { + size_t string_length = string_get_length(string); + char* result = malloc(sizeof(char*) * string_length); + for (size_t index = index_start; index <= index_end; index++) { + character_append(result, string[index]); + } + return result; +} + +bool string_get_is_substring(const char* string, const char* substring) { + bool is_substring = false; + 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[index_considered] == substring[index_substring]) { + index_substring++; + index_considered++; + } + is_substring = index_substring == substring_length; + } + return is_substring; +} + +char* string_get_formatted_number(const long long number, char* separator) { + char* number_string = convert_number_to_string(number); + bool is_negative = number_string[0] == '-'; + if (is_negative) { + number_string = string_substring(number_string, 1, string_get_length(number_string)); + } + size_t number_string_length = string_get_length(number_string); + char* result = malloc(sizeof(char*) * number_string_length); + if (result == NULL) { + exit(EXIT_FAILURE); + } + size_t count = 0; + for (size_t index = 0; index < number_string_length; index++) { + size_t index_reversed = number_string_length - index - 1; + count++; + result = string_concatenate(result, convert_character_to_string(number_string[index_reversed])); + if (count == 3) { + result = string_concatenate(result, separator); + 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); + } + if (is_negative) { + result = string_concatenate(convert_character_to_string('-'), result); + } + return result; +} + +char* string_get_last_occurence_of_character(const char* string, char character) { + size_t string_length = string_get_length(string); + char* result = malloc(sizeof(char*) * string_length); + if (result == NULL) { + exit(EXIT_FAILURE); + } + size_t index_result = 0; + for (size_t index = 0; index < string_length; index++) { + if (string[index] == character) { + index_result = 0; + result = string_copy(""); + } + character_append(result, string[index]); + index_result++; + } + return result; +} + +bool string_starts_with(const char* string, const char* 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[index] == prefix[index]; + } + return starts_with; +} + +bool string_ends_with(const char* string, const char* prefix) { + bool ends_with = true; + 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[index_string] == prefix[index_prefix]; + index_string--; + index_prefix--; + } + return ends_with; +} diff --git a/lib/string.h b/lib/string.h new file mode 100644 index 0000000..a34c669 --- /dev/null +++ b/lib/string.h @@ -0,0 +1,204 @@ +#ifndef __STRING__ +#define __STRING__ + +#include +#include + +/** + * @brief Return the length of a string (excluding '\0'). + * + * @param string + * @return size_t + */ +size_t string_get_length(const char* string); + +/** + * @brief Converts all the alphabetic characters in a string to uppercase. + * + * @param string + * @return char* + */ +char* string_to_uppercase(char* string); + +/** + * @brief Converts all the alphabetic characters in a string to lowercase. + * + * @param string + * @return char* + */ +char* string_to_lowercase(char* string); + +/** + * @brief Replace all the occurrences of search value into replace value in the string. + * + * @param string + * @param search_value A character search value. + * @param replace_value A character containing the text to replace for match. + * @return char* + */ +char* string_replace(char* string, char search, char replace); + +/** + * @brief Removes all whitespace from the start of a string. + * + * @param string + * @return char* + */ +char* string_trim_start(char* string); + +/** + * @brief Removes all whitespace from the end of a string. + * + * @param string + * @return char* + */ +char* string_trim_end(char* string); + +/** + * @brief Removes all whitespace from the start and end of a string. + * + * @param string + * @return char* + */ +char* string_trim(char* string); + +/** + * @brief Return the copy of a string. + * + * @param string + * @return char* + */ +char* string_copy(const char* string); + +/** + * @brief Capitalizes the string. + * + * @param string + * @return char* + */ +char* string_capitalize(char* string); + +/** + * @brief Returns the total number of occurrences of the given character in the string. + * + * @param string + * @param character + * @return size_t + */ +size_t string_total_occurrences_of_character(char* string, char character); + +/** + * @brief Reverse the characters in an array. + * + * @param string + * @return char* + */ +char* string_reverse(const char* string); + +/** + * @brief Check if two strings are equals. + * + * @param string1 + * @param string2 + * @return true if the strings are equals, false otherwise + */ +bool string_get_is_equal(const char* string1, const char* string2); + +/** + * @brief Check if the string is a integer. + * + * @param string + * @return true if the string is a integer, false otherwise + */ +bool string_get_is_integer(const char* string); + +/** + * @brief Split a string into substrings using the specified separator and return them as an array and update the pointer `result_size` to the resulting size of the created array. + * + * @param string + * @param separator + * @return char** + */ +char** string_split(const char* string, char separator, size_t* result_size); + +/** + * @brief Adds all the elements of an array into a string, separated by the specified separator string. + * + * @param array + * @param separator + * @return char* + */ +char* string_join(char** array, const char separator, size_t array_length); + +/** + * @brief Concatenate two strings. + * + * @param string1 + * @param string2 + * @return char* + */ +char* string_concatenate(char* string1, char* string2); + +/** + * @brief Check if a string contains only unique characters. + * + * @param string + * @return true if string contains only unique characters, false otherwise + */ +bool string_get_has_unique_characters(const char* string); + +/** + * @brief Returns the part of the string between the start and end indexes (both included). + * + * @param string + * @param index_start + * @param index_end + * @return char* + */ +char* string_substring(const char* string, size_t index_start, size_t index_end); + +/** + * @brief Check if a string contains a substring. + * + * @param string + * @param substring + * @return true if the string contains the substring, false otherwise + */ +bool string_get_is_substring(const char* string, const char* substring); + +/** + * @brief Format a number to a string with specified separator. + * + * @param integer + * @return char* example: string_get_formatted_number(1000, " ") => "1 000" + */ +char* string_get_formatted_number(const long long number, char* separator); + +/** + * @brief Returns a pointer to the last occurrence of character in the string. + * + * @param string + * @param character + * @return char* + */ +char* string_get_last_occurence_of_character(const char* string, char character); + +/** + * @brief Check if a string starts with a substring. + * + * @param string + * @param prefix + * @return true if the string starts with the substring, false otherwise + */ +bool string_starts_with(const char* string, const char* prefix); + +/** + * @brief Check if a string ends with a substring. + * + * @param string + * @param prefix + * @return true if the string ends with the substring, false otherwise + */ +bool string_ends_with(const char* string, const char* prefix); + +#endif diff --git a/lib/terminal.c b/lib/terminal.c new file mode 100644 index 0000000..8d3bc91 --- /dev/null +++ b/lib/terminal.c @@ -0,0 +1,122 @@ +#include "terminal.h" + +#include +#include +#include +#include + +#include "character.h" +#include "dictionary.h" +#include "linked_list.h" +#include "queue.h" +#include "stack.h" + +char* terminal_input() { + char character; + size_t length = 1; + char* string = malloc(length * sizeof(char)); + if (string == NULL) { + exit(EXIT_FAILURE); + } + *string = '\0'; + while ((character = getchar()) != '\n' && character != EOF) { + length++; + string = realloc(string, length * sizeof(char)); + if (string == NULL) { + exit(EXIT_FAILURE); + } + character_append(string, character); + } + 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) { + printf("%d", *(int*)value); +} + +void terminal_print_long(void* value) { + printf("%ld", *(long*)value); +} + +void terminal_print_unsigned_long(void* value) { + printf("%lu", *(unsigned long*)value); +} + +void terminal_print_char(void* value) { + printf("%c", *(char*)value); +} + +void terminal_print_string(void* value) { + printf("%s", (char*)value); +} + +void terminal_print_stack(struct stack* stack, void (*print_element)(void*)) { + if (stack == NULL) { + exit(EXIT_FAILURE); + } + struct stack_node* node_current = stack->first; + while (node_current != NULL) { + printf("|\t"); + void* element = (char*)node_current->data; + print_element(&element); + node_current = node_current->next; + printf("\t|\n"); + } +} + +void terminal_print_queue(struct queue* queue, void (*print_element)(void*)) { + if (queue == NULL) { + exit(EXIT_FAILURE); + } + struct queue_node* node_current = queue->first; + while (node_current != NULL) { + printf("|\t"); + void* element = (char*)node_current->data; + print_element(&element); + node_current = node_current->next; + printf("\t|\n"); + } +} + +void terminal_print_linked_list(struct linked_list* linked_list, void (*print_element)(void*)) { + if (linked_list == NULL) { + exit(EXIT_FAILURE); + } + struct linked_list_node* node_current = linked_list->head; + while (node_current != NULL) { + void* element = (char*)node_current->data; + node_current = node_current->next; + print_element(&element); + printf(" -> "); + } + printf("NULL\n"); +} + +void terminal_print_dictionary(struct dictionary* dictionary, void (*print_element)(void*)) { + if (dictionary == NULL) { + exit(EXIT_FAILURE); + } + printf("{\n"); + for (size_t index = 0; index < dictionary->length; index++) { + struct dictionary_item* item = dictionary->items[index]; + printf("\t\""); + terminal_print_string(item->key); + printf("\" -> "); + print_element(&item->data); + printf("\n"); + } + printf("}\n"); +} diff --git a/lib/terminal.h b/lib/terminal.h new file mode 100644 index 0000000..ce3c0f2 --- /dev/null +++ b/lib/terminal.h @@ -0,0 +1,38 @@ +#ifndef __TERMINAL__ +#define __TERMINAL__ + +#include + +#include "dictionary.h" +#include "linked_list.h" +#include "queue.h" +#include "stack.h" + +/** + * @brief Read a line from stdin. + * + * @return char* + */ +char* terminal_input(); + +void terminal_print_array(void* array, size_t array_size, size_t element_size, void (*print_element)(void*)); + +void terminal_print_int(void* value); + +void terminal_print_long(void* value); + +void terminal_print_unsigned_long(void* value); + +void terminal_print_char(void* value); + +void terminal_print_string(void* value); + +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_linked_list(struct linked_list* linked_list, void (*print_element)(void*)); + +void terminal_print_dictionary(struct dictionary* dictionary, void (*print_element)(void*)); + +#endif diff --git a/libcproject.h b/libcproject.h new file mode 100644 index 0000000..9c0a716 --- /dev/null +++ b/libcproject.h @@ -0,0 +1,15 @@ +#ifndef __LIBCPROJECT__ +#define __LIBCPROJECT__ + +#include "lib/character.h" +#include "lib/convert.h" +#include "lib/dictionary.h" +#include "lib/filesystem.h" +#include "lib/linked_list.h" +#include "lib/mathematics.h" +#include "lib/queue.h" +#include "lib/stack.h" +#include "lib/string.h" +#include "lib/terminal.h" + +#endif diff --git a/main.c b/main.c new file mode 100644 index 0000000..7b0f915 --- /dev/null +++ b/main.c @@ -0,0 +1,11 @@ +#include +#include + +#include "libcproject.h" + +int main() { + char* string = "Hello, world!"; + printf("%s\n", string); + printf("string_length = %ld\n", string_get_length(string)); + return EXIT_SUCCESS; +} diff --git a/test/character_test.c b/test/character_test.c new file mode 100644 index 0000000..74f404e --- /dev/null +++ b/test/character_test.c @@ -0,0 +1,73 @@ +#include "character_test.h" + +#include +#include +#include + +#include "libcproject.h" +#include "test.h" + +void character_test() { + character_append_test(); + character_append_at_test(); + character_to_upper_test(); + character_to_lower_test(); + character_get_is_digit_test(); + character_get_alphabet_position_test(); +} + +void character_append_test() { + char string[5] = "abc"; + character_append(string, 'd'); + assert(assert_string_equal(string, "abcd")); +} + +void character_append_at_test() { + char string[5] = "abc"; + character_append_at(string, 'd', 1); + assert(assert_string_equal(string, "adbc")); + + char string2[5] = "abcd"; + character_append_at(string2, 'e', 4); + assert(assert_string_equal(string2, "abcde")); +} + +void character_to_upper_test() { + assert(character_to_upper('a') == 'A'); + assert(character_to_upper('e') == 'E'); + assert(character_to_upper('A') == 'A'); +} + +void character_to_lower_test() { + assert(character_to_lower('A') == 'a'); + assert(character_to_lower('E') == 'e'); + assert(character_to_lower('a') == 'a'); +} + +void character_get_is_digit_test() { + assert(character_get_is_digit('0')); + assert(character_get_is_digit('1')); + assert(character_get_is_digit('2')); + assert(character_get_is_digit('3')); + assert(character_get_is_digit('4')); + assert(character_get_is_digit('5')); + assert(character_get_is_digit('6')); + assert(character_get_is_digit('7')); + assert(character_get_is_digit('8')); + assert(character_get_is_digit('9')); + assert(!character_get_is_digit('a')); + assert(!character_get_is_digit('/')); + assert(!character_get_is_digit(':')); +} + +void character_get_alphabet_position_test() { + assert(character_get_alphabet_position('a') == 1); + assert(character_get_alphabet_position('A') == 1); + assert(character_get_alphabet_position('B') == 2); + assert(character_get_alphabet_position('D') == 4); + assert(character_get_alphabet_position('m') == 13); + assert(character_get_alphabet_position('n') == 14); + assert(character_get_alphabet_position('z') == 26); + assert(character_get_alphabet_position('@') == 0); + assert(character_get_alphabet_position('-') == 0); +} diff --git a/test/character_test.h b/test/character_test.h new file mode 100644 index 0000000..0b5c386 --- /dev/null +++ b/test/character_test.h @@ -0,0 +1,18 @@ +#ifndef __CHARACTER_TEST__ +#define __CHARACTER_TEST__ + +void character_test(); + +void character_append_test(); + +void character_append_at_test(); + +void character_to_upper_test(); + +void character_to_lower_test(); + +void character_get_is_digit_test(); + +void character_get_alphabet_position_test(); + +#endif diff --git a/test/convert_test.c b/test/convert_test.c new file mode 100644 index 0000000..9418c52 --- /dev/null +++ b/test/convert_test.c @@ -0,0 +1,102 @@ +#include "convert_test.h" + +#include +#include +#include + +#include "libcproject.h" +#include "test.h" + +void convert_test() { + convert_character_to_string_test(); + convert_character_to_digit_test(); + convert_digit_to_character_test(); + convert_string_to_number_test(); + convert_number_to_string_test(); + convert_number_from_base_to_another_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'), "")); +} + +void convert_character_to_digit_test() { + assert(convert_character_to_digit('0') == 0); + assert(convert_character_to_digit('1') == 1); + assert(convert_character_to_digit('2') == 2); + assert(convert_character_to_digit('3') == 3); + assert(convert_character_to_digit('4') == 4); + assert(convert_character_to_digit('5') == 5); + assert(convert_character_to_digit('6') == 6); + assert(convert_character_to_digit('7') == 7); + assert(convert_character_to_digit('8') == 8); + assert(convert_character_to_digit('9') == 9); +} + +void convert_digit_to_character_test() { + assert(convert_digit_to_character(0) == '0'); + assert(convert_digit_to_character(1) == '1'); + assert(convert_digit_to_character(2) == '2'); + assert(convert_digit_to_character(3) == '3'); + assert(convert_digit_to_character(4) == '4'); + assert(convert_digit_to_character(5) == '5'); + assert(convert_digit_to_character(6) == '6'); + assert(convert_digit_to_character(7) == '7'); + assert(convert_digit_to_character(8) == '8'); + assert(convert_digit_to_character(9) == '9'); +} + +void convert_string_to_number_test() { + assert(convert_string_to_number("0") == 0); + assert(convert_string_to_number("1") == 1); + assert(convert_string_to_number("2") == 2); + assert(convert_string_to_number("3") == 3); + assert(convert_string_to_number("4") == 4); + assert(convert_string_to_number("5") == 5); + assert(convert_string_to_number("6") == 6); + assert(convert_string_to_number("7") == 7); + assert(convert_string_to_number("8") == 8); + assert(convert_string_to_number("9") == 9); + assert(convert_string_to_number("10") == 10); + assert(convert_string_to_number("11") == 11); + assert(convert_string_to_number("20") == 20); + assert(convert_string_to_number("-0") == 0); + assert(convert_string_to_number("-1") == -1); + assert(convert_string_to_number("-20") == -20); +} + +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")); +} + +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")); +} diff --git a/test/convert_test.h b/test/convert_test.h new file mode 100644 index 0000000..e896781 --- /dev/null +++ b/test/convert_test.h @@ -0,0 +1,18 @@ +#ifndef __CONVERT_TEST__ +#define __CONVERT_TEST__ + +void convert_test(); + +void convert_character_to_string_test(); + +void convert_character_to_digit_test(); + +void convert_digit_to_character_test(); + +void convert_string_to_number_test(); + +void convert_number_to_string_test(); + +void convert_number_from_base_to_another_test(); + +#endif diff --git a/test/dictionary_test.c b/test/dictionary_test.c new file mode 100644 index 0000000..ad69dbc --- /dev/null +++ b/test/dictionary_test.c @@ -0,0 +1,33 @@ +#include "dictionary_test.h" + +#include +#include +#include + +#include "libcproject.h" + +void dictionary_test() { + struct dictionary *dictionary = dictionary_initialization(); + assert(dictionary->length == 0); + dictionary_add(dictionary, "key", (void *)'a'); + dictionary_add(dictionary, "key1", (void *)'b'); + dictionary_add(dictionary, "key2", (void *)'c'); + dictionary_add(dictionary, "key3", (void *)'d'); + dictionary_add(dictionary, "key4", (void *)'e'); + dictionary_add(dictionary, "key5", (void *)'f'); + assert(dictionary->length == 6); + assert(dictionary_get(dictionary, "key")->data == (void *)'a'); + assert(dictionary_get(dictionary, "key1")->data == (void *)'b'); + assert(dictionary_get(dictionary, "key2")->data == (void *)'c'); + assert(dictionary_get(dictionary, "key3")->data == (void *)'d'); + assert(dictionary_get(dictionary, "key4")->data == (void *)'e'); + assert(dictionary_get(dictionary, "key5")->data == (void *)'f'); + dictionary_add(dictionary, "key5", (void *)'a'); + assert(dictionary_get(dictionary, "key5")->data == (void *)'a'); + assert(dictionary_contains_key(dictionary, "key5")); + assert(!dictionary_contains_key(dictionary, "invalid key")); + assert(dictionary_contains_key(dictionary, "key5")); + dictionary_remove(dictionary, "key5"); + assert(dictionary->length == 5); + assert(!dictionary_contains_key(dictionary, "key5")); +} diff --git a/test/dictionary_test.h b/test/dictionary_test.h new file mode 100644 index 0000000..4b354e8 --- /dev/null +++ b/test/dictionary_test.h @@ -0,0 +1,6 @@ +#ifndef __DICTIONARY_TEST__ +#define __DICTIONARY_TEST__ + +void dictionary_test(); + +#endif diff --git a/test/linked_list_test.c b/test/linked_list_test.c new file mode 100644 index 0000000..97fc4bb --- /dev/null +++ b/test/linked_list_test.c @@ -0,0 +1,99 @@ +#include "linked_list_test.h" + +#include +#include +#include +#include + +#include "libcproject.h" + +void linked_list_test() { + linked_list_initialization_test(); + linked_list_add_in_head_test(); + linked_list_delete_in_head_test(); + linked_list_add_after_last_test(); + linked_list_reverse_test(); + linked_list_reverse_mutate_test(); +} + +void linked_list_initialization_test() { + struct linked_list *list = linked_list_initialization(); + assert(list->length == 0); + assert(list->head == NULL); +} + +void linked_list_add_in_head_test() { + struct linked_list *list = linked_list_initialization(); + linked_list_add_in_head(list, (void *)4); + linked_list_add_in_head(list, (void *)8); + linked_list_add_in_head(list, (void *)15); + assert(list->length == 3); + assert(((uintptr_t)list->head->data) == 15); + assert(((uintptr_t)list->head->next->data) == 8); + assert(((uintptr_t)list->head->next->next->data) == 4); + assert(list->head->next->next->next == NULL); +} + +void linked_list_delete_in_head_test() { + struct linked_list *list = linked_list_initialization(); + linked_list_add_in_head(list, (void *)4); + linked_list_add_in_head(list, (void *)8); + linked_list_add_in_head(list, (void *)15); + linked_list_delete_in_head(list); + assert(list->length == 2); + assert(((uintptr_t)list->head->data) == 8); + assert(((uintptr_t)list->head->next->data) == 4); + assert(list->head->next->next == NULL); +} + +void linked_list_add_after_last_test() { + struct linked_list *list = linked_list_initialization(); + linked_list_add_in_head(list, (void *)4); + linked_list_add_in_head(list, (void *)8); + linked_list_add_in_head(list, (void *)15); + assert(list->length == 3); + assert(((uintptr_t)list->head->data) == 15); + assert(((uintptr_t)list->head->next->data) == 8); + assert(((uintptr_t)list->head->next->next->data) == 4); + linked_list_add_after_last(list, (void *)18); + assert(list->length == 4); + assert(((uintptr_t)list->head->data) == 15); + 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); +} + +void linked_list_reverse_test() { + struct linked_list *list = linked_list_initialization(); + linked_list_add_after_last(list, (void *)'A'); + linked_list_add_after_last(list, (void *)'B'); + linked_list_add_after_last(list, (void *)'C'); + linked_list_add_after_last(list, (void *)'D'); + assert(list->length == 4); + struct linked_list *list_reversed = linked_list_reverse(list); + assert(list->length == 4); + assert((list->head->data) == (void *)'A'); + assert((list->head->next->data) == (void *)'B'); + assert((list->head->next->next->data) == (void *)'C'); + assert((list->head->next->next->next->data) == (void *)'D'); + assert(list_reversed->length == 4); + assert((list_reversed->head->data) == (void *)'D'); + 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'); +} + +void linked_list_reverse_mutate_test() { + struct linked_list *list = linked_list_initialization(); + linked_list_add_after_last(list, (void *)'A'); + linked_list_add_after_last(list, (void *)'B'); + linked_list_add_after_last(list, (void *)'C'); + linked_list_add_after_last(list, (void *)'D'); + assert(list->length == 4); + linked_list_reverse_mutate(list); + assert(list->length == 4); + assert((list->head->data) == (void *)'D'); + assert((list->head->next->data) == (void *)'C'); + assert((list->head->next->next->data) == (void *)'B'); + assert((list->head->next->next->next->data) == (void *)'A'); +} diff --git a/test/linked_list_test.h b/test/linked_list_test.h new file mode 100644 index 0000000..92a74c8 --- /dev/null +++ b/test/linked_list_test.h @@ -0,0 +1,18 @@ +#ifndef __LINKED_LIST_TEST__ +#define __LINKED_LIST_TEST__ + +void linked_list_test(); + +void linked_list_initialization_test(); + +void linked_list_add_in_head_test(); + +void linked_list_delete_in_head_test(); + +void linked_list_add_after_last_test(); + +void linked_list_reverse_test(); + +void linked_list_reverse_mutate_test(); + +#endif diff --git a/test/main.c b/test/main.c new file mode 100644 index 0000000..453da0e --- /dev/null +++ b/test/main.c @@ -0,0 +1,24 @@ +#include +#include + +#include "character_test.h" +#include "convert_test.h" +#include "dictionary_test.h" +#include "linked_list_test.h" +#include "mathematics_test.h" +#include "queue_test.h" +#include "stack_test.h" +#include "string_test.h" + +int main() { + character_test(); + convert_test(); + dictionary_test(); + linked_list_test(); + mathematics_test(); + queue_test(); + stack_test(); + string_test(); + printf("Success: Tests passed!\n"); + return EXIT_SUCCESS; +} diff --git a/test/mathematics_test.c b/test/mathematics_test.c new file mode 100644 index 0000000..9d08c35 --- /dev/null +++ b/test/mathematics_test.c @@ -0,0 +1,62 @@ +#include "mathematics_test.h" + +#include + +#include "libcproject.h" + +void mathematics_test() { + mathematics_absolute_value_test(); + mathematics_pow_test(); + mathematics_root_test(); + mathematics_square_root_test(); + mathematics_factorial_test(); +} + +void mathematics_absolute_value_test() { + assert(mathematics_absolute_value(0) == 0); + assert(mathematics_absolute_value(-0) == 0); + assert(mathematics_absolute_value(1) == 1); + assert(mathematics_absolute_value(-1) == 1); + assert(mathematics_absolute_value(2) == 2); + assert(mathematics_absolute_value(-2) == 2); +} + +void mathematics_pow_test() { + assert(mathematics_pow(0, 0) == 1); + assert(mathematics_pow(0, 1) == 0); + assert(mathematics_pow(2, 2) == 4); + assert(mathematics_pow(5, 2) == 25); + assert(mathematics_pow(3, 3) == 27); + assert(mathematics_pow(7, 5) == 16807); +} + +void mathematics_root_test() { + assert(mathematics_get_is_equal(mathematics_root(0, 0), 0)); + assert(mathematics_get_is_equal(mathematics_root(0, 1), 0)); + assert(mathematics_get_is_equal(mathematics_root(2, 2), 1)); + assert(mathematics_get_is_equal(mathematics_root(27, 3), 3)); + assert(mathematics_get_is_equal(mathematics_root(16807, 5), 7)); +} + +void mathematics_square_root_test() { + assert(mathematics_get_is_equal(mathematics_square_root(0), 0)); + assert(mathematics_get_is_equal(mathematics_square_root(1), 1)); + assert(mathematics_get_is_equal(mathematics_square_root(4), 2)); + assert(mathematics_get_is_equal(mathematics_square_root(9), 3)); + assert(mathematics_get_is_equal(mathematics_square_root(25), 5)); + assert(mathematics_get_is_equal(mathematics_square_root(100), 10)); +} + +void mathematics_factorial_test() { + assert(mathematics_factorial(0) == 1); + assert(mathematics_factorial(1) == 1); + assert(mathematics_factorial(2) == 2); + assert(mathematics_factorial(3) == 6); + assert(mathematics_factorial(4) == 24); + assert(mathematics_factorial(5) == 120); + assert(mathematics_factorial(6) == 720); + assert(mathematics_factorial(7) == 5040); + assert(mathematics_factorial(8) == 40320); + assert(mathematics_factorial(9) == 362880); + assert(mathematics_factorial(10) == 3628800); +} diff --git a/test/mathematics_test.h b/test/mathematics_test.h new file mode 100644 index 0000000..ffe3ffa --- /dev/null +++ b/test/mathematics_test.h @@ -0,0 +1,16 @@ +#ifndef __MATHEMATICS_TEST__ +#define __MATHEMATICS_TEST__ + +void mathematics_test(); + +void mathematics_absolute_value_test(); + +void mathematics_pow_test(); + +void mathematics_root_test(); + +void mathematics_square_root_test(); + +void mathematics_factorial_test(); + +#endif diff --git a/test/queue_test.c b/test/queue_test.c new file mode 100644 index 0000000..7dde116 --- /dev/null +++ b/test/queue_test.c @@ -0,0 +1,44 @@ +#include "queue_test.h" + +#include +#include +#include + +#include "libcproject.h" + +void queue_test() { + queue_initialization_test(); + queue_push_test(); + queue_pop_test(); +} + +void queue_initialization_test() { + struct queue *queue = queue_initialization(); + assert(queue->length == 0); + assert(queue->first == NULL); +} + +void queue_push_test() { + struct queue *queue = queue_initialization(); + queue_push(queue, (void *)4); + queue_push(queue, (void *)8); + queue_push(queue, (void *)15); + assert(queue->length == 3); + assert(((uintptr_t)queue->first->data) == 4); + assert(((uintptr_t)queue->first->next->data) == 8); + assert(((uintptr_t)queue->first->next->next->data) == 15); + assert(queue->first->next->next->next == NULL); +} + +void queue_pop_test() { + struct queue *queue = queue_initialization(); + queue_push(queue, (void *)4); + queue_push(queue, (void *)8); + queue_push(queue, (void *)15); + void *node = queue_pop(queue); + assert(queue->length == 2); + assert(((uintptr_t)node) == 4); + assert(((uintptr_t)queue->first->data) == 8); + assert(((uintptr_t)queue->first->next->data) == 15); + assert(queue->first->next->next == NULL); +} diff --git a/test/queue_test.h b/test/queue_test.h new file mode 100644 index 0000000..a14f028 --- /dev/null +++ b/test/queue_test.h @@ -0,0 +1,12 @@ +#ifndef __QUEUE_TEST__ +#define __QUEUE_TEST__ + +void queue_test(); + +void queue_initialization_test(); + +void queue_push_test(); + +void queue_pop_test(); + +#endif diff --git a/test/stack_test.c b/test/stack_test.c new file mode 100644 index 0000000..452a530 --- /dev/null +++ b/test/stack_test.c @@ -0,0 +1,44 @@ +#include "stack_test.h" + +#include +#include +#include + +#include "libcproject.h" + +void stack_test() { + stack_initialization_test(); + stack_push_test(); + stack_pop_test(); +} + +void stack_initialization_test() { + struct stack *stack = stack_initialization(); + assert(stack->length == 0); + assert(stack->first == NULL); +} + +void stack_push_test() { + struct stack *stack = stack_initialization(); + stack_push(stack, (void *)4); + stack_push(stack, (void *)8); + stack_push(stack, (void *)15); + assert(stack->length == 3); + assert(((uintptr_t)stack->first->data) == 15); + assert(((uintptr_t)stack->first->next->data) == 8); + assert(((uintptr_t)stack->first->next->next->data) == 4); + assert(stack->first->next->next->next == NULL); +} + +void stack_pop_test() { + struct stack *stack = stack_initialization(); + stack_push(stack, (void *)4); + stack_push(stack, (void *)8); + stack_push(stack, (void *)15); + void *node = stack_pop(stack); + assert(stack->length == 2); + assert(((uintptr_t)node) == 15); + assert(((uintptr_t)stack->first->data) == 8); + assert(((uintptr_t)stack->first->next->data) == 4); + assert(stack->first->next->next == NULL); +} diff --git a/test/stack_test.h b/test/stack_test.h new file mode 100644 index 0000000..a9ad712 --- /dev/null +++ b/test/stack_test.h @@ -0,0 +1,12 @@ +#ifndef __STACK_TEST__ +#define __STACK_TEST__ + +void stack_test(); + +void stack_initialization_test(); + +void stack_push_test(); + +void stack_pop_test(); + +#endif diff --git a/test/string_test.c b/test/string_test.c new file mode 100644 index 0000000..5fb08ae --- /dev/null +++ b/test/string_test.c @@ -0,0 +1,222 @@ +#include "string_test.h" + +#include +#include +#include + +#include "libcproject.h" +#include "test.h" + +void string_test() { + string_get_length_test(); + string_to_uppercase_test(); + string_to_lowercase_test(); + string_replace_test(); + string_trim_start_test(); + string_trim_end_test(); + string_trim_test(); + string_copy_test(); + string_capitalize_test(); + string_total_occurrences_of_character_test(); + string_reverse_test(); + string_get_is_equal_test(); + string_get_is_integer_test(); + string_split_test(); + string_join_test(); + string_concatenate_test(); + string_get_has_unique_characters_test(); + string_substring_test(); + string_get_is_substring_test(); + string_get_formatted_number_test(); + string_get_last_occurence_of_character_test(); + string_starts_with_test(); + string_ends_with_test(); +} + +void string_get_length_test() { + char *string = "Hello World!"; + size_t string_length = string_get_length(string); + assert(string_length == 12); +} + +void string_to_uppercase_test() { + char *string = "heLlO world"; + string = string_to_uppercase(string); + assert(assert_string_equal(string, "HELLO WORLD")); +} + +void string_to_lowercase_test() { + char *string = "HellO WoRLd"; + string = string_to_lowercase(string); + assert(assert_string_equal(string, "hello world")); +} + +void string_replace_test() { + char *string = "hello world"; + string = string_replace(string, 'l', 'z'); + assert(assert_string_equal(string, "hezzo worzd")); +} + +void string_trim_start_test() { + char *string = " hello world "; + string = string_trim_start(string); + assert(assert_string_equal(string, "hello world ")); +} + +void string_trim_end_test() { + char *string = " hello world "; + string = string_trim_end(string); + assert(assert_string_equal(string, " hello world")); +} + +void string_trim_test() { + char *string = " hello world "; + string = string_trim(string); + assert(assert_string_equal(string, "hello world")); +} + +void string_copy_test() { + char *string = "hello world"; + char *string2 = string_copy(string); + assert(assert_string_equal(string, string2)); + string2[0] = 'a'; + assert(assert_string_not_equal(string, string2)); + assert(assert_string_equal(string, "hello world")); + assert(assert_string_equal(string2, "aello world")); +} + +void string_capitalize_test() { + char *string = "hello world"; + string = string_capitalize(string); + assert(assert_string_equal(string, "Hello world")); +} + +void string_total_occurrences_of_character_test() { + char *string = "hello world"; + assert(string_total_occurrences_of_character(string, 'l') == 3); +} + +void string_reverse_test() { + char *string = "hello world"; + string = string_reverse(string); + assert(assert_string_equal(string, "dlrow olleh")); +} + +void string_get_is_equal_test() { + char *string1 = "hello world"; + char *string2 = "dlrow olleh"; + char *string3 = "dlrow olleh"; + assert(!string_get_is_equal(string1, string2)); + assert(string_get_is_equal(string1, string1)); + assert(string_get_is_equal(string2, string3)); +} + +void string_get_is_integer_test() { + assert(string_get_is_integer("1")); + assert(string_get_is_integer("12")); + assert(string_get_is_integer("-12")); + assert(!string_get_is_integer("1 000")); + assert(!string_get_is_integer("abc")); + assert(!string_get_is_integer("- 12")); + assert(!string_get_is_integer(" -12")); + assert(!string_get_is_integer("-12 ")); + assert(!string_get_is_integer("-")); +} + +void string_split_test() { + char *string = "abc def ghij kl"; + size_t result_length = 0; + char **result = string_split(string, ' ', &result_length); + assert(result_length == 4); + assert(assert_string_equal(result[0], "abc")); + assert(assert_string_equal(result[1], "def")); + assert(assert_string_equal(result[2], "ghij")); + assert(assert_string_equal(result[3], "kl")); +} + +void string_join_test() { + char *string = "abc def ghij kl"; + size_t result_length = 0; + char **result = string_split(string, ' ', &result_length); + char *new_string = string_join(result, ' ', result_length); + char *new_string2 = string_join(result, '+', result_length); + assert(assert_string_equal(new_string, string)); + assert(assert_string_equal(new_string2, "abc+def+ghij+kl")); +} + +void string_concatenate_test() { + assert(assert_string_equal(string_concatenate("abc", "def"), "abcdef")); + assert(assert_string_equal(string_concatenate("abc ", " defghi"), "abc defghi")); +} + +void string_get_has_unique_characters_test() { + assert(string_get_has_unique_characters("ABCDEF")); + assert(!string_get_has_unique_characters("AAABCDEF")); + assert(!string_get_has_unique_characters("AaaBCDEF")); +} + +void string_substring_test() { + char *string = "abcdef"; + char *substring = string_substring(string, 1, 3); + assert(assert_string_equal(substring, "bcd")); +} + +void string_get_is_substring_test() { + char *string = "abcdef"; + assert(string_get_is_substring(string, "abc")); + assert(string_get_is_substring(string, "bcd")); + assert(string_get_is_substring(string, "de")); + assert(string_get_is_substring(string, "f")); + assert(!string_get_is_substring(string, "af")); + assert(string_get_is_substring("3662277", "2277")); + assert(string_get_is_substring("3662277", "62")); + assert(!string_get_is_substring("3662277", "322")); +} + +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")); +} + +void string_get_last_occurence_of_character_test() { + char *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")); +} + +void string_starts_with_test() { + assert(string_starts_with("abcdef", "abc")); + assert(!string_starts_with("abcdef", "bcd")); + assert(!string_starts_with("abcdef", "def")); + assert(!string_starts_with("abcdef", "ef")); + assert(!string_starts_with("abcdef", "f")); + assert(!string_starts_with("abcdef", "abcdefg")); +} + +void string_ends_with_test() { + assert(string_ends_with("abcdef", "def")); + assert(string_ends_with("abcdef", "ef")); + assert(string_ends_with("abcdef", "f")); + assert(!string_ends_with("abcdef", "abc")); + assert(!string_ends_with("abcdef", "bcd")); + assert(!string_ends_with("abcdef", "abcdefg")); +} diff --git a/test/string_test.h b/test/string_test.h new file mode 100644 index 0000000..8535501 --- /dev/null +++ b/test/string_test.h @@ -0,0 +1,52 @@ +#ifndef __STRING_TEST__ +#define __STRING_TEST__ + +void string_test(); + +void string_get_length_test(); + +void string_to_uppercase_test(); + +void string_to_lowercase_test(); + +void string_replace_test(); + +void string_trim_start_test(); + +void string_trim_end_test(); + +void string_trim_test(); + +void string_copy_test(); + +void string_capitalize_test(); + +void string_total_occurrences_of_character_test(); + +void string_reverse_test(); + +void string_get_is_equal_test(); + +void string_get_is_integer_test(); + +void string_split_test(); + +void string_join_test(); + +void string_concatenate_test(); + +void string_get_has_unique_characters_test(); + +void string_substring_test(); + +void string_get_is_substring_test(); + +void string_get_formatted_number_test(); + +void string_get_last_occurence_of_character_test(); + +void string_starts_with_test(); + +void string_ends_with_test(); + +#endif diff --git a/test/test.c b/test/test.c new file mode 100644 index 0000000..824b60f --- /dev/null +++ b/test/test.c @@ -0,0 +1,19 @@ +#include +#include +#include + +bool assert_string_equal(const char *actual, const char *expected) { + if (strcmp(expected, actual) != 0) { + printf("FAIL: expected = \"%s\" ; actual = \"%s\"\n", expected, actual); + return false; + } + return true; +} + +bool assert_string_not_equal(const char *actual, const char *expected) { + if (strcmp(expected, actual) == 0) { + printf("FAIL: expected = \"%s\" ; actual = \"%s\"\n", expected, actual); + return false; + } + return true; +} diff --git a/test/test.h b/test/test.h new file mode 100644 index 0000000..decaa60 --- /dev/null +++ b/test/test.h @@ -0,0 +1,10 @@ +#ifndef __TEST__ +#define __TEST__ + +#include + +bool assert_string_equal(const char *actual, const char *expected); + +bool assert_string_not_equal(const char *actual, const char *expected); + +#endif