diff --git a/Array/include/array.h b/Array/include/array.h index 065a85a..99a6d7c 100644 --- a/Array/include/array.h +++ b/Array/include/array.h @@ -26,7 +26,6 @@ Status Array_CopyOf(Array *inst, Array *other); Status Array_Delete(Array *inst); Status Array_GetIdx(Array *inst, Var *store, int index); Status Array_SetIdx(Array *inst, Var *source, int index); -Status Array_Literalise(Array *inst, char const *store); bool Array_Equal(Array *arr1, Array *arr2); /* Extensional. */ diff --git a/Array/src/array.c b/Array/src/array.c index e30c91f..3edf7aa 100644 --- a/Array/src/array.c +++ b/Array/src/array.c @@ -1,4 +1,5 @@ #include +#include Status Array_Create(Array *inst, int len) { @@ -7,77 +8,99 @@ Status Array_Create(Array *inst, int len) state((len < 0), InvalidArrayLength); solve((!len), { inst->len = 0; inst->members = NULL; return NormalStatus; }) - + inst->len = len; + inst->members = calloc(len, sizeof(Var)); } Status Array_CopyOf(Array *inst, Array *other) { /* Skip unavailable inst and invalid param. */ fails(inst, UnavailableInstance); + fails(other, error(InvalidParameter, "Given other was unavailable.")); + /* Assign value for len. */ + inst->len = other->len; + + /* Recreate array. */ + if (inst->members == NULL) return NormalStatus; + match(RuntimeError, Array_Delete(inst), "Failed on deleting array."); + match(RuntimeError, Array_Create(inst, other->len), "Failed on recreating " + "array."); + + /* Copy and assign for each member from other to inst. */ + for (register int i = 0; i < inst->len; i++) { + inst[i] = other[i]; + } + + return NormalStatus; } Status Array_Delete(Array *inst) { /* Skip unavailable inst and invalid param. */ fails(inst, UnavailableInstance); + solve((inst->members == NULL), return NormalStatus); + inst->len = 0; + free(inst->members); + inst->members = NULL; + + return NormalStatus; } Status Array_GetIdx(Array *inst, Var *store, int index) { /* Skip unavailable inst and invalid param. */ fails(inst, UnavailableInstance); + fails(store, error(InvalidParameter, "Given reference to store was " + "unavailable.")); + state((index < 0 || index >= inst->len), ArrayIndexOutOfBound); + *store = inst->members[index]; + + return NormalStatus; } Status Array_SetIdx(Array *inst, Var *source, int index) { /* Skip unavailable inst and invalid param. */ fails(inst, UnavailableInstance); + fails(source, error(InvalidParameter, "Given reference to source was " + "unavailable.")); + state((index < 0 || index >= inst->len), ArrayIndexOutOfBound); + inst->members[index] = *source; + + return NormalStatus; } -Status Array_Literalise(Array *inst, char const *store) +bool Array_Equal(Array *a, Array *b) { /* Skip unavailable inst and invalid param. */ + state((a == NULL || b == NULL), false); + state((a->len != b->len), false); + + for (register int i = 0; i < a->len; i++) { + if (!Var_Equal(&a->members[i], &b->members[i])) { + return false; + } + } + + return true; +} + + + +Status ArrayUtils_Fill(Array *inst, Var *elem, int off, int len) +{ fails(inst, UnavailableInstance); + fails(elem, error(InvalidParameter, "Given reference to elem was unavailable.")); + state((off + len > inst->len) || (off < 0) || (len < 0), ArrayIndexOutOfBound); + /* Copy elem into each specified members from inst with off and len. */ + for (register int i = off; i < (off + len); i++) { + inst->members[i] = *elem; + } + + return NormalStatus; } - -bool Array_Equal(Array *arr1, Array *arr2) -{ - /* Skip unavailable inst and invalid param. */ - state((arr1 == NULL || arr2 == NULL), false); - -} - - - - -// Status Array_Create(Array *inst, int len) -// { -// fails(inst, UnavailableInstance); -// state(len < 0, InvalidArrayLength); - -// Var arr[len] = {}; -// *inst = (Array) { -// .len = len, -// .members = arr -// }; - -// /* Initialise members. */ -// for (register int i = 0; i < inst->len; i++) { -// state(!(StatusUtils_IsOkay(Var_Create(&inst->members[i], NULL, 0, NULL))), -// error(RuntimeError, -// "Failed initialisations on var_create for array_create.")); -// } - -// return NormalStatus; -// } - -// Status Array_Delete(Array *inst); - -// bool ArrayUtils_IsEmpty(Array *inst); - -// bool Array_Equal(Array *arr1, Array *arr2); diff --git a/CMakeLists.txt b/CMakeLists.txt index d15ae8a..9d29751 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,11 +4,16 @@ project (Compound) add_compile_options(-g -std=c99 -Wall -Wextra -Wformat) +# add_executable(CompoundTest test.c +# Var/src/var.c +# Status/src/status.c +# Stack/src/stack.c +# Array/src/array.c +# Utils/src/utils.c +# catlog.c +# name.c) + add_executable(CompoundTest test.c Var/src/var.c - Status/src/status.c - Stack/src/stack.c Array/src/array.c - Utils/src/utils.c - catlog.c - name.c) + Status/src/status.c) diff --git a/Status/include/status.h b/Status/include/status.h index 475f43a..2dce171 100644 --- a/Status/include/status.h +++ b/Status/include/status.h @@ -118,8 +118,8 @@ TIME [PRIORITY] STATUSNAME (ORIGINATOR): STATUS.DESCRIPTION Fri 10 May 03:02:37 CST 2024 [EXCEPTIONAL] InvalidParameter (Nullity): Given buffer was unavailable. - at /external/Documents/Projects/Compound/Status/src/status.c:104, report_literalise - at /external/Documents/Projects/Compound/Status/src/status.c:114, reportsender_send + at /external/Documents/Projects/Compound/Status/src/status.c:104, Report_Literalise + at /external/Documents/Projects/Compound/Status/src/status.c:114, ReportSender_Send at /external/Documents/Projects/Compound/Status/src/status.c:69, _throw !!!!at /external/Documents/Projects/Compound/Array/src/array.c:16, array_create at /external/Documents/Projects/Compound/test.c:24, main @@ -130,10 +130,14 @@ Fri 10 May 03:02:37 CST 2024 [EXCEPTIONAL] InvalidParameter (Nullity): Given buf # define REPORT_LITERALISE_CHAINS_FORMAT " at %s:%d, %s" # define REPORT_LITERALISE_CHAINS_EXCLAIM_FORMAT "!!!!at %s:%d, %s" -# define REPORT_LITERALISE_HEADER_FORMAT_LENGTH(PRIORITY, STATUSNAME, \ +# define REPORT_LITERALISE_HEADER_FORMAT_LENGTH(buff, PRIORITY, STATUSNAME, \ ORIGINATOR, DESCRIPTION) \ - (INT64_DIGITS_DEC + strlen(PRIORITY) + strlen(STATUSNAME) + \ - strlen(ORIGINATOR) + strlen(DESCRIPTION) + 9) // Does not count '\0' +{ \ + const time_t now = time(NULL); \ + (void)strflen(buff, 28, DATETIME_FORMAT, localtime(&now)); \ + *length = strlen(buff); \ +} + # define REPORT_LITERALISE_CHAINS_FORMAT_LENGTH(FILEPATH, LINE, FUNCNAME) \ (strlen(FILEPATH) + utils_calc_digits(LINE) + \ strlen(FUNCNAME) + 10) // Does not count '\0' @@ -197,9 +201,10 @@ typedef struct { # define STATUS_BUFFER_MAXIMUM_LENGTH UINT32_MAX bool Location_Equal(Location lc1, Location lc2); -void Status_Dump(Status stat, Status *statbuff, int idx); bool Status_Equal(Status stat1, Status stat2); -bool StatusUtils_HasPrev(Status stat); +Status Status_Literalise(Status *inst, char *buff); +void StatusUtils_Dump(Status *stat, Status *statbuff, int idx); +bool StatusUtils_HasPrev(Status *stat); bool StatusUtils_IsOkay(Status stat); bool StatusUtils_IsValid(Status stat); bool StatusUtils_IsRecursive(Status stat); @@ -382,6 +387,7 @@ static Status ReportMessageLengthTooLong = { // ======================================================== +/* Throw the report created with $e if $e is abnormal, commented with $c. */ # define ensure(e, c) { \ Status stat = e; \ solve(!(StatusUtils_IsOkay(stat)), { \ @@ -391,6 +397,16 @@ static Status ReportMessageLengthTooLong = { }) \ } +/* Throw the report created with $s if $e is abnormal, commented with $c. */ +# define match(s, e, c) { \ + Status stat = s; \ + solve(!(StatusUtils_IsOkay(e)), { \ + Report rep = stamp(error(stat, c), (char *)__func__); \ + (void)throw(rep); \ + return ReportThrown; \ + }) \ +} + /* Add location parameter requirement in order to give proper information * before throwing the report out. */ # define throw(report) __throw(report, __HERE__) @@ -414,11 +430,11 @@ static int HANDLER(void *report) REPORT_SENDING_PRIORITY_FATAL); /* Perform throwing. */ - (void)_throw(e); // Throw the report alone. + (void)throw(e); // Throw the report alone. return 1; } - (void)_throw(*(Report *)report); // Lonely _throw, no catch will company. + (void)throw(*(Report *)report); // Lonely _throw, no catch will company. return 0; } diff --git a/Status/src/status.c b/Status/src/status.c index 1d08cb6..eeeaa2b 100644 --- a/Status/src/status.c +++ b/Status/src/status.c @@ -1,5 +1,6 @@ #include #include +#include bool status_issuelocation_equal(Location lc1, Location lc2) { return ((!strcmp(lc1.file, lc2.file)) && (lc1.line == lc2.line) && @@ -8,7 +9,7 @@ bool status_issuelocation_equal(Location lc1, Location lc2) { bool status_hasprev(Status stat) { /* Skip when stat is unavailable for accessing. */ - state(status_equal(stat, (Status){}), false); + state(Status_Equal(stat, (Status){}), false); return (stat.prev != NULL); } @@ -24,18 +25,18 @@ bool status_recursive(Status stat) { return (stat.prev != NULL && stat.prev == &stat); } -void status_dump(Status inst, Status *statbuff, int idx) { +void status_dump(Status *inst, Status *statbuff, int idx) { /* Skip when either stat or stat.prev is unavailable, or, idx is invalid. */ - solve((statbuff == NULL || !status_hasprev(inst) || idx < 0), return;); + solve((statbuff == NULL || !status_hasprev(*inst) || idx < 0), return;); - statbuff[idx] = inst; + statbuff[idx] = *inst; (void)printf("status_dump: Index %d has assigned with %p\n", idx, &inst); - status_dump(*inst.prev, statbuff, ++idx); + status_dump(inst->prev, statbuff, ++idx); } -bool status_equal(Status stat1, Status stat2) { +bool Status_Equal(Status stat1, Status stat2) { /* Skip when both stat1 and stat2 are empty. */ state((stat1.value == 0 && stat2.value == 0 && stat1.description == 0x0 && @@ -47,10 +48,15 @@ bool status_equal(Status stat1, Status stat2) { return ((stat1.value == stat2.value) && (!strcmp(stat1.description, stat2.description)) && (stat1.characteristic == stat2.characteristic) && - (status_equal(*stat1.prev, *stat2.prev))); + (Status_Equal(*stat1.prev, *stat2.prev))); } -int status_depth(Status *stat) { +Status Status_Literalise(Status *inst, char *buff) +{ + +} + +int StatusUtils_Depth(Status *stat) { /* Skip unavailable stat. */ state((stat == NULL), -1); @@ -85,16 +91,41 @@ Status report_create(Report *inst, Status *stat, FILE *dest, char *originator, return NormalStatus; } -Status report_literalise(Report *inst, char *buff) { +Status Report_Literalise(Report *inst, char *buff) +{ /* Skip when inst or buff is unavailable. */ fails(inst, UnavailableInstance); fails(buff, error(InvalidParameter, "Given buffer was unavailable.")); - const int depth = status_depth(&inst->stat); - char buff // TODO(william): HERE + /* By calculating the depth of status, we can calculate the exact length of + literalisation of report. */ + const int depth = StatusUtils_Depth(&inst->stat); + + /* Dump all the status. */ + Status stats[depth]; + StatusUtils_Dump(&inst->stat, stats, 0); + + /* Literalise by iterating. */ + int report_literalised_length = 0; + for (register int i = 0; i < depth; i++) { + /* Literalise individual status. */ + char buff[strlen(stats[i].description) + 1 + ]; + (void)Status_Literalise(&stats[i], buff); // Ignore the returning. + // Otherwise, if we throw the report once the returning status is abnormal, + // this function would be called again by the throw function. + + /* Accumulate length of report literalisation. */ + report_literalised_length += strlen(buff); + } + + /* Create report literalisation buffer according to + report_literalised_length. */ + char report_literalised_buffer[report_literalised_length]; + + /* */ } -Status reportsender_create(ReportSender *inst, Report *report) { +Status ReportSender_Create(ReportSender *inst, Report *report) { fails(inst, UnavailableInstance); fails(report, error(UnavailableParameter, "Given report was unavailable.")); @@ -107,7 +138,7 @@ Status reportsender_create(ReportSender *inst, Report *report) { return NormalStatus; } -Status reportsender_send(ReportSender *inst, ReportSendingTask task) { +Status ReportSender_Send(ReportSender *inst, ReportSendingTask task) { /* Skip when inst or task is unavailable. */ fails(inst, error(UnavailableInstance, "Report sender was given unavailable.")); @@ -116,7 +147,7 @@ Status reportsender_send(ReportSender *inst, ReportSendingTask task) { /* Assign for dest. */ const FILE *dest = (inst->report->dest == NULL ? stdout : inst->report->dest); // char buff[]; - // TODO(william): HERE, report_literalise + // TODO(william): HERE, Report_Literalise /* Write/Send data. */ inst->report->status = REPORT_SENDING_TASK_STATUS_PROCEEDING; @@ -138,7 +169,7 @@ Status reportsender_send(ReportSender *inst, ReportSendingTask task) { ReportSendingTaskID _throw(Report report, Location loc) { // /* Create new a instance of ReportSender. */ // ReportSender sender; - // reportsender_create(&sender, stderr); + // ReportSender_Create(&sender, stderr); // /* Send message. */ // /* Initialise sender's thread. */ @@ -157,18 +188,18 @@ ReportSendingTaskID _throw(Report report, Location loc) { // } // /* Perform sending. */ - // reportsender_send(&sender, NULL); + // ReportSender_Send(&sender, NULL); /* Initialise sender. */ ReportSender sender; /* Return with -1 when initialisation failed. */ - state(!(status_isokay(reportsender_create(&sender, &report))), -1); + state(!(status_isokay(ReportSender_Create(&sender, &report))), -1); /* Inject location information. Could be more elegant, though. */ sender.report->stat.loc = loc; /* Send. */ /* Return -1 when failed on sending. */ - state(!status_isokay(reportsender_send(&sender, HANDLER)), -1); + state(!status_isokay(ReportSender_Send(&sender, HANDLER)), -1); } diff --git a/String/include/string.h b/String/include/string.h index fb45682..2a95ead 100644 --- a/String/include/string.h +++ b/String/include/string.h @@ -22,10 +22,6 @@ Status String_Delete(String *inst); Status String_GetIdx(String *inst, Char *item, int index); Status String_SetIdx(String *inst, Char *item, int index); Status String_Literalise(String *inst, String *store); -Status String_Encode(String *inst, StringEncoding encoding) - throws(UnsupportedEncoding EncodingError DecodingError); -Status String_Decode(String *inst, StringEncoding encoding); - throws(UnsupportedEncoding EncodingError DecodingError); bool String_Equal(String *arr1, String *arr2); /* Extensional. */ @@ -80,6 +76,10 @@ Status StringUtils_ToCharBuff(String *inst, char const *buff, int base); Status StringUtils_ToWideCharBuff(String *inst, wchar_t const *wbuff, int base); Status StringUtils_Format(String *inst, const String *__restrict fmt, ...); Status StringUtils_Tokenise(String *inst, const String *delim, String *store); +Status String_Encode(String *inst, StringEncoding encoding) + throws(UnsupportedEncoding EncodingError DecodingError); +Status String_Decode(String *inst, StringEncoding encoding); + throws(UnsupportedEncoding EncodingError DecodingError); int StringUtils_Compare(String *a, String *b); static Status StringConversionPrecisionError = { diff --git a/Utils/include/utils.h b/Utils/include/utils.h index a28fffe..ac4fbff 100644 --- a/Utils/include/utils.h +++ b/Utils/include/utils.h @@ -1,9 +1,16 @@ #ifndef COMPOUND_UTILS_H # define COMPOUND_UTILS_H +# include +# include +# include + # include # include +# define DATETIME_FORMAT "%a %d %b %X %Z %Y" + int Utils_CalcDigits(long long n); +int Utils_CalcDateTimeLiteralisationLength(char *buff); #endif /* COMPOUND_UTILS_H */ diff --git a/Utils/src/utils.c b/Utils/src/utils.c index e33f767..12224f2 100644 --- a/Utils/src/utils.c +++ b/Utils/src/utils.c @@ -14,3 +14,12 @@ int Utils_CalcDigits(long long n) return i; } + +int Utils_CalcDateTimeLiteralisationLength(char *buff) +{ + const time_t now = time(NULL); + + (void)strftime(buff, 28, DATETIME_FORMAT, localtime(&now)); + + return strlen(buff); +} diff --git a/Var/include/var.h b/Var/include/var.h index 9a23f77..56f8dc4 100644 --- a/Var/include/var.h +++ b/Var/include/var.h @@ -45,8 +45,10 @@ typedef struct { Status Var_Create(Var *inst, void *addr, size_t size, char *identity); Status Var_CopyOf(Var *inst, Var *other); +Status Var_Literalise(Var *inst, char *buff); +bool Var_Equal(Var *a, Var *b); void Var_Delete(Var *inst); -Status VarUtils_Literalise(Var *inst, char *buff); + void VarUtils_Swap(Var *v1, Var *v2); bool VarUtils_IsIdentityLegal(char *identity); diff --git a/Var/src/var.c b/Var/src/var.c index 0f680f7..c88afc1 100644 --- a/Var/src/var.c +++ b/Var/src/var.c @@ -50,7 +50,7 @@ void VarUtils_Swap(Var *v1, Var *v2) *v2 = v3; } -Status VarUtils_Literalise(Var *inst, char *buff) +Status Var_Literalise(Var *inst, char *buff) { /* Skip when inst is unavailable. */ state(inst == NULL, UnavailableInstance); @@ -63,6 +63,16 @@ Status VarUtils_Literalise(Var *inst, char *buff) return NormalStatus; } +bool Var_Equal(Var *a, Var *b) +{ + /* Skip unavailable inst and invalid param. */ + state((a == NULL || b == NULL), false); + + return (a->addr == b->addr && + a->size == b->size && + (!strcmp(a->identity, b->identity))); +} + bool VarUtils_IsIdentityLegal(char *identity) { /* Skip when identity is unavailable. */ diff --git a/catlog.c b/catlog.c index ab0e6bf..4515985 100755 --- a/catlog.c +++ b/catlog.c @@ -11,7 +11,7 @@ Status CatlogMsg_Create(CatlogMsg *inst, CatlogLevel level, inst->time = time(NULL); inst->level = level; *inst->originator = *originator; - *inst->msg = *msg; + *inst->content = *msg; return NormalStatus; } @@ -36,7 +36,7 @@ bool CatlogMsg_Equal(CatlogMsg *inst, CatlogMsg *other) inst->time == other->time && inst->level == other->level && (!strcmp(inst->originator, other->originator)) && - (!strcmp(inst->msg, other->msg)) + (!strcmp(inst->content, other->content)) ); } @@ -92,12 +92,13 @@ Status CatlogSender_Send(CatlogSender *inst, int *store, bool append) fails(store, InvalidParameter); /* Open file. */ - ensure(CatlogUtils_OpenFile(inst->dst, "r"), "Unable to open file."); - ensure(CatlogMsg_Create(&(CatlogMsg){}, 0, "", ""), "Failed!"); + ensure(CatlogUtils_OpenFile(inst->dst, (append ? "a" : "w")), + "Unable to open file."); - /* Read file. */ - /* Creating buffer, */ - // TODO(william): Finish this function. + /* Write msg. */ + *store = fprintf(inst->dst, "%s", inst->msg.content); + + return NormalStatus; } Status CatlogUtils_CalcElapsed(struct timespec t1, struct timespec t2); diff --git a/catlog.h b/catlog.h index 1cf9dc6..3ffa286 100755 --- a/catlog.h +++ b/catlog.h @@ -19,7 +19,7 @@ typedef struct { time_t time; CatlogLevel level; char *originator; - char *msg; + char *content; } CatlogMsg; Status CatlogMsg_Create(CatlogMsg *inst, CatlogLevel level,