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 <unistd.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
#define LOG_TSBUFFER 64
|
#define LOG_TSBUFFER 64
|
||||||
|
|
||||||
|
@ -38,8 +39,158 @@ struct LogConfig
|
||||||
FILE *out;
|
FILE *out;
|
||||||
int flags;
|
int flags;
|
||||||
char *tsFmt;
|
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
|
void
|
||||||
Log(LogConfig * config, LogLevel level, const char *msg,...)
|
Log(LogConfig * config, LogLevel level, const char *msg,...)
|
||||||
{
|
{
|
||||||
|
@ -65,6 +216,8 @@ Log(LogConfig * config, LogLevel level, const char *msg,...)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pthread_mutex_lock(&config->lock);
|
||||||
|
|
||||||
for (i = 0; i < config->indent; i++)
|
for (i = 0; i < config->indent; i++)
|
||||||
{
|
{
|
||||||
fputc(' ', config->out);
|
fputc(' ', config->out);
|
||||||
|
@ -146,7 +299,7 @@ Log(LogConfig * config, LogLevel level, const char *msg,...)
|
||||||
indicator = '*';
|
indicator = '*';
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
indicator = ' ';
|
indicator = '?';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,163 +325,6 @@ Log(LogConfig * config, LogLevel level, const char *msg,...)
|
||||||
{
|
{
|
||||||
fflush(config->out);
|
fflush(config->out);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
LogConfig *
|
pthread_mutex_unlock(&config->lock);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,8 +50,6 @@ typedef struct Array Array;
|
||||||
/*
|
/*
|
||||||
* Create a new, empty array on the heap.
|
* Create a new, empty array on the heap.
|
||||||
*
|
*
|
||||||
* Params: none
|
|
||||||
*
|
|
||||||
* Return: A pointer to an Array, or NULL if there was an error
|
* Return: A pointer to an Array, or NULL if there was an error
|
||||||
* allocating memory for the Array.
|
* allocating memory for the Array.
|
||||||
*/
|
*/
|
||||||
|
@ -214,4 +212,4 @@ extern void
|
||||||
extern int
|
extern int
|
||||||
ArrayTrim(Array *);
|
ArrayTrim(Array *);
|
||||||
|
|
||||||
#endif
|
#endif /* TELODENDRIA_ARRAY_H */
|
||||||
|
|
|
@ -152,4 +152,4 @@ extern void
|
||||||
extern int
|
extern int
|
||||||
Base64Pad(char **, size_t);
|
Base64Pad(char **, size_t);
|
||||||
|
|
||||||
#endif
|
#endif /* TELODENDRIA_BASE64_H */
|
||||||
|
|
|
@ -83,4 +83,4 @@ extern int
|
||||||
extern char *
|
extern char *
|
||||||
CanonicalJsonEncodeToString(HashMap *);
|
CanonicalJsonEncodeToString(HashMap *);
|
||||||
|
|
||||||
#endif
|
#endif /* TELODENDRIA_CANONICALJSON_H */
|
||||||
|
|
|
@ -205,4 +205,4 @@ extern HashMap *
|
||||||
extern void
|
extern void
|
||||||
ConfigFree(HashMap *);
|
ConfigFree(HashMap *);
|
||||||
|
|
||||||
#endif
|
#endif /* TELODENDRIA_CONFIG_H */
|
||||||
|
|
|
@ -180,4 +180,4 @@ extern int
|
||||||
extern void
|
extern void
|
||||||
HashMapFree(HashMap *);
|
HashMapFree(HashMap *);
|
||||||
|
|
||||||
#endif
|
#endif /* TELODENDRIA_HASHMAP_H */
|
||||||
|
|
|
@ -102,11 +102,13 @@ typedef enum HttpStatus
|
||||||
struct HttpRequest
|
struct HttpRequest
|
||||||
{
|
{
|
||||||
HttpRequestMethod method;
|
HttpRequestMethod method;
|
||||||
|
HashMap *headers;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct HttpResponse
|
struct HttpResponse
|
||||||
{
|
{
|
||||||
HttpStatus status;
|
HttpStatus status;
|
||||||
|
HashMap *headers;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern char *
|
extern char *
|
||||||
|
|
|
@ -268,4 +268,4 @@ extern int
|
||||||
extern HashMap *
|
extern HashMap *
|
||||||
JsonDecode(FILE *);
|
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 possible flags that can be applied to alter the behavior of
|
||||||
* the logger
|
* the logger.
|
||||||
*/
|
*/
|
||||||
typedef enum LogFlag
|
typedef enum LogFlag
|
||||||
{
|
{
|
||||||
|
@ -71,50 +71,126 @@ typedef enum LogFlag
|
||||||
/*
|
/*
|
||||||
* The log configurations structure in which all settings exist.
|
* The log configurations structure in which all settings exist.
|
||||||
* It's not super elegant to pass around a pointer to the logging
|
* 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;
|
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 *
|
extern LogConfig *
|
||||||
LogConfigCreate(void);
|
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
|
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
|
extern void
|
||||||
LogConfigLevelSet(LogConfig * config, LogLevel level);
|
LogConfigOutputSet(LogConfig *, FILE *);
|
||||||
|
|
||||||
extern LogLevel
|
|
||||||
LogConfigLevelGet(LogConfig * config);
|
|
||||||
|
|
||||||
extern void
|
extern void
|
||||||
LogConfigIndentSet(LogConfig * config, size_t indent);
|
LogConfigFlagSet(LogConfig *, int);
|
||||||
|
|
||||||
extern size_t
|
|
||||||
LogConfigIndentGet(LogConfig * config);
|
|
||||||
|
|
||||||
extern void
|
extern void
|
||||||
LogConfigIndent(LogConfig * config);
|
LogConfigFlagClear(LogConfig *, int);
|
||||||
|
|
||||||
extern void
|
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
|
extern void
|
||||||
LogConfigOutputSet(LogConfig * config, FILE * out);
|
Log(LogConfig *, LogLevel, const char *,...);
|
||||||
|
|
||||||
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,...);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -21,13 +21,51 @@
|
||||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* 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
|
#ifndef TELODENDRIA_UTIL_H
|
||||||
#define 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
|
extern long
|
||||||
UtilServerTs(void);
|
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 *
|
extern char *
|
||||||
UtilUtf8Encode(unsigned long utf8);
|
UtilUtf8Encode(unsigned long);
|
||||||
|
|
||||||
#endif
|
#endif /* TELODENDRIA_UTIL_H */
|
||||||
|
|
Loading…
Reference in a new issue