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

chore: initial commit

This commit is contained in:
Divlo 2023-01-05 19:28:05 +01:00
commit 0fa82c5772
No known key found for this signature in database
GPG Key ID: 8F9478F220CE65E9
46 changed files with 2537 additions and 0 deletions

2
.clang-format Normal file
View File

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

7
.gitignore vendored Normal file
View File

@ -0,0 +1,7 @@
build
bin
.vscode
*.out
*.o
*.exe
*.a

21
LICENSE Normal file
View File

@ -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.

37
Makefile Normal file
View File

@ -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

83
README.md Normal file
View File

@ -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 <path-to-libcproject> ./ # copy
# or
ln -s <path-to-libcproject> ./ # symbolic link
```
### Step 4: Create a new C file
```sh
touch main.c
```
```cpp
#include <stdio.h>
#include <stdlib.h>
#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
```

47
lib/character.c Normal file
View File

@ -0,0 +1,47 @@
#include "character.h"
#include <stdbool.h>
#include <stdlib.h>
#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;
}

59
lib/character.h Normal file
View File

@ -0,0 +1,59 @@
#ifndef __CHARACTER__
#define __CHARACTER__
#include <stdbool.h>
#include <stdlib.h>
/**
* @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

109
lib/convert.c Normal file
View File

@ -0,0 +1,109 @@
#include "convert.h"
#include <stdio.h>
#include <stdlib.h>
#include "character.h"
#include "mathematics.h"
#include "stdbool.h"
#include "string.h"
char* convert_character_to_string(const char character) {
char* string = malloc(sizeof(char*) * 2);
if (string == NULL) {
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);
}

20
lib/convert.h Normal file
View File

@ -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

68
lib/dictionary.c Normal file
View File

@ -0,0 +1,68 @@
#include "dictionary.h"
#include <stdlib.h>
#include "string.h"
struct dictionary *dictionary_initialization() {
struct dictionary *dictionary = malloc(sizeof(struct dictionary));
dictionary->items = malloc(sizeof(struct dictionary_item *) * DICTIONARY_INITIAL_CAPACITY);
dictionary->length = 0;
dictionary->capacity = DICTIONARY_INITIAL_CAPACITY;
for (size_t index = 0; index < dictionary->capacity; index++) {
dictionary->items[index] = NULL;
}
return dictionary;
}
void dictionary_add(struct dictionary *dictionary, char *key, void *data) {
if (dictionary->length == dictionary->capacity) {
size_t previous_capacity = dictionary->capacity;
dictionary->capacity += DICTIONARY_INITIAL_CAPACITY;
dictionary->items = realloc(dictionary->items, sizeof(struct dictionary_item *) * dictionary->capacity);
for (size_t index = previous_capacity; index < dictionary->capacity; index++) {
dictionary->items[index] = NULL;
}
}
struct dictionary_item *item = NULL;
for (size_t index = 0; index < dictionary->length && item == NULL; index++) {
if (string_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;
}

34
lib/dictionary.h Normal file
View File

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

57
lib/filesystem.c Normal file
View File

@ -0,0 +1,57 @@
#include "filesystem.h"
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <pwd.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "string.h"
int filesystem_read(char *path, char **file_content, off_t *file_size) {
int file_descriptor = open(path, O_RDONLY);
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";
}

38
lib/filesystem.h Normal file
View File

@ -0,0 +1,38 @@
#ifndef __FILESYSTEM__
#define __FILESYSTEM__
#include <fcntl.h>
/**
* @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

91
lib/linked_list.c Normal file
View File

@ -0,0 +1,91 @@
#include "linked_list.h"
#include <stdbool.h>
#include <stdlib.h>
#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;
}
}

30
lib/linked_list.h Normal file
View File

@ -0,0 +1,30 @@
#ifndef __LINKED_LIST__
#define __LINKED_LIST__
#include <stdlib.h>
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

36
lib/mathematics.c Normal file
View File

@ -0,0 +1,36 @@
#include "mathematics.h"
#include <stdbool.h>
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);
}

27
lib/mathematics.h Normal file
View File

@ -0,0 +1,27 @@
#ifndef __MATHEMATICS__
#define __MATHEMATICS__
#define MATHEMATICS_FLOAT_PRECISION 0.00000001
#include <stdbool.h>
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

48
lib/queue.c Normal file
View File

@ -0,0 +1,48 @@
#include "queue.h"
#include <stdio.h>
#include <stdlib.h>
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;
}

23
lib/queue.h Normal file
View File

@ -0,0 +1,23 @@
#ifndef __QUEUE__
#define __QUEUE__
#include <stdlib.h>
// 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

40
lib/stack.c Normal file
View File

@ -0,0 +1,40 @@
#include "stack.h"
#include <stdio.h>
#include <stdlib.h>
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;
}

23
lib/stack.h Normal file
View File

@ -0,0 +1,23 @@
#ifndef __STACK__
#define __STACK__
#include <stdlib.h>
// 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

363
lib/string.c Normal file
View File

@ -0,0 +1,363 @@
#include "string.h"
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include "character.h"
#include "convert.h"
#include "dictionary.h"
size_t string_get_length(const char* string) {
size_t length = 0;
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;
}

204
lib/string.h Normal file
View File

@ -0,0 +1,204 @@
#ifndef __STRING__
#define __STRING__
#include <stdbool.h>
#include <stdlib.h>
/**
* @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

122
lib/terminal.c Normal file
View File

@ -0,0 +1,122 @@
#include "terminal.h"
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "character.h"
#include "dictionary.h"
#include "linked_list.h"
#include "queue.h"
#include "stack.h"
char* terminal_input() {
char character;
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");
}

38
lib/terminal.h Normal file
View File

@ -0,0 +1,38 @@
#ifndef __TERMINAL__
#define __TERMINAL__
#include <stdlib.h>
#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

15
libcproject.h Normal file
View File

@ -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

11
main.c Normal file
View File

@ -0,0 +1,11 @@
#include <stdio.h>
#include <stdlib.h>
#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;
}

73
test/character_test.c Normal file
View File

@ -0,0 +1,73 @@
#include "character_test.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#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);
}

18
test/character_test.h Normal file
View File

@ -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

102
test/convert_test.c Normal file
View File

@ -0,0 +1,102 @@
#include "convert_test.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#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"));
}

18
test/convert_test.h Normal file
View File

@ -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

33
test/dictionary_test.c Normal file
View File

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

6
test/dictionary_test.h Normal file
View File

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

99
test/linked_list_test.c Normal file
View File

@ -0,0 +1,99 @@
#include "linked_list_test.h"
#include <assert.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#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');
}

18
test/linked_list_test.h Normal file
View File

@ -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

24
test/main.c Normal file
View File

@ -0,0 +1,24 @@
#include <stdio.h>
#include <stdlib.h>
#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;
}

62
test/mathematics_test.c Normal file
View File

@ -0,0 +1,62 @@
#include "mathematics_test.h"
#include <assert.h>
#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);
}

16
test/mathematics_test.h Normal file
View File

@ -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

44
test/queue_test.c Normal file
View File

@ -0,0 +1,44 @@
#include "queue_test.h"
#include <assert.h>
#include <stdint.h>
#include <stdlib.h>
#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);
}

12
test/queue_test.h Normal file
View File

@ -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

44
test/stack_test.c Normal file
View File

@ -0,0 +1,44 @@
#include "stack_test.h"
#include <assert.h>
#include <stdint.h>
#include <stdlib.h>
#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);
}

12
test/stack_test.h Normal file
View File

@ -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

222
test/string_test.c Normal file
View File

@ -0,0 +1,222 @@
#include "string_test.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#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"));
}

52
test/string_test.h Normal file
View File

@ -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

19
test/test.c Normal file
View File

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

10
test/test.h Normal file
View File

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