Initial commit

This commit is contained in:
Nathan Fisher 2024-02-05 11:23:45 -05:00
commit 49fdf75c41
11 changed files with 474 additions and 0 deletions

9
.gitignore vendored Normal file
View file

@ -0,0 +1,9 @@
test/output/
test/*
!test/*.c
!test/Makefile
*.o
*.a
*.so
*.so.*
*.core

93
Makefile Normal file
View file

@ -0,0 +1,93 @@
# _,.---._ .-._ .--.-. ,--.--------.
# _,..---._ ,-.' , - `. /==/ \ .-._/==/ //==/, - , -\
# /==/, - \ /==/_, , - \|==|, \/ /, |==\ -\\==\.-. - ,-./
# |==| _ _\==| .=. |==|- \| | \==\- \`--`\==\- \
# |==| .=. |==|_ : ;=: - |==| , | -| `--`-' \==\_ \
# |==|,| | -|==| , '=' |==| - _ | |==|- |
# |==| '=' /\==\ - ,_ /|==| /\ , | |==|, |
# |==|-, _`/ '.='. - .' /==/, | |- | /==/ -/
# `-.`.____.' `--`--'' `--`./ `--` `--`--`
# _ __ ,---. .-._ .=-.-. _,.----.
# .-`.' ,`..--.' \ /==/ \ .-._ /==/_ /.' .' - \
# /==/, - \==\-/\ \ |==|, \/ /, /==|, |/==/ , ,-'
# |==| _ .=. /==/-|_\ | |==|- \| ||==| ||==|- | .
# |==| , '=',\==\, - \ |==| , | -||==|- ||==|_ `-' \
# |==|- '..'/==/ - ,| |==| - _ ||==| ,||==| _ , |
# |==|, | /==/- /\ - \|==| /\ , ||==|- |\==\. /
# /==/ - | \==\ _.\=\.-'/==/, | |- |/==/. / `-.`.___.-'
# `--`---' `--` `--`./ `--``--`-`
#
# @(#)Copyright (c) 2024, Nathan D. Fisher.
#
# This is free software. It comes with NO WARRANTY.
# Permission to use, modify and distribute this source code
# is granted subject to the following conditions.
# 1/ that the above copyright notice and this notice
# are preserved in all copies and that due credit be given
# to the author.
# 2/ that any changes to this code are clearly commented
# as such so that the author does not get blamed for bugs
# other than his own.
#
include config.mk
.SUFFIXES:
.SUFFIXES: .o .c
libname = epoch
CFLAGS += -Wall -Werror
CFLAGS += -Iinclude
CFLAGS += -fPIC
hdrs += include/epoch.h
srcs += epoch.c
srcs += month.c
srcs += weekday.c
srcs += year.c
srcs += zone.c
objs = $(srcs:.c=.o)
all: shared static
shared: lib$(libname).so
static: lib$(libname).a
$(srcs): $(hdrs)
lib$(libname).a: $(objs)
$(AR) rcs $@ $?
lib$(libname).so: $(objs)
$(CC) -shared -o $@ $? $(LIBS)
install: install_include install_shared install_static
install_include: include/$(libname).h
@[ -d $(includedir) ] || install -d $(includedir)
install -m644 include/$(libname).h $(includedir)/
install_static: lib$(libname).a
@[ -d $(libdir) ] || install -d $(libdir)
install -m644 lib$(libname) $(libdir)/
install_shared: lib$(libname).so
@[ -d $(libdir) ] || install -d $(libdir)
install -m755 lib$(libname).so $(libdir)/
test: lib$(libname).a
$(MAKE) -C test
testclean:
$(MAKE) -C test clean
clean:
rm -rf *.a *.so *.o haggis
$(MAKE) -C test clean
.PHONY: all shared static clean install install_include install_static \
install_shared testclean test

3
compile_flags.txt Normal file
View file

@ -0,0 +1,3 @@
-I
include

0
config.mk Normal file
View file

0
epoch.c Normal file
View file

88
include/epoch.h Normal file
View file

@ -0,0 +1,88 @@
#ifndef LIBEPOCH_H
#define LIBEPOCH_H 1
#include <stdint.h>
#define SECONDS_PER_MINUTE 60
#define SECONDS_PER_HOUR 60 * 60
#define SECONDS_PER_DAY 60 * 60 * 24
typedef enum {
normalYear,
leapYear,
} yearTag;
typedef struct {
yearTag tag;
uint32_t year;
} Year;
typedef enum {
January = 1,
February = 2,
March = 3,
April = 4,
May = 5,
June = 6,
July = 7,
August = 8,
September = 9,
October = 10,
November = 11,
December = 12,
} Month;
typedef enum {
Thursday = 0,
Friday = 1,
Saturday = 2,
Sunday = 3,
Monday = 4,
Tuesday = 5,
Wednesday = 6,
} Weekday;
typedef enum {
Offset,
UTC,
} timeZoneTag;
typedef enum {
Positive,
Negative,
} offsetSign;
typedef struct {
offsetSign sign;
uint8_t hours;
uint8_t minutes;
} TzOffset;
typedef struct {
timeZoneTag tag;
TzOffset *offset;
} TimeZone;
void yearNew(Year *year, int32_t inner);
uint16_t yearGetDays(Year *year);
int64_t yearGetSeconds(Year *year);
int32_t yearGetInner(Year *year);
void yearIncrement(Year *year);
void yearDecrement(Year *year);
uint8_t monthGetDays(Month month, Year *year);
uint32_t monthGetSeconds(Month month, Year *year);
int monthIncrement(Month *month);
int monthDecrement(Month *month);
const char* monthName(Month month);
const char* monthAbbr(Month month);
int parseMonth(const char *s);
const char* weekdayName(Weekday day);
const char* weekdayAbbr(Weekday day);
int parseWeekday(const char *s);
int offsetNew(TzOffset *offs, offsetSign sign, uint8_t hours, uint8_t minutes);
void printTz(TimeZone *zone);
#endif // !LIBEPOCH_H

69
month.c Normal file
View file

@ -0,0 +1,69 @@
#include <stdint.h>
#include <stddef.h> // NULL
#include <string.h> // memcmp
#include <strings.h>
#include "epoch.h"
uint8_t monthGetDays(Month month, Year *year) {
switch (month) {
case January:
case March:
case May:
case July:
case August:
case October:
case December:
return 31;
case February:
switch (year->tag) {
case leapYear:
return 28;
default:
return 29;
}
default:
return 30;
}
}
uint32_t monthGetSeconds(Month month, Year *year) {
return (int64_t)monthGetDays(month, year) * SECONDS_PER_DAY;
}
int monthIncrement(Month *month) {
if (*month == December)
return 1;
else
*month += 1;
return 0;
}
int monthDecrement(Month *month) {
if (*month == January)
return 1;
else
*month -= 1;
return 0;
}
const char *MonthNames[] = { "January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December" };
const char *MonthAbbrs[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
"Aug", "Sep", "Oct", "Nov", "Dec" };
const char* monthName(Month month) {
return MonthNames[month - 1];
}
const char* monthAbbr(Month month) {
return MonthAbbrs[month - 1];
}
int parseMonth(const char *s) {
int i;
for (i = 0; i < 12; i++) {
if (strncasecmp(s, MonthAbbrs[i], 4) == 0 || strncasecmp(s, MonthNames[i], 10) == 0)
return i + 1;
}
return -1;
}

110
test/Makefile Normal file
View file

@ -0,0 +1,110 @@
# _,.---._ .-._ .--.-. ,--.--------.
# _,..---._ ,-.' , - `. /==/ \ .-._/==/ //==/, - , -\
# /==/, - \ /==/_, , - \|==|, \/ /, |==\ -\\==\.-. - ,-./
# |==| _ _\==| .=. |==|- \| | \==\- \`--`\==\- \
# |==| .=. |==|_ : ;=: - |==| , | -| `--`-' \==\_ \
# |==|,| | -|==| , '=' |==| - _ | |==|- |
# |==| '=' /\==\ - ,_ /|==| /\ , | |==|, |
# |==|-, _`/ '.='. - .' /==/, | |- | /==/ -/
# `-.`.____.' `--`--'' `--`./ `--` `--`--`
# _ __ ,---. .-._ .=-.-. _,.----.
# .-`.' ,`..--.' \ /==/ \ .-._ /==/_ /.' .' - \
# /==/, - \==\-/\ \ |==|, \/ /, /==|, |/==/ , ,-'
# |==| _ .=. /==/-|_\ | |==|- \| ||==| ||==|- | .
# |==| , '=',\==\, - \ |==| , | -||==|- ||==|_ `-' \
# |==|- '..'/==/ - ,| |==| - _ ||==| ,||==| _ , |
# |==|, | /==/- /\ - \|==| /\ , ||==|- |\==\. /
# /==/ - | \==\ _.\=\.-'/==/, | |- |/==/. / `-.`.___.-'
# `--`---' `--` `--`./ `--``--`-`
#
# @(#)Copyright (c) 2023, Nathan D. Fisher.
#
# This is free software. It comes with NO WARRANTY.
# Permission to use, modify and distribute this source code
# is granted subject to the following conditions.
# 1/ that the above copyright notice and this notice
# are preserved in all copies and that due credit be given
# to the author.
# 2/ that any changes to this code are clearly commented
# as such so that the author does not get blamed for bugs
# other than his own.
#
include ../config.mk
CFLAGS += -I../include
LDLIBS += ../libhaggis.a
LDLIBS += $(LIBS)
tests += store_u16
tests += load_u16
tests += store_u32
tests += load_u32
tests += store_u64
tests += load_u64
tests += store_header
tests += check_header
tests += store_device
tests += load_device
tests += store_md5
tests += load_md5
tests += store_sha1
tests += load_sha1
tests += store_sha256
tests += load_sha256
tests += init_file_md5
tests += init_file_sha1
tests += init_file_sha256
tests += store_file_md5
tests += load_file_md5
tests += store_file_sha1
tests += load_file_sha1
tests += store_file_sha256
tests += load_file_sha256
tests += fnv1a_hash_inode
tests += fnv1a_hash_str
tests += linkmap_init
tests += linkmap_put
tests += create_dir_node
tests += create_symlink_node
tests += create_fifo_node
tests += create_dev_node
tests += create_file_node
tests += mq_push_pop
tests += extract_dev_node
tests += extract_dir_node
tests += extract_fifo_node
tests += extract_file_node
tests += extract_symlink_node
tests += extract_hardlink_node
total != echo $(tests) | wc -w | awk '{ print $$1 }'
.PHONY: test
test: $(tests) output
@echo -e "\n\t=== \e[0;33mRunning $(total) tests\e[0m ===\n"
@idx=1 ; success=0 ; fail=0; skip=0; for t in $(tests) ; \
do printf "[%02i/$(total)] %-25s" $${idx} $${t} ; \
idx=$$(expr $${idx} + 1) ; \
./$${t} ; \
retval=$$? ; \
if [ $${retval} -eq 0 ] ; \
then echo -e '\e[0;32mSuccess\e[0m' ; \
success=$$(expr $${success} + 1) ; \
elif [ $${retval} -eq 255 ] ; \
then echo Skipped ; \
skip=$$(expr $${skip} + 1) ; \
else echo -e '\e[0;31mFailure\e[0m' ; \
fail=$$(expr $${fail} + 1) ; \
fi ; done || true ; \
if [ $${fail} == 0 ] ; \
then echo -e '\nResults: \e[0;32mOk\e[0m.' "$${success} succeeded; $${fail} failed; $${skip} skipped" ; \
else echo -e '\nResults: \e[0;31mFAILED\e[0m.' "$${success} succeeded; $${fail} failed; $${skip} skipped" ; \
fi
output:
@ [-d $@ ] 2>/dev/null || install -d $@
.PHONY: clean
clean:
rm -rf $(tests) output/*

24
weekday.c Normal file
View file

@ -0,0 +1,24 @@
#include "epoch.h"
#include <strings.h>
const char *WeekdayNames[] = { "Thursday", "Friday", "Saturday", "Sunday", "Monday",
"Tuesday", "Wednesday" };
const char *WeekdayAbbrs[] = { "Thu", "Fri", "Sat", "Sun", "Mon", "Tue", "Wed" };
const char* weekdayName(Weekday day) {
return WeekdayNames[day];
}
const char* weekdayAbbr(Weekday day) {
return WeekdayAbbrs[day];
}
int parseWeekday(const char *s) {
int i;
for (i = 0; i < 7; i++) {
if (strncasecmp(s, WeekdayAbbrs[i], 4) == 0 || strncasecmp(s, WeekdayNames[i], 10) == 0) {
return i;
}
}
return -1;
}

45
year.c Normal file
View file

@ -0,0 +1,45 @@
#include <stdint.h>
#include "epoch.h"
void yearNew(Year *year, int32_t inner) {
year->year = inner;
if (inner % 4 == 0 && (inner % 100 != 0 || inner % 400 == 0))
year->tag = leapYear;
else
year->tag = normalYear;
}
uint16_t yearGetDays(Year *year) {
switch (year->tag) {
case normalYear:
return 365;
case leapYear:
return 366;
default:
return 365;
}
}
int64_t yearGetSeconds(Year *year) {
return (int64_t)yearGetDays(year) * SECONDS_PER_DAY;
}
int32_t yearGetInner(Year *year) {
return year->year;
}
void yearIncrement(Year *year) {
year->year += 1;
if (year->year % 4 == 0 && (year->year % 100 != 0 || year->year % 400 == 0))
year->tag = leapYear;
else
year->tag = normalYear;
}
void yearDecrement(Year *year) {
year->year -= 1;
if (year->year % 4 == 0 && (year->year % 100 != 0 || year->year % 400 == 0))
year->tag = leapYear;
else
year->tag = normalYear;
}

33
zone.c Normal file
View file

@ -0,0 +1,33 @@
#include "epoch.h"
#include <stdio.h>
#include <stdint.h>
#include <string.h>
int offsetNew(TzOffset *offs, offsetSign sign, uint8_t hours, uint8_t minutes) {
if (offs == NULL) return 1;
if (hours > 12) return 2;
if (hours > 11 && minutes > 0) return 3;
if (minutes > 59) return 4;
offs->sign = sign;
offs->hours = hours;
offs->minutes = minutes;
return 0;
}
void printTz(TimeZone *zone) {
switch (zone->tag) {
case UTC: printf("UTC");
case Offset:
switch (zone->offset->sign) {
case Positive:
puts("+");
break;
case Negative:
puts("-");
break;
}
default:
break;
printf("%.2u:%.2u", zone->offset->hours, zone->offset->minutes);
}
}