(SOC) Storage Only Commit

(ADD) Name, NameScope, Catlog, Object, String, Attribute, Char, Registry, Utils, Type, <Platform Support>, <Global Constants>, README

(MOD) Array, Var, Status, MemMan, <Common>
This commit is contained in:
William
2024-05-16 00:04:42 +08:00
parent 989e512f8f
commit 5f7a6c6f93
32 changed files with 1694 additions and 195 deletions

View File

@@ -9,7 +9,9 @@
# include <time.h>
# include <stdio.h>
# define __HERE__ { .file = __FILE__, .line = __LINE__, .func = __func__ }
# include <Compound/common.h>
# include <Compound/utils.h>
# include <Compound/platform.h>
/* Status characteristics */
typedef enum {
@@ -18,22 +20,30 @@ typedef enum {
STATUS_ERROR = 1
} StatusCharacteristics;
//!!! UNKNOWN ENTITY !!!
// enum {
// ARGUE_FINALISED = 0b01,
// ARGUE_UNSETTLED =-0b01,
// ARGUE_POSITIVE = 0b10,
// ARGUE_NEGATIVE = -0b10,
// };
typedef enum {
/* Settlement. */
ARGUE_RESULT_FINALISED = 0b01,
ARGUE_RESULT_UNSETTLED = -0b01,
/* Nature. */
ARGUE_RESULT_POSITIVE = 0b10,
ARGUE_RESULT_NEGATIVE = -0b10,
} ArgueResult;
/* Indicated the exact location where the "issue" was occurred at. */
typedef struct {
const char *file;
char *file;
int line;
const char *func;
char *func;
} Location;
# define __HERE__ (Location){ \
.file = (char *)__FILE__, \
.line = __LINE__, \
.func = (char *)__func__ \
}
/* Common return type for reporting functions that require to give more
information about the procedure. */
typedef struct _Status {
@@ -43,36 +53,41 @@ typedef struct _Status {
Otherwise, the function would just return the structure Status. */
char *description;
int characteristic;
Location loc;
struct _Status *prev;
} Status;
/* "Report" recollects essential informations, included but not limited to
Status and others for making an report for debugging and such. */
typedef struct {
Status stat;
Location pos;
char *originator;
struct tm time;
int priority;
} Report;
/*
typedef struct {
FILE **dests_ref;
Report **reports_ref;
int totalreports;
int reportsent;
struct timespec elapsed;
} ReportSender;
{value "description" characteristic prev}
typedef Status (*ReportSendingTask) (FILE **, Report *);
typedef int ReportSendingTaskID;
"%d \"%s\" %d %p"
typedef struct {
ReportSendingTask *tasks_ref;
int sendercount;
int finishedcount;
Status *senderreturn;
} ReportSendingManager;
*/
# ifdef __COMPOUND_32__
# define STATUS_LITERALISE_LENGTH(stat) \
(utils_calc_digits(stat.value) + strlen(stat.description) + 2 + \
utils_calc_digits(INT32_DIGITS_DEC))
# elif defined __COMPOUND_64__
# define STATUS_LITERALISE_LENGTH(stat) \
(utils_calc_digits(stat.value) + strlen(stat.description) + 2 + \
utils_calc_digits(INT64_DIGITS_DEC))
# endif
# define STATUS_LITERALISE_FORMAT "%d \"%s\" %d %p"
typedef enum {
REPORT_SENDING_PRIORITY_ALL = 0, // Highest level; least value.
REPORT_SENDING_PRIORITY_FATAL,
REPORT_SENDING_PRIORITY_EXCEPTIONAL,
REPORT_SENDING_PRIORITY_CRITICAL,
REPORT_SENDING_PRIORITY_MAJOR,
REPORT_SENDING_PRIORITY_NORMAL,
REPORT_SENDING_PRIORITY_MINOR,
REPORT_SENDING_PRIORITY_DEBUG,
REPORT_SENDING_PRIORITY_NONE, // Lowest level, greatest value.
} ReportSendingPriority;
typedef enum {
REPORT_SENDING_TASK_STATUS_FINISHED = 0,
@@ -82,30 +97,97 @@ typedef enum {
REPORT_SENDING_TASK_STATUS_NOTFOUND
} ReportSendingTaskStatus;
typedef Status (*Argue) (Report);
/* "Report" recollects essential informations, included but not limited to
Status and others for making an report for debugging and such. */
typedef struct {
Argue argue_start; // Implicitly converting thrd_start_t to Argue
void *external_param;
} ArgueStarter;
Status stat;
char *originator;
time_t time;
ReportSendingPriority priority;
ReportSendingTaskStatus status;
FILE *dest; // The destination where the report is sending to.
} Report;
/*
TIME [PRIORITY] STATUSNAME (ORIGINATOR): STATUS.DESCRIPTION
at LOCATION.FILE:LOCATION.LINE, LOCATION.FUNC
at LOCATION.FILE:LOCATION.LINE, LOCATION.FUNC
at LOCATION.FILE:LOCATION.LINE, LOCATION.FUNC
at LOCATION.FILE:LOCATION.LINE, LOCATION.FUNC
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:69, _throw
!!!!at /external/Documents/Projects/Compound/Array/src/array.c:16, array_create
at /external/Documents/Projects/Compound/test.c:24, main
*/
# define REPORT_LITERALISE_HEADER_FORMAT "%ld [%s] %s (%s): %s"
# 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, \
ORIGINATOR, DESCRIPTION) \
(INT64_DIGITS_DEC + strlen(PRIORITY) + strlen(STATUSNAME) + \
strlen(ORIGINATOR) + strlen(DESCRIPTION) + 9) // Does not count '\0'
# define REPORT_LITERALISE_CHAINS_FORMAT_LENGTH(FILEPATH, LINE, FUNCNAME) \
(strlen(FILEPATH) + utils_calc_digits(LINE) + \
strlen(FUNCNAME) + 10) // Does not count '\0'
# define REPORT_LITERALISE_CHAINS_EXCLAIM_FORMAT_LENGTH \
REPORT_LITERALISE_CHAINS_FORMAT_LENGTH
/* Argument levels (qualities) */
typedef enum {
ARGUMENT_NONE = 0,
ARGUMENT_MINOR,
ARGUMENT_NORMAL,
ARGUMENT_MAJOR,
ARGUMENT_CRITICAL,
ARGUMENT_SEVERE,
ARGUMENT_ALL,
} ArgumentLevel;
REPORT_SENDER_RESULT_FINISHED,
REPORT_SENDER_RESULT_PROGRESSING,
REPORT_SENDER_RESULT_PENDING
} ReportSenderResult;
typedef struct {
ReportSender *streams;
ArgueStarter handler;
ArgumentLevel level;
bool muted;
} Argument;
thrd_t thread;
Report *report; // The report for sending.
time_t elapsed; // The individual elapsed time for each report. (Array)
ReportSenderResult result;
bool successful;
} ReportSender;
typedef int (*ReportSendingTask)(Report *rep);
typedef int ReportSendingTaskID;
typedef struct {
ReportSendingTask *tasks; // Array Ref
int sendercount;
int finishedcount;
int *results; // Array
} ReportSendingManager;
// typedef thrd_start_t ArgueStart;
// typedef struct {
// ArgueStart handler;
// void *external_param;
// } ArgueStartParam;
// /* Argument levels (qualities) */
// typedef enum {
// ARGUMENT_NONE = 0,
// ARGUMENT_MINOR,
// ARGUMENT_NORMAL,
// ARGUMENT_MAJOR,
// ARGUMENT_CRITICAL,
// ARGUMENT_SEVERE,
// ARGUMENT_ALL,
// } ArgumentLevel;
// typedef struct {
// ReportSender stream;
// ArgueStartParam handler; // Obsolete?
// ArgumentLevel level;
// bool muted;
// } Argument;
// typedef struct {
// Argument *members;
@@ -114,73 +196,58 @@ 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);
bool StatusUtils_IsOkay(Status stat);
bool StatusUtils_IsValid(Status stat);
bool StatusUtils_IsRecursive(Status stat);
int StatusUtils_Depth(Status *stat);
Status
Report_Create(Report *inst, Status *stat, FILE *dest, char *originator,
int priority);
bool
status_issueposition_compare(Location lc1, Location lc2);
bool
status_hasprev(Status stat);
bool
status_isnormal(Status stat);
bool
status_isvalid(Status stat);
bool
status_recursive(Status stat);
void
status_dump(Status stat, Status *statbuff, int idx);
bool
status_compare(Status stat1, Status stat2);
bool
report_compare(Report repo1, Report repo2);
Report_Equal(Report repo1, Report repo2);
Status
Report_Literalise(Report *inst, char *buff);
Status
reportsender_create(ReportSender *inst, FILE **dests_ref,
ReportSendingTask *tasks_ref);
ReportSender_Create(ReportSender *inst, Report *report);
Status
reportsender_send(ReportSender sender, ReportSendingTask *tasks_ref);
ReportSender_Send(ReportSender *inst, ReportSendingTask task);
ReportSendingTaskStatus
ReportSender_GetStatus(ReportSender *inst);
ReportSendingTaskID
reportsendingmanager_appendtask(ReportSendingManager *inst,
ReportSenderManager_AppendTask(ReportSendingManager *inst,
ReportSendingTask task);
Status
reportsendingmanager_removetask(ReportSendingManager *inst,
ReportSendingTaskID taskid);
ReportSendingTaskStatus
reportsendingmanager_taskstatus(ReportSendingManager *inst,
ReportSendingTaskID taskid);
Status ReportSenderManager_RemoveTask(ReportSendingManager *inst,
ReportSendingTaskID taskid);
// Status
// arguestarter_create(ArgueStartParam *inst, void *external_param);
// Status
// arguestarter_constr(ArgueStartParam *inst, ArgueStart argue_start,
// void *external_param);
// Status
// arguestarter_start(ArgueStartParam *inst);
// bool
// arguestarter_equal(ArgueStartParam *inst1, ArgueStartParam *inst2);
// Status arguestarter_current(void);
// Status arguestarter_sleep(const struct timespec *time_point,
// struct timespec *remaining);
// void arguestarter_exit(int code) __attribute__ ((__noreturn__));
// Status arguestarter_join(ArgueStart thrd);
Status
arguestarter_create(ArgueStarter *inst, void *external_param);
Status
arguestarter_constr(ArgueStarter *inst, Argue argue_start,
void *external_param);
Status
arguestarter_start(ArgueStarter *inst);
static inline int
arguestarter_equal(ArgueStarter *inst1, ArgueStarter *inst2)
{
return (inst1->argue_start == inst2->argue_start)
|| (inst1->external_param == inst2->external_param);
}
Status arguestarter_current(void);
Status arguestarter_sleep(const struct timespec *time_point,
struct timespec *remaining);
void arguestarter_exit(int code) __attribute__ ((__noreturn__));
Status arguestarter_join(Argue thrd);
// Status
// argument_create(Argument *inst, ReportSender *streams, ArgueStartParam handler,
// int level, bool muted);
Status
argument_create(Argument *inst, ReportSender *streams, ArgueStarter handler);
Status
argument_constr(Argument *inst, ReportSender *streams, ArgueStarter handler,
int level, bool muted);
// --------------------------------------------------------
// ---------------------ELEMENTARY-------------------------
static Status UnknownStatus = {
.description = "An unknown status.",
@@ -200,12 +267,18 @@ static Status ErrorStatus = {
.prev = NULL
};
// --------------------------------------------------------
// ----------------------EXTENDED--------------------------
static Status MemoryViolation = {
.description = "Illegal access on certain memory address.",
.characteristic = STATUS_ERROR,
.prev = &ErrorStatus
};
static Status NullPointerAccounted = {
.description = "An involving null pointer was not accepted.",
.characteristic = STATUS_ERROR,
.prev = &ErrorStatus
.prev = &MemoryViolation
};
static Status InvalidParameter = {
@@ -226,4 +299,127 @@ static Status ArithmeticError = {
.prev = &ErrorStatus
};
static Status RuntimeError = {
.description = "A runtime error occurred.",
.characteristic = STATUS_ERROR,
.prev = &ErrorStatus
};
static Status ArrayLengthError = {
.description = "Given array length does not meet the requirement.",
.characteristic = STATUS_ERROR,
.prev = &ErrorStatus
};
static Status VariableFormatMismatch = {
.description = "Given format does not match with given subjects.",
.characteristic = STATUS_ERROR,
.prev = &ErrorStatus
};
static Status ImprecisionError = {
.description = "Precision was not enough for handling the calculation.",
.characteristic = STATUS_ERROR,
.prev = &RuntimeError
};
// ---------------USER DEFINED | RUNTIME-------------------
static Status UnavailableInstance = {
.description = "An unavailable instance was given for initialisation.",
.characteristic = STATUS_ERROR,
.prev = &NullPointerAccounted
};
static Status UnavailableParameter = {
.description = "An unavailable instance was given as a parameter.",
.characteristic = STATUS_ERROR,
.prev = &UnavailableInstance
};
static Status InvalidReportTask = {
.description = "An unavailable or illegal report task was given.",
.characteristic = STATUS_ERROR,
.prev = &InvalidParameter
};
static Status UnableToThrowError = {
.description = "Unable to report an exceptional situation.",
.characteristic = STATUS_ERROR,
.prev = &RuntimeError
};
static Status ReadWriteError = {
.description = "Error occurred during IO session.",
.characteristic = STATUS_ERROR,
.prev = &RuntimeError
};
static Status FileNotFound = {
.description = "Target file was unavailable and unable to find.",
.characteristic = STATUS_ERROR,
.prev = &ReadWriteError
};
static Status InvalidFileName = {
.description = "Given file name was invalid.",
.characteristic = STATUS_ERROR,
.prev = &ReadWriteError
};
static Status ReportThrown = {
.description = "This function has thrown a report, "
"following instructions aborted.",
.characteristic = STATUS_ERROR,
.prev = &RuntimeError
};
static Status ReportMessageLengthTooLong = {
.description = "Given message is too long.",
.characteristic = STATUS_ERROR,
.prev = &ArrayLengthError
};
// ========================================================
# define ensure(e, c) { \
Status stat = e; \
solve(!(StatusUtils_IsOkay(stat)), { \
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__)
/* Useless in C, only for human to see.
Probably rewrite this in Classify. */
# define throws(e)
ReportSendingTaskID __throw(Report report, Location loc);
Report catch(ReportSendingTaskID taskid);
static int HANDLER(void *report)
{
/* Throw UnableToThrowError when param is unavailable. */
if (report == NULL) {
/* Create report on this. */
Report e;
Report_Create(
&e,
&error(UnableToThrowError, "Cannot perform throwing. Aborted."),
stderr, nameof(DEFAULT_ARGUE_STARTER),
REPORT_SENDING_PRIORITY_FATAL);
/* Perform throwing. */
(void)_throw(e); // Throw the report alone.
return 1;
}
(void)_throw(*(Report *)report); // Lonely _throw, no catch will company.
return 0;
}
#endif /* COMPOUND_STATUS_H */

View File

@@ -1,30 +1,174 @@
#include <Compound/common.h>
#include <Compound/status.h>
bool status_issueposition_compare(Location lc1, Location lc2) {
bool status_issuelocation_equal(Location lc1, Location lc2) {
return ((!strcmp(lc1.file, lc2.file)) && (lc1.line == lc2.line) &&
(!strcmp(lc1.func, lc2.func)));
}
bool status_hasprev(Status stat) { return (stat.prev != NULL); }
bool status_hasprev(Status stat) {
/* Skip when stat is unavailable for accessing. */
state(status_equal(stat, (Status){}), false);
bool status_isnormal(Status stat) { return (!stat.characteristic); }
return (stat.prev != NULL);
}
bool status_isokay(Status stat) { return (!stat.characteristic); }
bool status_isvalid(Status stat) {
return (!strcmp(stat.description, "") && stat.characteristic >= 0 &&
stat.prev != NULL);
}
bool status_recursive(Status stat) {
return (stat.prev != NULL && stat.prev == &stat);
}
void status_dump(Status stat, Status *statbuff, int idx) {
if (statbuff == NULL || !status_hasprev(stat) || idx < 0) {
return;
}
void status_dump(Status inst, Status *statbuff, int idx) {
statbuff[idx] = stat;
/* Skip when either stat or stat.prev is unavailable, or, idx is invalid. */
solve((statbuff == NULL || !status_hasprev(inst) || idx < 0), return;);
status_dump(*stat.prev, statbuff, ++idx);
statbuff[idx] = inst;
(void)printf("status_dump: Index %d has assigned with %p\n", idx, &inst);
status_dump(*inst.prev, statbuff, ++idx);
}
bool status_compare(Status stat1, Status stat2) {
return (!strcmp(stat1.description, stat2.description) &&
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 &&
stat2.description == 0x0 && stat1.characteristic == 0 &&
stat2.characteristic == 0 && stat1.prev == 0x0 && stat2.prev == 0x0),
true);
/* True for equality; False for inequality. */
return ((stat1.value == stat2.value) &&
(!strcmp(stat1.description, stat2.description)) &&
(stat1.characteristic == stat2.characteristic) &&
(!status_compare(*stat1.prev, *stat2.prev)));
(status_equal(*stat1.prev, *stat2.prev)));
}
int status_depth(Status *stat) {
/* Skip unavailable stat. */
state((stat == NULL), -1);
Status *p = stat; // Include this layer of Status.
int cnt = 1;
while (p != NULL) {
if (status_recursive(*p) || !status_hasprev(*stat)) break;
p = p->prev;
cnt += 1;
}
return cnt;
}
Status report_create(Report *inst, Status *stat, FILE *dest, char *originator,
int priority) {
/* Skip unavailable parameters. */
fails(inst, UnavailableInstance);
fails(stat, error(InvalidParameter, "Given originator was null."));
fails(originator, error(InvalidParameter, "Given originator was null."));
state(priority < 0, error(InvalidParameter, "Given priority was negative."));
/* Copy and assign. */
inst->stat = *stat;
inst->originator = originator;
inst->time = time(NULL);
inst->priority = priority;
inst->status = REPORT_SENDING_TASK_STATUS_PENDING;
inst->dest = (dest == NULL ? stderr : dest);
return NormalStatus;
}
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
}
Status reportsender_create(ReportSender *inst, Report *report) {
fails(inst, UnavailableInstance);
fails(report, error(UnavailableParameter, "Given report was unavailable."));
thrd_create(&inst->thread, &HANDLER, report);
*inst->report = *report;
inst->elapsed = 0;
inst->result = REPORT_SENDER_RESULT_PENDING;
inst->successful = false;
return NormalStatus;
}
Status reportsender_send(ReportSender *inst, ReportSendingTask task) {
/* Skip when inst or task is unavailable. */
fails(inst,
error(UnavailableInstance, "Report sender was given unavailable."));
fails(task, InvalidReportTask);
/* Assign for dest. */
const FILE *dest = (inst->report->dest == NULL ? stdout : inst->report->dest);
// char buff[];
// TODO(william): HERE, report_literalise
/* Write/Send data. */
inst->report->status = REPORT_SENDING_TASK_STATUS_PROCEEDING;
if (!fprintf(dest, buff)) {
}
/* Sent successfully! Mark down properties. */
}
// bool arguestarter_equal(ArgueStarter *inst1, ArgueStarter *inst2)
// {
// /* Skip when either inst1 or inst2 is unavailable. */
// state(inst1 == NULL || inst2 == NULL, false);
// return (inst1->argue_start == inst2->argue_start)
// || (inst1->external_param == inst2->external_param);
// }
ReportSendingTaskID _throw(Report report, Location loc) {
// /* Create new a instance of ReportSender. */
// ReportSender sender;
// reportsender_create(&sender, stderr);
// /* Send message. */
// /* Initialise sender's thread. */
// thrd_t sending;
// /* Skip on failing on creating thread. */
// if (!thrd_create(&sending, starter, NULL)) {
// /* Conclude the session of sender. */
// report.status = REPORT_SENDING_TASK_STATUS_FINISHED,
// report.result = (ARGUE_RESULT_FINALISED | ARGUE_RESULT_NEGATIVE);
// sender.result = REPORT_SENDER_RESULT_FINISHED;
// sender.successful = false;
// return -1;
// }
// /* Perform sending. */
// reportsender_send(&sender, NULL);
/* Initialise sender. */
ReportSender sender;
/* Return with -1 when initialisation failed. */
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);
}