forked from lda/telodendria
Apply #14
This commit is contained in:
parent
27acd6dc45
commit
fa0bd9a7c6
10 changed files with 309 additions and 199 deletions
314
src/Log.c
314
src/Log.c
|
@ -28,6 +28,7 @@
|
|||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
#include <stdarg.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#define LOG_TSBUFFER 64
|
||||
|
||||
|
@ -38,8 +39,158 @@ struct LogConfig
|
|||
FILE *out;
|
||||
int flags;
|
||||
char *tsFmt;
|
||||
|
||||
pthread_mutex_t lock;
|
||||
};
|
||||
|
||||
LogConfig *
|
||||
LogConfigCreate(void)
|
||||
{
|
||||
LogConfig *config;
|
||||
|
||||
config = calloc(1, sizeof(LogConfig));
|
||||
|
||||
if (!config)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LogConfigLevelSet(config, LOG_MESSAGE);
|
||||
LogConfigIndentSet(config, 0);
|
||||
LogConfigOutputSet(config, NULL); /* Will set to stdout */
|
||||
LogConfigFlagSet(config, LOG_FLAG_COLOR);
|
||||
LogConfigTimeStampFormatSet(config, "%y-%m-%d %H:%M:%S");
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
void
|
||||
LogConfigFlagClear(LogConfig * config, int flags)
|
||||
{
|
||||
if (!config)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
config->flags &= ~flags;
|
||||
}
|
||||
|
||||
static int
|
||||
LogConfigFlagGet(LogConfig * config, int flags)
|
||||
{
|
||||
if (!config)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return config->flags & flags;
|
||||
}
|
||||
|
||||
void
|
||||
LogConfigFlagSet(LogConfig * config, int flags)
|
||||
{
|
||||
if (!config)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
config->flags |= flags;
|
||||
}
|
||||
|
||||
void
|
||||
LogConfigFree(LogConfig * config)
|
||||
{
|
||||
free(config);
|
||||
}
|
||||
|
||||
void
|
||||
LogConfigIndent(LogConfig * config)
|
||||
{
|
||||
if (config)
|
||||
{
|
||||
config->indent += 2;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
LogConfigIndentSet(LogConfig * config, size_t indent)
|
||||
{
|
||||
if (!config)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
config->indent = indent;
|
||||
}
|
||||
|
||||
LogLevel
|
||||
LogConfigLevelGet(LogConfig * config)
|
||||
{
|
||||
if (!config)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return config->level;
|
||||
}
|
||||
|
||||
void
|
||||
LogConfigLevelSet(LogConfig * config, LogLevel level)
|
||||
{
|
||||
if (!config)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (level)
|
||||
{
|
||||
case LOG_ERROR:
|
||||
case LOG_WARNING:
|
||||
case LOG_MESSAGE:
|
||||
case LOG_DEBUG:
|
||||
config->level = level;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
LogConfigOutputSet(LogConfig * config, FILE * out)
|
||||
{
|
||||
if (!config)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (out)
|
||||
{
|
||||
config->out = out;
|
||||
}
|
||||
else
|
||||
{
|
||||
config->out = stdout;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
LogConfigTimeStampFormatSet(LogConfig * config, char *tsFmt)
|
||||
{
|
||||
if (config)
|
||||
{
|
||||
config->tsFmt = tsFmt;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
LogConfigUnindent(LogConfig * config)
|
||||
{
|
||||
if (config && config->indent >= 2)
|
||||
{
|
||||
config->indent -= 2;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Log(LogConfig * config, LogLevel level, const char *msg,...)
|
||||
{
|
||||
|
@ -65,6 +216,8 @@ Log(LogConfig * config, LogLevel level, const char *msg,...)
|
|||
return;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&config->lock);
|
||||
|
||||
for (i = 0; i < config->indent; i++)
|
||||
{
|
||||
fputc(' ', config->out);
|
||||
|
@ -146,7 +299,7 @@ Log(LogConfig * config, LogLevel level, const char *msg,...)
|
|||
indicator = '*';
|
||||
break;
|
||||
default:
|
||||
indicator = ' ';
|
||||
indicator = '?';
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -172,163 +325,6 @@ Log(LogConfig * config, LogLevel level, const char *msg,...)
|
|||
{
|
||||
fflush(config->out);
|
||||
}
|
||||
}
|
||||
|
||||
LogConfig *
|
||||
LogConfigCreate(void)
|
||||
{
|
||||
LogConfig *config;
|
||||
|
||||
config = calloc(1, sizeof(LogConfig));
|
||||
|
||||
if (!config)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LogConfigLevelSet(config, LOG_MESSAGE);
|
||||
LogConfigIndentSet(config, 0);
|
||||
LogConfigOutputSet(config, NULL); /* Will set to stdout */
|
||||
LogConfigFlagSet(config, LOG_FLAG_COLOR);
|
||||
LogConfigTimeStampFormatSet(config, "%y-%m-%d %H:%M:%S");
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
void
|
||||
LogConfigFlagClear(LogConfig * config, int flags)
|
||||
{
|
||||
if (!config)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
config->flags &= ~flags;
|
||||
}
|
||||
|
||||
int
|
||||
LogConfigFlagGet(LogConfig * config, int flags)
|
||||
{
|
||||
if (!config)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return config->flags & flags;
|
||||
}
|
||||
|
||||
void
|
||||
LogConfigFlagSet(LogConfig * config, int flags)
|
||||
{
|
||||
if (!config)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
config->flags |= flags;
|
||||
}
|
||||
|
||||
void
|
||||
LogConfigFree(LogConfig * config)
|
||||
{
|
||||
free(config);
|
||||
}
|
||||
|
||||
void
|
||||
LogConfigIndent(LogConfig * config)
|
||||
{
|
||||
if (config)
|
||||
{
|
||||
config->indent += 2;
|
||||
}
|
||||
}
|
||||
|
||||
size_t
|
||||
LogConfigIndentGet(LogConfig * config)
|
||||
{
|
||||
if (!config)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return config->indent;
|
||||
}
|
||||
|
||||
void
|
||||
LogConfigIndentSet(LogConfig * config, size_t indent)
|
||||
{
|
||||
if (!config)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
config->indent = indent;
|
||||
}
|
||||
|
||||
LogLevel
|
||||
LogConfigLevelGet(LogConfig * config)
|
||||
{
|
||||
if (!config)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return config->level;
|
||||
}
|
||||
|
||||
void
|
||||
LogConfigLevelSet(LogConfig * config, LogLevel level)
|
||||
{
|
||||
if (!config)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (level)
|
||||
{
|
||||
case LOG_ERROR:
|
||||
case LOG_WARNING:
|
||||
case LOG_MESSAGE:
|
||||
case LOG_DEBUG:
|
||||
config->level = level;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
LogConfigOutputSet(LogConfig * config, FILE * out)
|
||||
{
|
||||
if (!config)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (out)
|
||||
{
|
||||
config->out = out;
|
||||
}
|
||||
else
|
||||
{
|
||||
config->out = stdout;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
LogConfigTimeStampFormatSet(LogConfig * config, char *tsFmt)
|
||||
{
|
||||
if (config)
|
||||
{
|
||||
config->tsFmt = tsFmt;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
LogConfigUnindent(LogConfig * config)
|
||||
{
|
||||
if (config && config->indent >= 2)
|
||||
{
|
||||
config->indent -= 2;
|
||||
}
|
||||
pthread_mutex_unlock(&config->lock);
|
||||
}
|
||||
|
|
|
@ -50,8 +50,6 @@ typedef struct Array Array;
|
|||
/*
|
||||
* Create a new, empty array on the heap.
|
||||
*
|
||||
* Params: none
|
||||
*
|
||||
* Return: A pointer to an Array, or NULL if there was an error
|
||||
* allocating memory for the Array.
|
||||
*/
|
||||
|
@ -214,4 +212,4 @@ extern void
|
|||
extern int
|
||||
ArrayTrim(Array *);
|
||||
|
||||
#endif
|
||||
#endif /* TELODENDRIA_ARRAY_H */
|
||||
|
|
|
@ -152,4 +152,4 @@ extern void
|
|||
extern int
|
||||
Base64Pad(char **, size_t);
|
||||
|
||||
#endif
|
||||
#endif /* TELODENDRIA_BASE64_H */
|
||||
|
|
|
@ -83,4 +83,4 @@ extern int
|
|||
extern char *
|
||||
CanonicalJsonEncodeToString(HashMap *);
|
||||
|
||||
#endif
|
||||
#endif /* TELODENDRIA_CANONICALJSON_H */
|
||||
|
|
|
@ -205,4 +205,4 @@ extern HashMap *
|
|||
extern void
|
||||
ConfigFree(HashMap *);
|
||||
|
||||
#endif
|
||||
#endif /* TELODENDRIA_CONFIG_H */
|
||||
|
|
|
@ -180,4 +180,4 @@ extern int
|
|||
extern void
|
||||
HashMapFree(HashMap *);
|
||||
|
||||
#endif
|
||||
#endif /* TELODENDRIA_HASHMAP_H */
|
||||
|
|
|
@ -102,11 +102,13 @@ typedef enum HttpStatus
|
|||
struct HttpRequest
|
||||
{
|
||||
HttpRequestMethod method;
|
||||
HashMap *headers;
|
||||
};
|
||||
|
||||
struct HttpResponse
|
||||
{
|
||||
HttpStatus status;
|
||||
HashMap *headers;
|
||||
};
|
||||
|
||||
extern char *
|
||||
|
|
|
@ -268,4 +268,4 @@ extern int
|
|||
extern HashMap *
|
||||
JsonDecode(FILE *);
|
||||
|
||||
#endif
|
||||
#endif /* TELODENDRIA_JSON_H */
|
||||
|
|
|
@ -61,7 +61,7 @@ typedef enum LogLevel
|
|||
|
||||
/*
|
||||
* The possible flags that can be applied to alter the behavior of
|
||||
* the logger
|
||||
* the logger.
|
||||
*/
|
||||
typedef enum LogFlag
|
||||
{
|
||||
|
@ -71,50 +71,126 @@ typedef enum LogFlag
|
|||
/*
|
||||
* The log configurations structure in which all settings exist.
|
||||
* It's not super elegant to pass around a pointer to the logging
|
||||
* configuration
|
||||
* configuration, but this really is the best way without having a
|
||||
* global variable. It allows multiple loggers to exist if necessary,
|
||||
* and makes things more thread safe.
|
||||
*/
|
||||
typedef struct LogConfig LogConfig;
|
||||
|
||||
/*
|
||||
* Create a new log configuration on the heap. This will be passed to
|
||||
* every Log() call after it is configured.
|
||||
*
|
||||
* Return: A pointer to a new LogConfig that can be configured and used
|
||||
* for logging. It should have sane defaults; in other words, you should
|
||||
* be able to immediately start logging with it.
|
||||
*/
|
||||
extern LogConfig *
|
||||
LogConfigCreate(void);
|
||||
|
||||
/*
|
||||
* Free a log configuration. Future attempts to log with the passed
|
||||
* configuration will fail in an undefined way, such as by hanging the
|
||||
* process or segfaulting.
|
||||
*
|
||||
* Params:
|
||||
*
|
||||
* (LogConfig *) The configuration to free. All memory associated with
|
||||
* configuring the logging mechanism will be
|
||||
* invalidated.
|
||||
*/
|
||||
extern void
|
||||
LogConfigFree(LogConfig * config);
|
||||
LogConfigFree(LogConfig *);
|
||||
|
||||
/*
|
||||
* Set the current log level on the specified log configuration. This
|
||||
* indicates that only messages at or above this level should be
|
||||
* logged; all other messages are ignored by the Log() function.
|
||||
*
|
||||
* Params:
|
||||
*
|
||||
* (LogConfig *) The log configuration to set the log level on.
|
||||
* (LogLevel) The log level to set.
|
||||
*/
|
||||
extern void
|
||||
LogConfigLevelSet(LogConfig *, LogLevel);
|
||||
|
||||
/*
|
||||
* Indent the log output by two spaces. This can be helpful in
|
||||
* generating stack traces, or otherwise producing hierarchical output.
|
||||
* After calling this function, all future log messages using this
|
||||
* configuration will be indented.
|
||||
*
|
||||
* Params:
|
||||
*
|
||||
* (LogConfig *) The log configuration to indent.
|
||||
*/
|
||||
extern void
|
||||
LogConfigIndent(LogConfig *);
|
||||
|
||||
/*
|
||||
* Decrease the log output indent by two spaces. This can be helpful in
|
||||
* generating stack traces, or otherwise producing hierarchical output.
|
||||
* After calling this function, all future log messages using this
|
||||
* configuration will be unindented, unless there was no indentation
|
||||
* to begin with; in that case, this function will do nothing.
|
||||
*
|
||||
* Params:
|
||||
*
|
||||
* (LogConfig *) The log configuration to unindent.
|
||||
*/
|
||||
extern void
|
||||
LogConfigUnindent(LogConfig *);
|
||||
|
||||
/*
|
||||
* Set the log output indent to an arbitrary amount. This can be helpful
|
||||
* in generating stack traces, or otherwise producing hierarchical
|
||||
* output. After calling this function, all future log messages using
|
||||
* this configuration will be indented by the given amount.
|
||||
*
|
||||
* Params:
|
||||
*
|
||||
* (LogConfig *) The log configuration to apply the indent to.
|
||||
*/
|
||||
extern void
|
||||
LogConfigIndentSet(LogConfig *, size_t);
|
||||
|
||||
extern void
|
||||
LogConfigLevelSet(LogConfig * config, LogLevel level);
|
||||
|
||||
extern LogLevel
|
||||
LogConfigLevelGet(LogConfig * config);
|
||||
LogConfigOutputSet(LogConfig *, FILE *);
|
||||
|
||||
extern void
|
||||
LogConfigIndentSet(LogConfig * config, size_t indent);
|
||||
|
||||
extern size_t
|
||||
LogConfigIndentGet(LogConfig * config);
|
||||
LogConfigFlagSet(LogConfig *, int);
|
||||
|
||||
extern void
|
||||
LogConfigIndent(LogConfig * config);
|
||||
LogConfigFlagClear(LogConfig *, int);
|
||||
|
||||
extern void
|
||||
LogConfigUnindent(LogConfig * config);
|
||||
LogConfigTimeStampFormatSet(LogConfig *, char *);
|
||||
|
||||
/*
|
||||
* Actually log a message to a console, file, or other output device,
|
||||
* using the given log configuration. This function is thread-safe; it
|
||||
* locks a mutex before writing a message, and then unlocks it after
|
||||
* the message was written. It should therefore work well in
|
||||
* multithreaded environments, and with multiple different log
|
||||
* configurations, as each one has its own mutex.
|
||||
*
|
||||
* This function only logs messages if they are above the currently
|
||||
* configured log level. In this way, it is easy to turn some messages
|
||||
* on and off.
|
||||
*
|
||||
* This function is a printf() style function; it takes a format
|
||||
* string and any number of parameters to format.
|
||||
*
|
||||
* Params:
|
||||
*
|
||||
* (LogConfig *) The logging configuration.
|
||||
* (LogLevel) The level of the message to log.
|
||||
* (const char *) The format string, or a plain message string.
|
||||
* (...) Any items to map into the format string, printf()
|
||||
* style.
|
||||
*/
|
||||
extern void
|
||||
LogConfigOutputSet(LogConfig * config, FILE * out);
|
||||
|
||||
extern void
|
||||
LogConfigFlagSet(LogConfig * config, int flags);
|
||||
|
||||
extern void
|
||||
LogConfigFlagClear(LogConfig * config, int flags);
|
||||
|
||||
extern int
|
||||
LogConfigFlagGet(LogConfig * config, int flags);
|
||||
|
||||
extern void
|
||||
LogConfigTimeStampFormatSet(LogConfig * config, char *tsFmt);
|
||||
|
||||
extern void
|
||||
Log(LogConfig * config, LogLevel level, const char *msg,...);
|
||||
Log(LogConfig *, LogLevel, const char *,...);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -21,13 +21,51 @@
|
|||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Util.h: Some misc. helper functions that provide functionality that
|
||||
* doesn't need its own full API. The functions here are entirely
|
||||
* stand-alone, and generally don't depend on any of the other APIs
|
||||
* defined by Telodendria.
|
||||
*/
|
||||
#ifndef TELODENDRIA_UTIL_H
|
||||
#define TELODENDRIA_UTIL_H
|
||||
|
||||
/*
|
||||
* Get the current type in milliseconds since the Unix epoch. This uses
|
||||
* POSIX gettimeofday(2) and time_t, and converts it to a single number,
|
||||
* which is returned.
|
||||
*
|
||||
* A note on the 2038 problem: that's a long ways away, screw future
|
||||
* me!
|
||||
*
|
||||
* Kidding. As long as (sizeof(long) == 8), that is, as long as the
|
||||
* long datatype is 64 bits, which is is on all modern 64-bit Unix-like
|
||||
* operating systems, then everything should be fine. Expect
|
||||
* Telodendria on 32-bit machines to break in 2038. I didn't want to
|
||||
* try to hack together some system to store larger numbers than the
|
||||
* architecture supports. We can always re-evaluate things over the
|
||||
* next decade.
|
||||
*
|
||||
* Return: A long representing the current time in milliseconds since
|
||||
* the beginning of the Unix epoch, just as the Matrix spec requires.
|
||||
*/
|
||||
extern long
|
||||
UtilServerTs(void);
|
||||
|
||||
/*
|
||||
* Encode a single UTF-8 codepoint as a string buffer containing
|
||||
* between 1 and 4 bytes. The string buffer is allocated on the heap,
|
||||
* so it should be freed when it is no longer needed.
|
||||
*
|
||||
* Params:
|
||||
*
|
||||
* (unsigned long) The UTF-8 codepoint to encode as a byte buffer.
|
||||
*
|
||||
* Return: a null-terminated byte buffer representing the UTF-8
|
||||
* codepoint.
|
||||
*/
|
||||
extern char *
|
||||
UtilUtf8Encode(unsigned long utf8);
|
||||
UtilUtf8Encode(unsigned long);
|
||||
|
||||
#endif
|
||||
#endif /* TELODENDRIA_UTIL_H */
|
||||
|
|
Loading…
Reference in a new issue