123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209 |
- #ifndef _LSUP_CORE_H
- #define _LSUP_CORE_H
- #include <ctype.h>
- #include <dirent.h>
- #include <errno.h>
- #include <inttypes.h>
- #include <limits.h>
- #include <stdbool.h>
- #include <stddef.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <sys/stat.h>
- #include <uuid/uuid.h>
- #ifdef DEBUG
- #define DEBUG_TEST 1
- #else
- #define DEBUG_TEST 0
- #endif
- #define STR "%s"
- #define TRACE(fmt, ...) \
- do {\
- if (DEBUG_TEST) \
- fprintf(stderr, "%s:%d:%s(): " fmt "\n", \
- __FILE__, __LINE__, __func__, __VA_ARGS__); \
- } while (0)
- #define LIKELY(x) __builtin_expect(!!(x), true)
- #define UNLIKELY(x) __builtin_expect(!!(x), false)
- // TODO Cross-platform ramdisk path.
- #define TMPDIR "/tmp"
- #define KLEN sizeof(LSUP_Key)
- #define DBL_KLEN sizeof(LSUP_DoubleKey)
- #define TRP_KLEN sizeof(LSUP_TripleKey)
- #define QUAD_KLEN sizeof(LSUP_QuadKey)
- # define UUIDSTR_SIZE 37
- // Handy flags operations.
- #define SET_FLAG(n, f) ((n) |= (f))
- #define CLR_FLAG(n, f) ((n) &= ~(f))
- #define TGL_FLAG(n, f) ((n) ^= (f))
- #define CHK_FLAG(n, f) ((n) & (f))
- /* * * RETURN CODES * * */
- /**
- * 0 is success, positive integers (>88800) are warnings, and negative integers
- * (<-88800) are errors.
- */
- typedef enum {
- LSUP_OK = 0,
- LSUP_NOACTION = 88801,
- LSUP_NORESULT = 88802,
- LSUP_END = 88803,
- LSUP_ERROR = -88801,
- LSUP_PARSE_ERR = -88802,
- LSUP_VALUE_ERR = -88803,
- LSUP_TXN_ERR = -88804,
- LSUP_DB_ERR = -88805,
- LSUP_NOT_IMPL_ERR = -88806,
- LSUP_IO_ERR = -88807,
- LSUP_MEM_ERR = -88808,
- } LSUP_rc;
- typedef enum {
- LSUP_BOOL_UNION,
- LSUP_BOOL_SUBTRACTION,
- LSUP_BOOL_INTERSECTION,
- LSUP_BOOL_XOR,
- } LSUP_bool_op;
- typedef size_t LSUP_Key;
- typedef LSUP_Key LSUP_DoubleKey[2];
- typedef LSUP_Key LSUP_TripleKey[3];
- typedef LSUP_Key LSUP_QuadKey[4];
- typedef char uuid_str_t[UUIDSTR_SIZE];
- // Yes, a textbook mistake; but writing min and max for all int types is crazy.
- #define min(x, y) (x) < (y) ? (x) : (y)
- #define max(x, y) (x) > (y) ? (x) : (y)
- /** @brief Make recursive directories.
- *
- * from https://gist.github.com/JonathonReinhart/8c0d90191c38af2dcadb102c4e202950
- */
- LSUP_rc mkdir_p(const char *path, mode_t mode);
- /** @brief Remove a directory recursively, as in Unix "rm -r".
- *
- * @param path[in] Path of directory to remove.
- */
- LSUP_rc
- rm_r (const char *path);
- /** @brief Convert a Unicode (UTF-8) code point to 4-byte sequence.
- */
- /*
- inline uint16_t utf8_to_bytes (uint16_t c) {
- unsigned char b[4] = {0};
- if (c<0x80) *b++=c;
- else if (c<0x800) *b++=192+c/64, *b++=128+c%64;
- else if (c-0xd800u<0x800) goto error;
- else if (c<0x10000) *b++=224+c/4096, *b++=128+c/64%64, *b++=128+c%64;
- else if (c<0x110000)
- *b++=240+c/262144, *b++=128+c/4096%64, *b++=128+c/64%64, *b++=128+c%64;
- else return NULL;
- return (uint16_t)b;
- }
- */
- /**
- * Encode a code point using UTF-8
- *
- * @author Ondřej Hruška <ondra@ondrovo.com>
- * @license MIT
- * https://gist.github.com/MightyPork/52eda3e5677b4b03524e40c9f0ab1da5
- *
- * @param out - output buffer (min 5 characters), will be 0-terminated
- * @param utf - code point 0-0x10FFFF
- * @return number of bytes on success, 0 on failure (also produces U+FFFD, which uses 3 bytes)
- */
- inline int utf8_encode(const uint32_t utf, unsigned char *out)
- {
- if (utf <= 0x7F) {
- // Plain ASCII
- out[0] = (char) utf;
- out[1] = 0;
- return 1;
- }
- else if (utf <= 0x07FF) {
- // 2-byte unicode
- out[0] = (char) (((utf >> 6) & 0x1F) | 0xC0);
- out[1] = (char) (((utf >> 0) & 0x3F) | 0x80);
- out[2] = 0;
- return 2;
- }
- else if (utf <= 0xFFFF) {
- // 3-byte unicode
- out[0] = (char) (((utf >> 12) & 0x0F) | 0xE0);
- out[1] = (char) (((utf >> 6) & 0x3F) | 0x80);
- out[2] = (char) (((utf >> 0) & 0x3F) | 0x80);
- out[3] = 0;
- return 3;
- }
- else if (utf <= 0x10FFFF) {
- // 4-byte unicode
- out[0] = (char) (((utf >> 18) & 0x07) | 0xF0);
- out[1] = (char) (((utf >> 12) & 0x3F) | 0x80);
- out[2] = (char) (((utf >> 6) & 0x3F) | 0x80);
- out[3] = (char) (((utf >> 0) & 0x3F) | 0x80);
- out[4] = 0;
- return 4;
- }
- else {
- // error - use replacement character
- out[0] = (char) 0xEF;
- out[1] = (char) 0xBF;
- out[2] = (char) 0xBD;
- out[3] = 0;
- return 0;
- }
- }
- // Error handling via goto.
- #define CHECK(exp, rc, marker) (rc) = (exp); if ((rc) != LSUP_OK) goto marker
- // Jump if rc is negative (skip warnings).
- #define PCHECK(exp, rc, marker) (rc) = (exp); if ((rc) < LSUP_OK) goto marker
- // Return rc if it is of LSUP_rc type and is negative (=error)
- #define RCCK(exp) LSUP_rc _rc = (exp); if (_rc < 0) return _rc
- // Return NULL if it is of LSUP_rc type and is negative (=error)
- #define RCNL(exp) if((exp) < 0) return NULL
- #define MALLOC_GUARD(var, rc) do { \
- (var) = malloc (sizeof *(var)); \
- if (UNLIKELY (var == NULL)) return (rc); \
- } while (0);
- #define CALLOC_GUARD(var, rc) do { \
- (var) = calloc (1, sizeof *(var)); \
- if (UNLIKELY (var == NULL)) return (rc); \
- } while (0);
- /*
- #define MALLOC_GUARD_ME(var) MALLOC_GUARD((var), LSUP_MEM_ERR) \
- #define CALLOC_GUARD_ME(var) CALLOC_GUARD((var), LSUP_MEM_ERR) \
- #define MALLOC_GUARD_NL(var) MALLOC_GUARD((var), NULL) \
- #define CALLOC_GUARD_NL(var) CALLOC_GUARD((var), NULL) \
- */
- #endif
|