From 9cb7dda5b12bd61291a4741c92e5697eb1d3c6ff Mon Sep 17 00:00:00 2001 From: chirag-diwan Date: Sat, 28 Feb 2026 12:22:03 +0530 Subject: [PATCH] Added extern for CXX support , resolved error in SDS.h file . TEST BUILD SUCCESSFUL --- bf16.h | 45 +++++---- fp16.c | 110 ++++++++++---------- fp16.h | 11 ++ gguflib.h | 283 +++++++++++++++++++++++++++------------------------- sds.h | 292 ++++++++++++++++++++++++++++-------------------------- 5 files changed, 396 insertions(+), 345 deletions(-) diff --git a/bf16.h b/bf16.h index 3c160f4..665c0d8 100644 --- a/bf16.h +++ b/bf16.h @@ -1,7 +1,14 @@ #ifndef BF16_h #define BF16_h + +#ifdef __cplusplus + #include +extern "C" { + +#endif + /** * Converts brain16 to float32. * @@ -42,29 +49,33 @@ * @see IEEE 754-2008 */ static inline float from_brain(uint16_t h) { - union { - float f; - uint32_t i; - } u; - u.i = (uint32_t)h << 16; - return u.f; + union { + float f; + uint32_t i; + } u; + u.i = (uint32_t)h << 16; + return u.f; } /** * Converts float32 to brain16. */ static inline uint16_t to_brain(float s) { - uint16_t h; - union { - float f; - uint32_t i; - } u; - u.f = s; - if ((u.i & 0x7fffffff) > 0x7f800000) { /* nan */ - h = (u.i >> 16) | 64; /* force to quiet */ - return h; - } - return (u.i + (0x7fff + ((u.i >> 16) & 1))) >> 16; + uint16_t h; + union { + float f; + uint32_t i; + } u; + u.f = s; + if ((u.i & 0x7fffffff) > 0x7f800000) { /* nan */ + h = (u.i >> 16) | 64; /* force to quiet */ + return h; + } + return (u.i + (0x7fff + ((u.i >> 16) & 1))) >> 16; +} + +#ifdef __cplusplus } +#endif #endif diff --git a/fp16.c b/fp16.c index fa90605..ed55d8a 100644 --- a/fp16.c +++ b/fp16.c @@ -8,83 +8,89 @@ * * The original code is MIT licensed. */ -#include #include +#include static inline float fp32_from_bits(uint32_t w) { - union { - uint32_t as_bits; - float as_value; - } fp32; - fp32.as_bits = w; - return fp32.as_value; + union { + uint32_t as_bits; + float as_value; + } fp32; + fp32.as_bits = w; + return fp32.as_value; } static inline uint32_t fp32_to_bits(float f) { - union { - float as_value; - uint32_t as_bits; - } fp32; - fp32.as_value = f; - return fp32.as_bits; + union { + float as_value; + uint32_t as_bits; + } fp32; + fp32.as_value = f; + return fp32.as_bits; } float from_half(uint16_t h) { - const uint32_t w = (uint32_t) h << 16; - const uint32_t sign = w & UINT32_C(0x80000000); - const uint32_t two_w = w + w; + const uint32_t w = (uint32_t)h << 16; + const uint32_t sign = w & UINT32_C(0x80000000); + const uint32_t two_w = w + w; - const uint32_t exp_offset = UINT32_C(0xE0) << 23; -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) || defined(__GNUC__) && !defined(__STRICT_ANSI__) - const float exp_scale = 0x1.0p-112f; + const uint32_t exp_offset = UINT32_C(0xE0) << 23; +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) || \ + defined(__GNUC__) && !defined(__STRICT_ANSI__) + const float exp_scale = 0x1.0p-112f; #else - const float exp_scale = fp32_from_bits(UINT32_C(0x7800000)); + const float exp_scale = fp32_from_bits(UINT32_C(0x7800000)); #endif - const float normalized_value = fp32_from_bits((two_w >> 4) + exp_offset) * exp_scale; + const float normalized_value = + fp32_from_bits((two_w >> 4) + exp_offset) * exp_scale; - const uint32_t magic_mask = UINT32_C(126) << 23; - const float magic_bias = 0.5f; - const float denormalized_value = fp32_from_bits((two_w >> 17) | magic_mask) - magic_bias; + const uint32_t magic_mask = UINT32_C(126) << 23; + const float magic_bias = 0.5f; + const float denormalized_value = + fp32_from_bits((two_w >> 17) | magic_mask) - magic_bias; - const uint32_t denormalized_cutoff = UINT32_C(1) << 27; - const uint32_t result = sign | - (two_w < denormalized_cutoff ? fp32_to_bits(denormalized_value) : fp32_to_bits(normalized_value)); - return fp32_from_bits(result); + const uint32_t denormalized_cutoff = UINT32_C(1) << 27; + const uint32_t result = + sign | (two_w < denormalized_cutoff ? fp32_to_bits(denormalized_value) + : fp32_to_bits(normalized_value)); + return fp32_from_bits(result); } uint16_t to_half(float f) { -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) || defined(__GNUC__) && !defined(__STRICT_ANSI__) - const float scale_to_inf = 0x1.0p+112f; - const float scale_to_zero = 0x1.0p-110f; +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) || \ + defined(__GNUC__) && !defined(__STRICT_ANSI__) + const float scale_to_inf = 0x1.0p+112f; + const float scale_to_zero = 0x1.0p-110f; #else - const float scale_to_inf = fp32_from_bits(UINT32_C(0x77800000)); - const float scale_to_zero = fp32_from_bits(UINT32_C(0x08800000)); + const float scale_to_inf = fp32_from_bits(UINT32_C(0x77800000)); + const float scale_to_zero = fp32_from_bits(UINT32_C(0x08800000)); #endif - float base = (fabsf(f) * scale_to_inf) * scale_to_zero; + float base = (fabsf(f) * scale_to_inf) * scale_to_zero; - const uint32_t w = fp32_to_bits(f); - const uint32_t shl1_w = w + w; - const uint32_t sign = w & UINT32_C(0x80000000); - uint32_t bias = shl1_w & UINT32_C(0xFF000000); - if (bias < UINT32_C(0x71000000)) { - bias = UINT32_C(0x71000000); - } + const uint32_t w = fp32_to_bits(f); + const uint32_t shl1_w = w + w; + const uint32_t sign = w & UINT32_C(0x80000000); + uint32_t bias = shl1_w & UINT32_C(0xFF000000); + if (bias < UINT32_C(0x71000000)) { + bias = UINT32_C(0x71000000); + } - base = fp32_from_bits((bias >> 1) + UINT32_C(0x07800000)) + base; - const uint32_t bits = fp32_to_bits(base); - const uint32_t exp_bits = (bits >> 13) & UINT32_C(0x00007C00); - const uint32_t mantissa_bits = bits & UINT32_C(0x00000FFF); - const uint32_t nonsign = exp_bits + mantissa_bits; - return (sign >> 16) | (shl1_w > UINT32_C(0xFF000000) ? UINT16_C(0x7E00) : nonsign); + base = fp32_from_bits((bias >> 1) + UINT32_C(0x07800000)) + base; + const uint32_t bits = fp32_to_bits(base); + const uint32_t exp_bits = (bits >> 13) & UINT32_C(0x00007C00); + const uint32_t mantissa_bits = bits & UINT32_C(0x00000FFF); + const uint32_t nonsign = exp_bits + mantissa_bits; + return (sign >> 16) | + (shl1_w > UINT32_C(0xFF000000) ? UINT16_C(0x7E00) : nonsign); } #ifdef TEST_MAIN #include int main(void) { - float f = 1.2345; - uint16_t half = to_half(f); - float f2 = from_half(half); - printf("%f %f\n", f, f2); - return 0; + float f = 1.2345; + uint16_t half = to_half(f); + float f2 = from_half(half); + printf("%f %f\n", f, f2); + return 0; } #endif diff --git a/fp16.h b/fp16.h index 10d2d82..1946811 100644 --- a/fp16.h +++ b/fp16.h @@ -2,6 +2,17 @@ #ifndef FP16_h #define FP16_h + +#ifdef __cplusplus +#include +extern "C" { +#endif + float from_half(uint16_t h); uint16_t to_half(float f); + +#ifdef __cplusplus +} +#endif + #endif diff --git a/gguflib.h b/gguflib.h index 4cb973a..18864e5 100644 --- a/gguflib.h +++ b/gguflib.h @@ -8,168 +8,174 @@ #ifndef GGUFLIB_H #define GGUFLIB_H +#ifdef __cplusplus + +#include #include +extern "C" { + +#endif /* ============================ Enums and structures ======================== */ /* Flags that can be used in different functions with the same meaning. */ -#define GGUF_NONE 0 // No flags. -#define GGUF_OVERWRITE (1<<0) // Overwrite the destination object. +#define GGUF_NONE 0 // No flags. +#define GGUF_OVERWRITE (1 << 0) // Overwrite the destination object. enum gguf_tensor_type { - GGUF_TYPE_F32 = 0, - GGUF_TYPE_F16 = 1, - GGUF_TYPE_Q4_0 = 2, - GGUF_TYPE_Q4_1 = 3, - // GGUF_TYPE_Q4_2 = 4, support has been removed - // GGUF_TYPE_Q4_3 (5) support has been removed - GGUF_TYPE_Q5_0 = 6, - GGUF_TYPE_Q5_1 = 7, - GGUF_TYPE_Q8_0 = 8, - GGUF_TYPE_Q8_1 = 9, - GGUF_TYPE_Q2_K = 10, - GGUF_TYPE_Q3_K = 11, - GGUF_TYPE_Q4_K = 12, - GGUF_TYPE_Q5_K = 13, - GGUF_TYPE_Q6_K = 14, - GGUF_TYPE_Q8_K = 15, - GGUF_TYPE_IQ2_XXS = 16, - GGUF_TYPE_IQ2_XS = 17, - GGUF_TYPE_IQ3_XXS = 18, - GGUF_TYPE_IQ1_S = 19, - GGUF_TYPE_IQ4_NL = 20, - GGUF_TYPE_IQ3_S = 21, - GGUF_TYPE_IQ2_S = 22, - GGUF_TYPE_IQ4_XS = 23, - GGUF_TYPE_I8 = 24, - GGUF_TYPE_I16 = 25, - GGUF_TYPE_I32 = 26, - GGUF_TYPE_I64 = 27, - GGUF_TYPE_F64 = 28, - GGUF_TYPE_IQ1_M = 29, - GGUF_TYPE_BF16 = 30, - GGUF_TYPE_COUNT, + GGUF_TYPE_F32 = 0, + GGUF_TYPE_F16 = 1, + GGUF_TYPE_Q4_0 = 2, + GGUF_TYPE_Q4_1 = 3, + // GGUF_TYPE_Q4_2 = 4, support has been removed + // GGUF_TYPE_Q4_3 (5) support has been removed + GGUF_TYPE_Q5_0 = 6, + GGUF_TYPE_Q5_1 = 7, + GGUF_TYPE_Q8_0 = 8, + GGUF_TYPE_Q8_1 = 9, + GGUF_TYPE_Q2_K = 10, + GGUF_TYPE_Q3_K = 11, + GGUF_TYPE_Q4_K = 12, + GGUF_TYPE_Q5_K = 13, + GGUF_TYPE_Q6_K = 14, + GGUF_TYPE_Q8_K = 15, + GGUF_TYPE_IQ2_XXS = 16, + GGUF_TYPE_IQ2_XS = 17, + GGUF_TYPE_IQ3_XXS = 18, + GGUF_TYPE_IQ1_S = 19, + GGUF_TYPE_IQ4_NL = 20, + GGUF_TYPE_IQ3_S = 21, + GGUF_TYPE_IQ2_S = 22, + GGUF_TYPE_IQ4_XS = 23, + GGUF_TYPE_I8 = 24, + GGUF_TYPE_I16 = 25, + GGUF_TYPE_I32 = 26, + GGUF_TYPE_I64 = 27, + GGUF_TYPE_F64 = 28, + GGUF_TYPE_IQ1_M = 29, + GGUF_TYPE_BF16 = 30, + GGUF_TYPE_COUNT, }; enum gguf_value_type { - // The value is a 8-bit unsigned integer. - GGUF_VALUE_TYPE_UINT8 = 0, - // The value is a 8-bit signed integer. - GGUF_VALUE_TYPE_INT8 = 1, - // The value is a 16-bit unsigned little-endian integer. - GGUF_VALUE_TYPE_UINT16 = 2, - // The value is a 16-bit signed little-endian integer. - GGUF_VALUE_TYPE_INT16 = 3, - // The value is a 32-bit unsigned little-endian integer. - GGUF_VALUE_TYPE_UINT32 = 4, - // The value is a 32-bit signed little-endian integer. - GGUF_VALUE_TYPE_INT32 = 5, - // The value is a 32-bit IEEE754 floating point number. - GGUF_VALUE_TYPE_FLOAT32 = 6, - // The value is a boolean. - // 1-byte value where 0 is false and 1 is true. - // Anything else is invalid, and should be treated as either the model - // being invalid or the reader being buggy. - GGUF_VALUE_TYPE_BOOL = 7, - // The value is a UTF-8 non-null-terminated string, with length prepended. - GGUF_VALUE_TYPE_STRING = 8, - // The value is an array of other values, with the length and type - // prepended. Arrays can be nested, and the length of the array is the - // number of elements in the array, not the number of bytes. - GGUF_VALUE_TYPE_ARRAY = 9, - // The value is a 64-bit unsigned little-endian integer. - GGUF_VALUE_TYPE_UINT64 = 10, - // The value is a 64-bit signed little-endian integer. - GGUF_VALUE_TYPE_INT64 = 11, - // The value is a 64-bit IEEE754 floating point number. - GGUF_VALUE_TYPE_FLOAT64 = 12, - // Special values used by the callbacks of gguf_do_with_value(). - GGUF_VALUE_TYPE_ARRAY_START = 100, - GGUF_VALUE_TYPE_ARRAY_END = 101 + // The value is a 8-bit unsigned integer. + GGUF_VALUE_TYPE_UINT8 = 0, + // The value is a 8-bit signed integer. + GGUF_VALUE_TYPE_INT8 = 1, + // The value is a 16-bit unsigned little-endian integer. + GGUF_VALUE_TYPE_UINT16 = 2, + // The value is a 16-bit signed little-endian integer. + GGUF_VALUE_TYPE_INT16 = 3, + // The value is a 32-bit unsigned little-endian integer. + GGUF_VALUE_TYPE_UINT32 = 4, + // The value is a 32-bit signed little-endian integer. + GGUF_VALUE_TYPE_INT32 = 5, + // The value is a 32-bit IEEE754 floating point number. + GGUF_VALUE_TYPE_FLOAT32 = 6, + // The value is a boolean. + // 1-byte value where 0 is false and 1 is true. + // Anything else is invalid, and should be treated as either the model + // being invalid or the reader being buggy. + GGUF_VALUE_TYPE_BOOL = 7, + // The value is a UTF-8 non-null-terminated string, with length prepended. + GGUF_VALUE_TYPE_STRING = 8, + // The value is an array of other values, with the length and type + // prepended. Arrays can be nested, and the length of the array is the + // number of elements in the array, not the number of bytes. + GGUF_VALUE_TYPE_ARRAY = 9, + // The value is a 64-bit unsigned little-endian integer. + GGUF_VALUE_TYPE_UINT64 = 10, + // The value is a 64-bit signed little-endian integer. + GGUF_VALUE_TYPE_INT64 = 11, + // The value is a 64-bit IEEE754 floating point number. + GGUF_VALUE_TYPE_FLOAT64 = 12, + // Special values used by the callbacks of gguf_do_with_value(). + GGUF_VALUE_TYPE_ARRAY_START = 100, + GGUF_VALUE_TYPE_ARRAY_END = 101 }; // A string in GGUF. struct gguf_string { - // The length of the string, in bytes. - uint64_t len; - // The string as a UTF-8 non-null-terminated string. - char string[]; + // The length of the string, in bytes. + uint64_t len; + // The string as a UTF-8 non-null-terminated string. + char string[]; }; // Union of possible values. union gguf_value { - uint8_t uint8; - int8_t int8; - uint16_t uint16; - int16_t int16; - uint32_t uint32; - int32_t int32; - float float32; - uint64_t uint64; - int64_t int64; - double float64; - uint8_t boolval; - struct gguf_string string; - struct { - // Any value type is valid, including arrays. - uint32_t type; - // Number of elements, not bytes - uint64_t len; - // The array of values follow... - } __attribute__((packed)) array; + uint8_t uint8; + int8_t int8; + uint16_t uint16; + int16_t int16; + uint32_t uint32; + int32_t int32; + float float32; + uint64_t uint64; + int64_t int64; + double float64; + uint8_t boolval; + struct gguf_string string; + struct { + // Any value type is valid, including arrays. + uint32_t type; + // Number of elements, not bytes + uint64_t len; + // The array of values follow... + } __attribute__((packed)) array; }; // Header struct gguf_header { - // Magic number to announce that this is a GGUF file. - // Must be `GGUF` at the byte level: `0x47` `0x47` `0x55` `0x46`. - uint32_t magic; - // The version of the format implemented. - // Must be `3` for version described in this spec. - uint32_t version; - // The number of tensors in the file. - // This is explicit, instead of being included in the metadata, to ensure - // it is always present for loading the tensors. - uint64_t tensor_count; - // The number of metadata key-value pairs. - uint64_t metadata_kv_count; + // Magic number to announce that this is a GGUF file. + // Must be `GGUF` at the byte level: `0x47` `0x47` `0x55` `0x46`. + uint32_t magic; + // The version of the format implemented. + // Must be `3` for version described in this spec. + uint32_t version; + // The number of tensors in the file. + // This is explicit, instead of being included in the metadata, to ensure + // it is always present for loading the tensors. + uint64_t tensor_count; + // The number of metadata key-value pairs. + uint64_t metadata_kv_count; }; /* Key representation in this library API. */ typedef struct { - const char *name; - size_t namelen; - uint32_t type; - union gguf_value *val; + const char *name; + size_t namelen; + uint32_t type; + union gguf_value *val; } gguf_key; /* Tensor representation in this library API. */ -#define GGUF_TENSOR_MAX_DIM 8 // Future-proof: actual limit is 4. +#define GGUF_TENSOR_MAX_DIM 8 // Future-proof: actual limit is 4. typedef struct { - const char *name; - size_t namelen; - uint32_t type; // Tensor type (enum gguf_tensor_type). - uint32_t ndim; // Number of dimensions of the tensor. - uint64_t dim[GGUF_TENSOR_MAX_DIM]; // Dimensions (Eg. [512, 1024, 1, 1]). - uint64_t offset; // Offset from start of file. - uint64_t bsize; // Total size in bytes. - uint64_t num_weights; // Total number of parameters. - uint8_t *weights_data; // Pointer to the mmaped file. + const char *name; + size_t namelen; + uint32_t type; // Tensor type (enum gguf_tensor_type). + uint32_t ndim; // Number of dimensions of the tensor. + uint64_t dim[GGUF_TENSOR_MAX_DIM]; // Dimensions (Eg. [512, 1024, 1, 1]). + uint64_t offset; // Offset from start of file. + uint64_t bsize; // Total size in bytes. + uint64_t num_weights; // Total number of parameters. + uint8_t *weights_data; // Pointer to the mmaped file. } gguf_tensor; /* The context you get after opening a GGUF file with gguf_init(). */ typedef struct { - int fd; - uint8_t *data; // Memory mapped data. - uint64_t size; // Total file size. - struct gguf_header *header; // GUFF file header info. - uint64_t left_kv; // Number of key-value pairs yet to read. - uint64_t left_tensors; // Number of tensors yet to read. - uint64_t off; // Offset of the next item to parse. - uint64_t data_off; // Offset of tensor data section. This - // is only set when all the kv/tensor header - // entries are processed. Initially 0. - uint64_t alignment; // File data alignment. Default: 32 bytes. + int fd; + uint8_t *data; // Memory mapped data. + uint64_t size; // Total file size. + struct gguf_header *header; // GUFF file header info. + uint64_t left_kv; // Number of key-value pairs yet to read. + uint64_t left_tensors; // Number of tensors yet to read. + uint64_t off; // Offset of the next item to parse. + uint64_t data_off; // Offset of tensor data section. This + // is only set when all the kv/tensor header + // entries are processed. Initially 0. + uint64_t alignment; // File data alignment. Default: 32 bytes. } gguf_ctx; /* =============================== Prototypes =============================== */ @@ -185,12 +191,17 @@ const char *gguf_get_value_type_name(uint32_t type); const char *gguf_get_tensor_type_name(uint32_t type); void gguf_do_with_value(gguf_ctx *ctx, uint32_t type, union gguf_value *val, void *privdata, uint64_t in_array, uint64_t array_len, - void(*callback)(void *privdata, uint32_t type, - union gguf_value *val, uint64_t in_array, - uint64_t array_len)); -void gguf_print_value(gguf_ctx *ctx, uint32_t type, union gguf_value *val, int full); -int gguf_append_kv(gguf_ctx *ctx, const char *keyname, uint64_t keylen, uint32_t type, void *val, uint64_t len); -int gguf_append_tensor_info(gguf_ctx *ctx, const char *tensorname, uint64_t namelen, uint32_t num_dim, uint64_t *dim, uint32_t type, uint64_t offset); + void (*callback)(void *privdata, uint32_t type, + union gguf_value *val, + uint64_t in_array, + uint64_t array_len)); +void gguf_print_value(gguf_ctx *ctx, uint32_t type, union gguf_value *val, + int full); +int gguf_append_kv(gguf_ctx *ctx, const char *keyname, uint64_t keylen, + uint32_t type, void *val, uint64_t len); +int gguf_append_tensor_info(gguf_ctx *ctx, const char *tensorname, + uint64_t namelen, uint32_t num_dim, uint64_t *dim, + uint32_t type, uint64_t offset); int gguf_append_tensor_data(gguf_ctx *ctx, void *tensor, uint64_t tensor_size); uint64_t gguf_get_alignment_padding(uint64_t alignment, uint64_t offset); void gguf_skip_key_values_section(gguf_ctx *ctx); @@ -198,4 +209,8 @@ float *gguf_tensor_to_float(gguf_tensor *tensor); int16_t *gguf_tensor_to_f16(gguf_tensor *tensor); int16_t *gguf_tensor_to_bf16(gguf_tensor *tensor); +#ifdef __cplusplus +} +#endif + #endif diff --git a/sds.h b/sds.h index adcc12c..9ab326d 100644 --- a/sds.h +++ b/sds.h @@ -33,186 +33,189 @@ #ifndef __SDS_H #define __SDS_H -#define SDS_MAX_PREALLOC (1024*1024) +#ifdef __cplusplus + +extern "C" { + +#endif + +#define SDS_MAX_PREALLOC (1024 * 1024) extern const char *SDS_NOINIT; -#include #include #include +#include typedef char *sds; /* Note: sdshdr5 is never used, we just access the flags byte directly. * However is here to document the layout of type 5 SDS strings. */ -struct __attribute__ ((__packed__)) sdshdr5 { - unsigned char flags; /* 3 lsb of type, and 5 msb of string length */ - char buf[]; +struct __attribute__((__packed__)) sdshdr5 { + unsigned char flags; /* 3 lsb of type, and 5 msb of string length */ + char buf[]; }; -struct __attribute__ ((__packed__)) sdshdr8 { - uint8_t len; /* used */ - uint8_t alloc; /* excluding the header and null terminator */ - unsigned char flags; /* 3 lsb of type, 5 unused bits */ - char buf[]; +struct __attribute__((__packed__)) sdshdr8 { + uint8_t len; /* used */ + uint8_t alloc; /* excluding the header and null terminator */ + unsigned char flags; /* 3 lsb of type, 5 unused bits */ + char buf[]; }; -struct __attribute__ ((__packed__)) sdshdr16 { - uint16_t len; /* used */ - uint16_t alloc; /* excluding the header and null terminator */ - unsigned char flags; /* 3 lsb of type, 5 unused bits */ - char buf[]; +struct __attribute__((__packed__)) sdshdr16 { + uint16_t len; /* used */ + uint16_t alloc; /* excluding the header and null terminator */ + unsigned char flags; /* 3 lsb of type, 5 unused bits */ + char buf[]; }; -struct __attribute__ ((__packed__)) sdshdr32 { - uint32_t len; /* used */ - uint32_t alloc; /* excluding the header and null terminator */ - unsigned char flags; /* 3 lsb of type, 5 unused bits */ - char buf[]; +struct __attribute__((__packed__)) sdshdr32 { + uint32_t len; /* used */ + uint32_t alloc; /* excluding the header and null terminator */ + unsigned char flags; /* 3 lsb of type, 5 unused bits */ + char buf[]; }; -struct __attribute__ ((__packed__)) sdshdr64 { - uint64_t len; /* used */ - uint64_t alloc; /* excluding the header and null terminator */ - unsigned char flags; /* 3 lsb of type, 5 unused bits */ - char buf[]; +struct __attribute__((__packed__)) sdshdr64 { + uint64_t len; /* used */ + uint64_t alloc; /* excluding the header and null terminator */ + unsigned char flags; /* 3 lsb of type, 5 unused bits */ + char buf[]; }; -#define SDS_TYPE_5 0 -#define SDS_TYPE_8 1 +#define SDS_TYPE_5 0 +#define SDS_TYPE_8 1 #define SDS_TYPE_16 2 #define SDS_TYPE_32 3 #define SDS_TYPE_64 4 #define SDS_TYPE_MASK 7 #define SDS_TYPE_BITS 3 -#define SDS_HDR_VAR(T,s) struct sdshdr##T *sh = (void*)((s)-(sizeof(struct sdshdr##T))); -#define SDS_HDR(T,s) ((struct sdshdr##T *)((s)-(sizeof(struct sdshdr##T)))) -#define SDS_TYPE_5_LEN(f) ((f)>>SDS_TYPE_BITS) +#define SDS_HDR_VAR(T, s) \ + struct sdshdr##T *sh = (struct sdshdr##T *)((s) - (sizeof(struct sdshdr##T))); +#define SDS_HDR(T, s) ((struct sdshdr##T *)((s) - (sizeof(struct sdshdr##T)))) +#define SDS_TYPE_5_LEN(f) ((f) >> SDS_TYPE_BITS) static inline size_t sdslen(const sds s) { - unsigned char flags = s[-1]; - switch(flags&SDS_TYPE_MASK) { - case SDS_TYPE_5: - return SDS_TYPE_5_LEN(flags); - case SDS_TYPE_8: - return SDS_HDR(8,s)->len; - case SDS_TYPE_16: - return SDS_HDR(16,s)->len; - case SDS_TYPE_32: - return SDS_HDR(32,s)->len; - case SDS_TYPE_64: - return SDS_HDR(64,s)->len; - } - return 0; + unsigned char flags = s[-1]; + switch (flags & SDS_TYPE_MASK) { + case SDS_TYPE_5: + return SDS_TYPE_5_LEN(flags); + case SDS_TYPE_8: + return SDS_HDR(8, s)->len; + case SDS_TYPE_16: + return SDS_HDR(16, s)->len; + case SDS_TYPE_32: + return SDS_HDR(32, s)->len; + case SDS_TYPE_64: + return SDS_HDR(64, s)->len; + } + return 0; } static inline size_t sdsavail(const sds s) { - unsigned char flags = s[-1]; - switch(flags&SDS_TYPE_MASK) { - case SDS_TYPE_5: { - return 0; - } - case SDS_TYPE_8: { - SDS_HDR_VAR(8,s); - return sh->alloc - sh->len; - } - case SDS_TYPE_16: { - SDS_HDR_VAR(16,s); - return sh->alloc - sh->len; - } - case SDS_TYPE_32: { - SDS_HDR_VAR(32,s); - return sh->alloc - sh->len; - } - case SDS_TYPE_64: { - SDS_HDR_VAR(64,s); - return sh->alloc - sh->len; - } - } + unsigned char flags = s[-1]; + switch (flags & SDS_TYPE_MASK) { + case SDS_TYPE_5: { return 0; + } + case SDS_TYPE_8: { + SDS_HDR_VAR(8, s); + return sh->alloc - sh->len; + } + case SDS_TYPE_16: { + SDS_HDR_VAR(16, s); + return sh->alloc - sh->len; + } + case SDS_TYPE_32: { + SDS_HDR_VAR(32, s); + return sh->alloc - sh->len; + } + case SDS_TYPE_64: { + SDS_HDR_VAR(64, s); + return sh->alloc - sh->len; + } + } + return 0; } static inline void sdssetlen(sds s, size_t newlen) { - unsigned char flags = s[-1]; - switch(flags&SDS_TYPE_MASK) { - case SDS_TYPE_5: - { - unsigned char *fp = ((unsigned char*)s)-1; - *fp = SDS_TYPE_5 | (newlen << SDS_TYPE_BITS); - } - break; - case SDS_TYPE_8: - SDS_HDR(8,s)->len = newlen; - break; - case SDS_TYPE_16: - SDS_HDR(16,s)->len = newlen; - break; - case SDS_TYPE_32: - SDS_HDR(32,s)->len = newlen; - break; - case SDS_TYPE_64: - SDS_HDR(64,s)->len = newlen; - break; - } + unsigned char flags = s[-1]; + switch (flags & SDS_TYPE_MASK) { + case SDS_TYPE_5: { + unsigned char *fp = ((unsigned char *)s) - 1; + *fp = SDS_TYPE_5 | (newlen << SDS_TYPE_BITS); + } break; + case SDS_TYPE_8: + SDS_HDR(8, s)->len = newlen; + break; + case SDS_TYPE_16: + SDS_HDR(16, s)->len = newlen; + break; + case SDS_TYPE_32: + SDS_HDR(32, s)->len = newlen; + break; + case SDS_TYPE_64: + SDS_HDR(64, s)->len = newlen; + break; + } } static inline void sdsinclen(sds s, size_t inc) { - unsigned char flags = s[-1]; - switch(flags&SDS_TYPE_MASK) { - case SDS_TYPE_5: - { - unsigned char *fp = ((unsigned char*)s)-1; - unsigned char newlen = SDS_TYPE_5_LEN(flags)+inc; - *fp = SDS_TYPE_5 | (newlen << SDS_TYPE_BITS); - } - break; - case SDS_TYPE_8: - SDS_HDR(8,s)->len += inc; - break; - case SDS_TYPE_16: - SDS_HDR(16,s)->len += inc; - break; - case SDS_TYPE_32: - SDS_HDR(32,s)->len += inc; - break; - case SDS_TYPE_64: - SDS_HDR(64,s)->len += inc; - break; - } + unsigned char flags = s[-1]; + switch (flags & SDS_TYPE_MASK) { + case SDS_TYPE_5: { + unsigned char *fp = ((unsigned char *)s) - 1; + unsigned char newlen = SDS_TYPE_5_LEN(flags) + inc; + *fp = SDS_TYPE_5 | (newlen << SDS_TYPE_BITS); + } break; + case SDS_TYPE_8: + SDS_HDR(8, s)->len += inc; + break; + case SDS_TYPE_16: + SDS_HDR(16, s)->len += inc; + break; + case SDS_TYPE_32: + SDS_HDR(32, s)->len += inc; + break; + case SDS_TYPE_64: + SDS_HDR(64, s)->len += inc; + break; + } } /* sdsalloc() = sdsavail() + sdslen() */ static inline size_t sdsalloc(const sds s) { - unsigned char flags = s[-1]; - switch(flags&SDS_TYPE_MASK) { - case SDS_TYPE_5: - return SDS_TYPE_5_LEN(flags); - case SDS_TYPE_8: - return SDS_HDR(8,s)->alloc; - case SDS_TYPE_16: - return SDS_HDR(16,s)->alloc; - case SDS_TYPE_32: - return SDS_HDR(32,s)->alloc; - case SDS_TYPE_64: - return SDS_HDR(64,s)->alloc; - } - return 0; + unsigned char flags = s[-1]; + switch (flags & SDS_TYPE_MASK) { + case SDS_TYPE_5: + return SDS_TYPE_5_LEN(flags); + case SDS_TYPE_8: + return SDS_HDR(8, s)->alloc; + case SDS_TYPE_16: + return SDS_HDR(16, s)->alloc; + case SDS_TYPE_32: + return SDS_HDR(32, s)->alloc; + case SDS_TYPE_64: + return SDS_HDR(64, s)->alloc; + } + return 0; } static inline void sdssetalloc(sds s, size_t newlen) { - unsigned char flags = s[-1]; - switch(flags&SDS_TYPE_MASK) { - case SDS_TYPE_5: - /* Nothing to do, this type has no total allocation info. */ - break; - case SDS_TYPE_8: - SDS_HDR(8,s)->alloc = newlen; - break; - case SDS_TYPE_16: - SDS_HDR(16,s)->alloc = newlen; - break; - case SDS_TYPE_32: - SDS_HDR(32,s)->alloc = newlen; - break; - case SDS_TYPE_64: - SDS_HDR(64,s)->alloc = newlen; - break; - } + unsigned char flags = s[-1]; + switch (flags & SDS_TYPE_MASK) { + case SDS_TYPE_5: + /* Nothing to do, this type has no total allocation info. */ + break; + case SDS_TYPE_8: + SDS_HDR(8, s)->alloc = newlen; + break; + case SDS_TYPE_16: + SDS_HDR(16, s)->alloc = newlen; + break; + case SDS_TYPE_32: + SDS_HDR(32, s)->alloc = newlen; + break; + case SDS_TYPE_64: + SDS_HDR(64, s)->alloc = newlen; + break; + } } sds sdsnewlen(const void *init, size_t initlen); @@ -241,7 +244,8 @@ void sdsrange(sds s, ssize_t start, ssize_t end); void sdsupdatelen(sds s); void sdsclear(sds s); int sdscmp(const sds s1, const sds s2); -sds *sdssplitlen(const char *s, ssize_t len, const char *sep, int seplen, int *count); +sds *sdssplitlen(const char *s, ssize_t len, const char *sep, int seplen, + int *count); void sdsfreesplitres(sds *tokens, int count); void sdstolower(sds s); void sdstoupper(sds s); @@ -271,4 +275,8 @@ void sds_free(void *ptr); int sdsTest(int argc, char *argv[]); #endif +#ifdef __cplusplus +} +#endif + #endif