Merge pull request 'add Q33 but not fulfilled' (#5) from developed_in_2024_12_18 into main
Reviewed-on: https://external.feng-arch.cn:35127/fengqi/ysyx/pulls/5
This commit is contained in:
commit
69528f7dab
0
pre-study_phase/2024_12_18/Q33/LICENSE
Normal file
0
pre-study_phase/2024_12_18/Q33/LICENSE
Normal file
61
pre-study_phase/2024_12_18/Q33/Makefile
Normal file
61
pre-study_phase/2024_12_18/Q33/Makefile
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
CFLAGS=-g -O2 -Wall -Wextra -Isrc -rdynamic -DNDEBUG $(OPTFLAGS)
|
||||||
|
LIBS=-ldl $(OPTLIBS)
|
||||||
|
PREFIX?=/usr/local
|
||||||
|
|
||||||
|
SOURCES=$(wildcard src/**/*.c src/*.c)
|
||||||
|
OBJECTS=$(patsubst %.c,%.o,$(SOURCES))
|
||||||
|
|
||||||
|
TEST_SRC=$(wildcard tests/*_tests.c)
|
||||||
|
TESTS=$(patsubst %.c,%,$(TEST_SRC))
|
||||||
|
|
||||||
|
TARGET=build/libYOUR_LIBRARY.a
|
||||||
|
SO_TARGET=$(patsubst %.a,%.so,$(TARGET))
|
||||||
|
|
||||||
|
# The Target Build
|
||||||
|
all: $(TARGET) $(SO_TARGET) tests
|
||||||
|
|
||||||
|
dev: CFLAGS=-g -Wall -Isrc -Wall -Wextra $(OPTFLAGS)
|
||||||
|
dev: all
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
$(TARGET): CFLAGS += -fPIC
|
||||||
|
$(TARGET): build $(OBJECTS)
|
||||||
|
ar rcs $@ $(OBJECTS)
|
||||||
|
ranlib $@
|
||||||
|
|
||||||
|
$(SO_TARGET): $(TARGET) $(OBJECTS)
|
||||||
|
$(CC) -shared -o $@ $(OBJECTS)
|
||||||
|
|
||||||
|
build:
|
||||||
|
@mkdir -p build
|
||||||
|
@mkdir -p bin
|
||||||
|
|
||||||
|
# The Unit Tests
|
||||||
|
.PHONY: tests
|
||||||
|
$(TESTS): %: %.c $(TARGET)
|
||||||
|
$(CC) $(CFLAGS) $< -o $@.out $(TARGET) $(LIBS)
|
||||||
|
tests: $(TESTS)
|
||||||
|
sh ./tests/runtests.sh
|
||||||
|
|
||||||
|
valgrind:
|
||||||
|
VALGRIND="valgrind --log-file=/tmp/valgrind-%p.log" $(MAKE)
|
||||||
|
|
||||||
|
# The Cleaner
|
||||||
|
clean:
|
||||||
|
rm -rf build $(OBJECTS) $(TESTS)
|
||||||
|
rm -f tests/tests.log
|
||||||
|
find . -name "*.gc*" -exec rm {} \;
|
||||||
|
find . -name "*.out*" -exec rm {} \;
|
||||||
|
rm -rf `find . -name "*.dSYM" -print`
|
||||||
|
|
||||||
|
# The Install
|
||||||
|
install: all
|
||||||
|
install -d $(DESTDIR)/$(PREFIX)/lib/
|
||||||
|
install $(TARGET) $(DESTDIR)/$(PREFIX)/lib/
|
||||||
|
|
||||||
|
# The Checker
|
||||||
|
BADFUNCS='[^_.>a-zA-Z0-9](str(n?cpy|n?cat|xfrm|n?dup|str|pbrk|tok|_)|stpn?cpy|a?sn?printf|byte_)'
|
||||||
|
check:
|
||||||
|
@echo Files with potentially dangerous functions.
|
||||||
|
@egrep $(BADFUNCS) $(SOURCES) || true
|
||||||
45
pre-study_phase/2024_12_18/Q33/src/lcthw/dbg.h
Normal file
45
pre-study_phase/2024_12_18/Q33/src/lcthw/dbg.h
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
#ifndef _dbg_h_
|
||||||
|
#define _dbg_h_
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
#ifdef NDEBUG
|
||||||
|
#define debug(M, ...)
|
||||||
|
#else
|
||||||
|
#define debug(M, ...) fprintf(stderr, "DEBUG %s:%d:" M "\n", __FILE__, __LINE__, ##__VA_ARGS__)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define clean_errno() (errno == 0 ? "None" : strerror(errno))
|
||||||
|
|
||||||
|
#define log_err(M, ...) fprintf(stderr, "[ERROR] (%s:%d: errno: %s) " M "\n", __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__)
|
||||||
|
|
||||||
|
#define log_warn(M, ...) fprintf(stderr, "[WARN] (%s:%d: errno: %s) " M "\n", __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__)
|
||||||
|
|
||||||
|
#define log_info(M, ...) fprintf(stderr, "[INFO] (%s:%d) " M "\n", __FILE__, __LINE__, ##__VA_ARGS__)
|
||||||
|
|
||||||
|
#define check(A, M, ...) \
|
||||||
|
if (!(A)) \
|
||||||
|
{ \
|
||||||
|
log_err(M, ##__VA_ARGS__); \
|
||||||
|
errno = 0; \
|
||||||
|
goto error; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define sentinel(M, ...) \
|
||||||
|
{ \
|
||||||
|
log_err(M, ##__VA_ARGS__); \
|
||||||
|
errno = 0; \
|
||||||
|
goto error; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define check_mem(A) check((A), "Out of memory.")
|
||||||
|
|
||||||
|
#define check_debug(A, M, ...) \
|
||||||
|
if (!(A)) \
|
||||||
|
{ \
|
||||||
|
debug(M, ##__VA_ARGS__); \
|
||||||
|
errno = 0; \
|
||||||
|
goto error; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
125
pre-study_phase/2024_12_18/Q33/src/lcthw/list.c
Normal file
125
pre-study_phase/2024_12_18/Q33/src/lcthw/list.c
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
#include "list.h"
|
||||||
|
#include "dbg.h"
|
||||||
|
|
||||||
|
List *List_create()
|
||||||
|
{
|
||||||
|
return calloc(1, sizeof(List));
|
||||||
|
}
|
||||||
|
|
||||||
|
void List_destroy(List *list)
|
||||||
|
{
|
||||||
|
LIST_FOREACH(list, first, next, cur)
|
||||||
|
{
|
||||||
|
if (cur->prev)
|
||||||
|
{
|
||||||
|
free(cur->prev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(list->last);
|
||||||
|
free(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
void List_clear_destroy(List *list)
|
||||||
|
{
|
||||||
|
List_clear(list);
|
||||||
|
List_destroy(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
void List_clear(List *list)
|
||||||
|
{
|
||||||
|
LIST_FOREACH(list, first, next, cur)
|
||||||
|
{
|
||||||
|
free(cur->value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void List_push(List *list, void *value)
|
||||||
|
{
|
||||||
|
ListNode *node = calloc(1, sizeof(ListNode));
|
||||||
|
check_mem(node);
|
||||||
|
node->value = value;
|
||||||
|
if (list->last == NULL)
|
||||||
|
{
|
||||||
|
list->first = node;
|
||||||
|
list->last = node;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
list->last->next = node;
|
||||||
|
node->prev = list->last;
|
||||||
|
list->last = node;
|
||||||
|
}
|
||||||
|
list->count++;
|
||||||
|
|
||||||
|
error:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *List_pop(List *list)
|
||||||
|
{
|
||||||
|
ListNode *node = list->last;
|
||||||
|
return node != NULL ? List_remove(list, node) : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void List_unshift(List *list, void *value)
|
||||||
|
{
|
||||||
|
ListNode *node = calloc(1, sizeof(ListNode));
|
||||||
|
check_mem(node);
|
||||||
|
node->value = value;
|
||||||
|
if (list->first == NULL)
|
||||||
|
{
|
||||||
|
list->first = node;
|
||||||
|
list->last = node;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
node->next = list->first;
|
||||||
|
list->first->prev = node;
|
||||||
|
list->first = node;
|
||||||
|
}
|
||||||
|
list->count++;
|
||||||
|
error:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *List_shift(List *list)
|
||||||
|
{
|
||||||
|
ListNode *node = list->first;
|
||||||
|
return node != NULL ? List_remove(list, node) : NULL;
|
||||||
|
}
|
||||||
|
void *List_remove(List *list, ListNode *node)
|
||||||
|
{
|
||||||
|
void *result = NULL;
|
||||||
|
check(list->first && list->last, "List is empty.");
|
||||||
|
check(node, "node can't be NULL");
|
||||||
|
|
||||||
|
if (node == list->first && node == list->last)
|
||||||
|
{
|
||||||
|
list->first = NULL;
|
||||||
|
list->last = NULL;
|
||||||
|
}
|
||||||
|
else if (node == list->first)
|
||||||
|
{
|
||||||
|
list->first = node->next;
|
||||||
|
check(list->first != NULL, "Invalid list, somehow got a first that is NULL.");
|
||||||
|
list->first->prev = NULL;
|
||||||
|
}
|
||||||
|
else if (node == list->last)
|
||||||
|
{
|
||||||
|
list->last = node->prev;
|
||||||
|
check(list->last != NULL, "Invalid list, somehow got a next that is NULL.");
|
||||||
|
list->last->next = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ListNode *after = node->next;
|
||||||
|
ListNode *before = node->prev;
|
||||||
|
before->next = after;
|
||||||
|
after->prev = before;
|
||||||
|
}
|
||||||
|
list->count--;
|
||||||
|
result = node->value;
|
||||||
|
free(node);
|
||||||
|
error:
|
||||||
|
return result;
|
||||||
|
}
|
||||||
41
pre-study_phase/2024_12_18/Q33/src/lcthw/list.h
Normal file
41
pre-study_phase/2024_12_18/Q33/src/lcthw/list.h
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
#ifndef lcthw_List_h
|
||||||
|
#define lcthw_List_h
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
typedef struct ListNode
|
||||||
|
{
|
||||||
|
struct ListNode *next;
|
||||||
|
struct ListNode *prev;
|
||||||
|
void *value;
|
||||||
|
} ListNode;
|
||||||
|
|
||||||
|
typedef struct List
|
||||||
|
{
|
||||||
|
int count;
|
||||||
|
ListNode *first;
|
||||||
|
ListNode *last;
|
||||||
|
} List;
|
||||||
|
|
||||||
|
List *List_create();
|
||||||
|
void List_destroy(List *list);
|
||||||
|
void List_clear(List *list);
|
||||||
|
void List_clear_destroy(List *list);
|
||||||
|
|
||||||
|
#define List_count(A) ((A)->count)
|
||||||
|
#define List_first(A) (((A)->first != NULL) ? ((A)->first->value) : NULL)
|
||||||
|
#define List_last(A) ((A)->last != NULL ? (A)->last->value : NULL)
|
||||||
|
|
||||||
|
void List_push(List *list, void *value);
|
||||||
|
void *List_pop(List *list);
|
||||||
|
|
||||||
|
void List_unshift(List *list, void *value);
|
||||||
|
void *List_shift(List *list);
|
||||||
|
|
||||||
|
void *List_remove(List *list, ListNode *node);
|
||||||
|
|
||||||
|
#define LIST_FOREACH(L, S, M, V) \
|
||||||
|
ListNode *_node = NULL; \
|
||||||
|
ListNode *V = NULL; \
|
||||||
|
for (V = _node = L->S; _node != NULL; V = _node = _node->M)
|
||||||
|
|
||||||
|
#endif
|
||||||
10
pre-study_phase/2024_12_18/Q33/src/lcthw/list_algos.c
Normal file
10
pre-study_phase/2024_12_18/Q33/src/lcthw/list_algos.c
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#include "list_algos.h"
|
||||||
|
#include "dbg.h"
|
||||||
|
|
||||||
|
int List_bubble_sort(List *list, List_compare cmp)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
List *List_merge_sort(List *list, List_compare cmp)
|
||||||
|
{
|
||||||
|
}
|
||||||
12
pre-study_phase/2024_12_18/Q33/src/lcthw/list_algos.h
Normal file
12
pre-study_phase/2024_12_18/Q33/src/lcthw/list_algos.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#ifndef lcthw_List_algos_h
|
||||||
|
#define lcthw_List_algos_h
|
||||||
|
|
||||||
|
#include "list.h"
|
||||||
|
|
||||||
|
typedef int (*List_compare)(const void *a, const void *b);
|
||||||
|
|
||||||
|
int List_bubble_sort(List *list, List_compare cmp);
|
||||||
|
|
||||||
|
List *List_merge_sort(List *list, List_compare cmp);
|
||||||
|
|
||||||
|
#endif
|
||||||
45
pre-study_phase/2024_12_18/Q33/tests/dbg.h
Normal file
45
pre-study_phase/2024_12_18/Q33/tests/dbg.h
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
#ifndef _dbg_h_
|
||||||
|
#define _dbg_h_
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
#ifdef NDEBUG
|
||||||
|
#define debug(M, ...)
|
||||||
|
#else
|
||||||
|
#define debug(M, ...) fprintf(stderr, "DEBUG %s:%d:" M "\n", __FILE__, __LINE__, ##__VA_ARGS__)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define clean_errno() (errno == 0 ? "None" : strerror(errno))
|
||||||
|
|
||||||
|
#define log_err(M, ...) fprintf(stderr, "[ERROR] (%s:%d: errno: %s) " M "\n", __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__)
|
||||||
|
|
||||||
|
#define log_warn(M, ...) fprintf(stderr, "[WARN] (%s:%d: errno: %s) " M "\n", __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__)
|
||||||
|
|
||||||
|
#define log_info(M, ...) fprintf(stderr, "[INFO] (%s:%d) " M "\n", __FILE__, __LINE__, ##__VA_ARGS__)
|
||||||
|
|
||||||
|
#define check(A, M, ...) \
|
||||||
|
if (!(A)) \
|
||||||
|
{ \
|
||||||
|
log_err(M, ##__VA_ARGS__); \
|
||||||
|
errno = 0; \
|
||||||
|
goto error; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define sentinel(M, ...) \
|
||||||
|
{ \
|
||||||
|
log_err(M, ##__VA_ARGS__); \
|
||||||
|
errno = 0; \
|
||||||
|
goto error; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define check_mem(A) check((A), "Out of memory.")
|
||||||
|
|
||||||
|
#define check_debug(A, M, ...) \
|
||||||
|
if (!(A)) \
|
||||||
|
{ \
|
||||||
|
debug(M, ##__VA_ARGS__); \
|
||||||
|
errno = 0; \
|
||||||
|
goto error; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
90
pre-study_phase/2024_12_18/Q33/tests/list_tests.c
Normal file
90
pre-study_phase/2024_12_18/Q33/tests/list_tests.c
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
#include "minunit.h"
|
||||||
|
#include <lcthw/list_algos.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
char *values[] = {"XXXX", "1234", "abcd", "xjvef", "NDSS"};
|
||||||
|
#define NUM_VALUES 5
|
||||||
|
|
||||||
|
List *create_words()
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
List *words = List_create();
|
||||||
|
|
||||||
|
for (i = 0; i < NUM_VALUES; i++)
|
||||||
|
{
|
||||||
|
List_push(words, values[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return words;
|
||||||
|
}
|
||||||
|
|
||||||
|
int is_sorted(List *words)
|
||||||
|
{
|
||||||
|
LIST_FOREACH(words, first, next, cur)
|
||||||
|
{
|
||||||
|
if (cur->next && strcmp(cur->value, cur->next->value) > 0)
|
||||||
|
{
|
||||||
|
debug("%s %s", (char *)cur->value, (char *)cur->next->value);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *test_bubble_sort()
|
||||||
|
{
|
||||||
|
List *words = create_words();
|
||||||
|
|
||||||
|
// should work on a list that needs sorting
|
||||||
|
int rc = List_bubble_sort(words, (List_compare)strcmp);
|
||||||
|
mu_assert(rc == 0, "Bubble sort failed.");
|
||||||
|
mu_assert(is_sorted(words), "Words are not sorted after bubble sort.");
|
||||||
|
|
||||||
|
// should work on an already sorted list
|
||||||
|
rc = List_bubble_sort(words, (List_compare)strcmp);
|
||||||
|
mu_assert(rc == 0, "Bubble sort of already sorted failed.");
|
||||||
|
mu_assert(is_sorted(words), "Words should be sort if already bubble sorted.");
|
||||||
|
|
||||||
|
List_destroy(words);
|
||||||
|
|
||||||
|
// should work on an empty list
|
||||||
|
words = List_create(words);
|
||||||
|
rc = List_bubble_sort(words, (List_compare)strcmp);
|
||||||
|
mu_assert(rc == 0, "Bubble sort failed on empty list.");
|
||||||
|
mu_assert(is_sorted(words), "Words should be sorted if empty.");
|
||||||
|
|
||||||
|
List_destroy(words);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *test_merge_sort()
|
||||||
|
{
|
||||||
|
List *words = create_words();
|
||||||
|
|
||||||
|
// should work on a list that needs sorting
|
||||||
|
List *res = List_merge_sort(words, (List_compare)strcmp);
|
||||||
|
mu_assert(is_sorted(res), "Words are not sorted after merge sort.");
|
||||||
|
|
||||||
|
List *res2 = List_merge_sort(res, (List_compare)strcmp);
|
||||||
|
mu_assert(is_sorted(res), "Should still be sorted after merge sort.");
|
||||||
|
List_destroy(res2);
|
||||||
|
List_destroy(res);
|
||||||
|
|
||||||
|
List_destroy(words);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *all_tests()
|
||||||
|
{
|
||||||
|
mu_suite_start();
|
||||||
|
|
||||||
|
mu_run_test(test_bubble_sort);
|
||||||
|
mu_run_test(test_merge_sort);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
RUN_TESTS(all_tests);
|
||||||
45
pre-study_phase/2024_12_18/Q33/tests/minunit.h
Normal file
45
pre-study_phase/2024_12_18/Q33/tests/minunit.h
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
#undef NDEBUG
|
||||||
|
#ifndef _minunit_h
|
||||||
|
#define _minunit_h
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "dbg.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#define mu_suite_start() char *message = NULL
|
||||||
|
|
||||||
|
#define mu_assert(test, message) \
|
||||||
|
if (!(test)) \
|
||||||
|
{ \
|
||||||
|
log_err(message); \
|
||||||
|
return message; \
|
||||||
|
}
|
||||||
|
#define mu_run_test(test) \
|
||||||
|
debug("\n-----%s", " " #test); \
|
||||||
|
message = test(); \
|
||||||
|
tests_run++; \
|
||||||
|
if (message) \
|
||||||
|
return message;
|
||||||
|
|
||||||
|
#define RUN_TESTS(name) \
|
||||||
|
int main(int argc, char *argv[]) \
|
||||||
|
{ \
|
||||||
|
(void)argc; \
|
||||||
|
debug("----- RUNNING: %s", argv[0]); \
|
||||||
|
printf("----\nRUNNING: %s\n", argv[0]); \
|
||||||
|
char *result = name(); \
|
||||||
|
if (result != 0) \
|
||||||
|
{ \
|
||||||
|
printf("FAILED: %s\n", result); \
|
||||||
|
} \
|
||||||
|
else \
|
||||||
|
{ \
|
||||||
|
printf("ALL TESTS PASSED\n"); \
|
||||||
|
} \
|
||||||
|
printf("Tests run: %d\n", tests_run); \
|
||||||
|
exit(result != 0); \
|
||||||
|
}
|
||||||
|
|
||||||
|
int tests_run;
|
||||||
|
|
||||||
|
#endif
|
||||||
4
pre-study_phase/2024_12_18/Q33/tests/runtests.sh
Normal file
4
pre-study_phase/2024_12_18/Q33/tests/runtests.sh
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
|
||||||
|
cd "$SCRIPT_DIR"
|
||||||
|
./list_tests.out
|
||||||
Loading…
x
Reference in New Issue
Block a user