Skip to content

Commit

Permalink
Adds formation structure as copy of climb structure
Browse files Browse the repository at this point in the history
  • Loading branch information
lgrosz committed Jun 27, 2024
1 parent 4bb3a51 commit 38bcad4
Show file tree
Hide file tree
Showing 5 changed files with 376 additions and 0 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ add_library(grades
grades_hueco.c
grades_font.c
climb.c
formation.c
node.c
graph.c
str_util.c
Expand Down
199 changes: 199 additions & 0 deletions formation.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
#include "formation.h"
#include "str_util.h"
#include <errno.h>
#include <stdlib.h>
#include <string.h>

struct Formation_
{
const char *name;
const char *description;
const char *brief;
const char **aliases;
size_t aliaseslen;
};

static int contains(const char **strs, size_t len, const char *str)
{
for (int i = 0; i < len; i++) {
if (strcmp(strs[i], str) == 0) {
return 1;
}
}

return 0;
}

Formation Formation_new()
{
Formation ret;

if (NULL == (ret = malloc(sizeof(struct Formation_)))) {
errno = ENOMEM;
return NULL;
} else {
ret->name = NULL;
ret->description = NULL;
ret->brief = NULL;
ret->aliases = NULL;
}

Formation_set_name(ret, "");
Formation_set_description(ret, "");
Formation_set_brief(ret, "");

ret->aliaseslen = 0;

errno = 0;
return ret;
}

void Formation_free(Formation formation)
{
if (formation == NULL) {
errno = EINVAL;
return;
}

errno = 0;
if (formation->name) free((void*)formation->name);
if (formation->description) free((void*)formation->description);
if (formation->brief) free((void*)formation->brief);

if (formation->aliases) {
for (int i = 0; i < formation->aliaseslen; i++) {
free((void*)formation->aliases[i]);
}

free(formation->aliases);
}

free(formation);
}

void Formation_set_name(Formation formation, const char *name)
{
free_allocate_and_assign_str(&formation->name, name);
}

const char *Formation_name(Formation formation)
{
return formation->name;
}

void Formation_set_description(Formation formation, const char *description)
{
free_allocate_and_assign_str(&formation->description, description);
}

const char *Formation_description(Formation formation)
{
return formation->description;
}

void Formation_set_brief(Formation formation, const char *description)
{
free_allocate_and_assign_str(&formation->brief, description);
}

const char *Formation_brief(Formation formation)
{
return formation->brief;
}

void Formation_add_alias(Formation formation, const char *alias)
{
if (formation == NULL) {
errno = EINVAL;
return;
}

if (contains(formation->aliases, formation->aliaseslen, alias)) {
return;
}

const char **aliases;
if (NULL == (aliases = malloc((formation->aliaseslen + 1) * sizeof(const char *)))) {
errno = ENOMEM;
return;
}

for (size_t i = 0; i < formation->aliaseslen; ++i) {
aliases[i] = formation->aliases[i];
}

char *new_str;
if (NULL == (new_str = malloc(strlen(alias) + 1))) {
// TODO Cleanup
errno = ENOMEM;
return;
}

strcpy(new_str, alias);

aliases[formation->aliaseslen] = new_str;

if (formation->aliases) {
free(formation->aliases);
}

errno = 0;
formation->aliaseslen = formation->aliaseslen + 1;
formation->aliases = aliases;
}

void Formation_remove_alias(Formation formation, const char *alias)
{
if (formation == NULL) {
errno = EINVAL;
return;
}

size_t index = 0;
int found = 0;

for (index = 0; index < formation->aliaseslen; ++index) {
if (strcmp(formation->aliases[index], alias) == 0) {
found = 1;
break;
}
}

if (!found) {
errno = 0;
return;
}

const char **aliases;
if (NULL == (aliases = malloc((formation->aliaseslen - 1) * sizeof(const char *)))) {
errno = ENOMEM;
return;
}

// Copy elements, skipping the element to remove
for (size_t i = 0, j = 0; i < formation->aliaseslen; ++i) {
if (i != index) {
aliases[j++] = formation->aliases[i];
}
}

if (formation->aliases) {
free((void *)formation->aliases[index]);
free(formation->aliases);
}

errno = 0;
formation->aliaseslen = formation->aliaseslen - 1;
formation->aliases = aliases;
}

const char **Formation_aliases(const Formation formation, size_t *len)
{
if (len == NULL) {
errno = EINVAL;
return NULL;
}

*len = formation->aliaseslen;
return formation->aliases;
}
24 changes: 24 additions & 0 deletions formation.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#ifndef _CLIMBLIB_FORMATION_H_
#define _CLIMBLIB_FORMATION_H_

#include <stddef.h>

typedef struct Formation_* Formation;

Formation Formation_new();
void Formation_free(Formation);

void Formation_set_name(Formation, const char *);
const char *Formation_name(const Formation);

void Formation_set_description(Formation, const char *);
const char *Formation_description(const Formation);

void Formation_set_brief(Formation, const char *);
const char *Formation_brief(const Formation);

void Formation_add_alias(Formation, const char *);
void Formation_remove_alias(Formation, const char *);
const char **Formation_aliases(const Formation, size_t *);

#endif
1 change: 1 addition & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ set(TestSources
font.c
hueco.c
climb.c
formation.c
graph.c
)

Expand Down
151 changes: 151 additions & 0 deletions tests/formation.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "verify.h"

#include <formation.h>

static void test_free_null()
{
Formation_free(NULL);
VERIFY(errno == EINVAL);
}

static void test_new()
{
Formation c = Formation_new();
VERIFY(errno == 0);
VERIFY(c != NULL);

Formation_free(c);
VERIFY(errno == 0);
}

static void test_name()
{
Formation c = Formation_new();
VERIFY(errno == 0);
VERIFY(c != NULL);

VERIFY(strcmp(Formation_name(c), "") == 0);

char name[] = "A Formation Name";
Formation_set_name(c, name);
VERIFY(errno == 0);
VERIFY(strcmp(Formation_name(c), name) == 0);

Formation_set_name(c, "");
VERIFY(errno == 0);
VERIFY(strcmp(Formation_name(c), "") == 0);

Formation_free(c);
VERIFY(errno == 0);
}

static void test_description()
{
Formation c = Formation_new();
VERIFY(errno == 0);
VERIFY(c != NULL);

VERIFY(strcmp(Formation_description(c), "") == 0);

char description[] = "A formation description...\nAnother line...";
Formation_set_description(c, description);
VERIFY(errno == 0);
VERIFY(strcmp(Formation_description(c), description) == 0);

Formation_set_description(c, "");
VERIFY(errno == 0);
VERIFY(strcmp(Formation_description(c), "") == 0);

Formation_free(c);
VERIFY(errno == 0);
}

static void test_brief()
{
Formation c = Formation_new();
VERIFY(errno == 0);
VERIFY(c != NULL);

VERIFY(strcmp(Formation_brief(c), "") == 0);

char brief[] = "A formation brief...";
Formation_set_brief(c, brief);
VERIFY(errno == 0);
VERIFY(strcmp(Formation_brief(c), brief) == 0);

Formation_set_brief(c, "");
VERIFY(errno == 0);
VERIFY(strcmp(Formation_brief(c), "") == 0);

Formation_free(c);
VERIFY(errno == 0);
}

static int string_array_contains(const char **arr, unsigned int len, const char *str)
{
for (int i = 0; i < len; i++) {
if (strcmp(arr[i], str) == 0) {
return 1;
}
}

return 0;
}

static void test_aliases()
{
Formation c = Formation_new();
VERIFY(errno == 0);
VERIFY(c != NULL);

char alias1[] = "An alias";
char alias2[] = "Another alias";

Formation_add_alias(c, alias1);
VERIFY(errno == 0);

Formation_add_alias(c, alias2);
VERIFY(errno == 0);

size_t aliaseslen;
const char **aliases = Formation_aliases(c, &aliaseslen);
VERIFY(errno == 0);
VERIFY(aliaseslen == 2);
VERIFY(string_array_contains(aliases, aliaseslen, alias1));
VERIFY(string_array_contains(aliases, aliaseslen, alias2));

Formation_remove_alias(c, alias1);
VERIFY(errno == 0);

aliases = Formation_aliases(c, &aliaseslen);
VERIFY(errno == 0);
VERIFY(aliaseslen == 1);
VERIFY(!string_array_contains(aliases, aliaseslen, alias1));
VERIFY(string_array_contains(aliases, aliaseslen, alias2));

Formation_add_alias(c, alias2);
VERIFY(errno == 0);
Formation_aliases(c, &aliaseslen);
VERIFY(errno == 0);
VERIFY(aliaseslen == 1);

Formation_free(c);
VERIFY(errno == 0);
}

int formation()
{
test_free_null();
test_new();
test_name();
test_description();
test_brief();
test_aliases();

exit(EXIT_SUCCESS);
}

0 comments on commit 38bcad4

Please sign in to comment.