diff --git a/Cytoplasm/src/Array.c b/Cytoplasm/src/Array.c index 948d9d9..f987b4f 100644 --- a/Cytoplasm/src/Array.c +++ b/Cytoplasm/src/Array.c @@ -259,7 +259,7 @@ ArrayQuickSort(Array * array, size_t low, size_t high, int (*compare) (void *, v { size_t pi = ArrayPartition(array, low, high, compare); - ArrayQuickSort(array, low, pi - 1, compare); + ArrayQuickSort(array, low, pi ? pi - 1 : 0, compare); ArrayQuickSort(array, pi + 1, high, compare); } } @@ -271,7 +271,7 @@ ArraySort(Array * array, int (*compare) (void *, void *)) { return; } - ArrayQuickSort(array, 0, array->size, compare); + ArrayQuickSort(array, 0, array->size - 1, compare); } /* Even though the following operations could be done using only the diff --git a/TODO.txt b/TODO.txt index 2afc7d7..dc32831 100644 --- a/TODO.txt +++ b/TODO.txt @@ -16,8 +16,9 @@ Milestone: v0.4.0 [~] Client-Server API [~] 6: Filtering + [ ] Finish validating filters before saving them. [~] 7: Events - [ ] Compute size of JSON object in Canonical JSON + [x] Compute size of JSON object in Canonical JSON [x] Rename Sha2.h to just Sha; add Sha1() function [x] Make Sha256() return raw bytes; add function to convert to hex string. @@ -44,6 +45,7 @@ Milestone: v0.4.0 use the default. This will make debugging a lot easier. [ ] Make sure admin registration token is printed to log, not stdout. Unless they are the same, of course. +[ ] Fix Json UTF-8 handling. Milestone: v0.5.0 ----------------- diff --git a/src/CanonicalJson.c b/src/CanonicalJson.c index c1e74f5..065868f 100644 --- a/src/CanonicalJson.c +++ b/src/CanonicalJson.c @@ -30,29 +30,32 @@ #include #include -int +static int CanonicalJsonKeyCompare(void *k1, void *k2) { return strcmp((char *) k1, (char *) k2); } -static void +int CanonicalJsonEncodeValue(JsonValue * value, Stream * out) { Array *arr; size_t i, len; + int length = 0; + /* Override object type to encode using the canonical functions */ switch (JsonValueType(value)) { case JSON_OBJECT: - CanonicalJsonEncode(JsonValueAsObject(value), out); + length += CanonicalJsonEncode(JsonValueAsObject(value), out); break; case JSON_ARRAY: arr = JsonValueAsArray(value); len = ArraySize(arr); StreamPutc(out, '['); + length++; for (i = 0; i < len; i++) { @@ -64,19 +67,23 @@ CanonicalJsonEncodeValue(JsonValue * value, Stream * out) continue; } - CanonicalJsonEncodeValue(aVal, out); + length += CanonicalJsonEncodeValue(aVal, out); if (i < len - 1) { StreamPutc(out, ','); + length++; } } StreamPutc(out, ']'); + length++; break; default: - JsonEncodeValue(value, out, JSON_DEFAULT); + length += JsonEncodeValue(value, out, JSON_DEFAULT); break; } + + return length; } int @@ -87,16 +94,17 @@ CanonicalJsonEncode(HashMap * object, Stream * out) Array *keys; size_t i; size_t keyCount; + int length; - if (!object || !out) + if (!object) { - return 0; + return -1; } keys = ArrayCreate(); if (!keys) { - return 0; + return -1; } while (HashMapIterate(object, &key, (void **) &value)) @@ -106,7 +114,11 @@ CanonicalJsonEncode(HashMap * object, Stream * out) ArraySort(keys, CanonicalJsonKeyCompare); + /* The total number of bytes written */ + length = 0; + StreamPutc(out, '{'); + length++; keyCount = ArraySize(keys); for (i = 0; i < keyCount; i++) @@ -128,18 +140,21 @@ CanonicalJsonEncode(HashMap * object, Stream * out) continue; } - JsonEncodeString(key, out); + length += JsonEncodeString(key, out); StreamPutc(out, ':'); - CanonicalJsonEncodeValue(value, out); + length++; + length += CanonicalJsonEncodeValue(value, out); if (i < keyCount - 1) { StreamPutc(out, ','); + length++; } } StreamPutc(out, '}'); + length++; ArrayFree(keys); - return 1; + return length; } diff --git a/src/include/CanonicalJson.h b/src/include/CanonicalJson.h index 92eefa4..815908e 100644 --- a/src/include/CanonicalJson.h +++ b/src/include/CanonicalJson.h @@ -55,6 +55,7 @@ #include #include +#include /** * Encode a JSON object following the rules of Canonical JSON. See the @@ -71,25 +72,19 @@ * .Fn JsonEncode , * because it is much cheaper both in terms of memory and CPU time. * .Pp - * This function returns a boolean value indicating whether or not the - * operation was sucessful. This function will fail only if NULL was - * given for any parameter. Otherwise, if an invalid pointer is given, - * undefined behavior results. + * This function returns the number of bytes written to the + * stream, just like + * .Fn JsonEncode . */ extern int CanonicalJsonEncode(HashMap *, Stream *); /** - * This function encodes a JSON object to a string. - * .Xr Json 3 - * doesn't have any way to send JSON to a string, because there's - * absolutely no reason to handle JSON strings in most cases. However, - * the sole reason Canonical JSON exists is so that JSON objects can - * be signed in a consisten way. Thus, it is likely you need a string - * to pass to the signing function. - * .Pp - * This function returns a C string containing the canonical JSON - * representation of the given object, or NULL if the encoding failed. + * Encode a JSON value following the rules of Canonical JSON. + * See the documentation for + * .Fn JsonEncodeValue , + * documented in + * .Xr Json 3 . */ -extern char * CanonicalJsonEncodeToString(HashMap *); +extern int CanonicalJsonEncodeValue(JsonValue *, Stream *); #endif /* TELODENDRIA_CANONICALJSON_H */ diff --git a/tools/bin/td b/tools/bin/td index 27c3973..3f17520 100644 --- a/tools/bin/td +++ b/tools/bin/td @@ -183,7 +183,7 @@ recipe_build() { if [ $(mod_time "$src") -ge $(mod_time "$out") ] || [ $do_rebuild -eq 1 ]; then echo "CC $(basename $out)" mkdir -p "$(dirname $out)" - if ! $CC $CFLAGS -o "$out" "$src" ${CYTOPLASM_FLAGS} ${LDFLAGS} ${STATIC}; then + if ! $CC $CFLAGS -o "$out" "$src" $objs ${CYTOPLASM_FLAGS} ${LDFLAGS} ${STATIC}; then exit 1 fi fi diff --git a/tools/src/http-debug-server.c b/tools/src/http-debug-server.c index c51b45e..5bc6644 100644 --- a/tools/src/http-debug-server.c +++ b/tools/src/http-debug-server.c @@ -34,74 +34,6 @@ #include #include -static void -HexDump(size_t off, char *hexBuf, char *asciiBuf, void *args) -{ - char *fmt; - - (void) args; - - if (hexBuf && asciiBuf) - { - fmt = "%04lx: | %s | %s |"; - } - else - { - fmt = "%04lx"; - } - - Log(LOG_DEBUG, fmt, off, hexBuf, asciiBuf); -} - -void -TelodendriaMemoryHook(MemoryAction a, MemoryInfo * i, void *args) -{ - char *action; - int err = 0; - - (void) args; - - switch (a) - { - case MEMORY_ALLOCATE: - action = "Allocated"; - break; - case MEMORY_REALLOCATE: - action = "Re-allocated"; - break; - case MEMORY_FREE: - action = "Freed"; - break; - case MEMORY_BAD_POINTER: - err = 1; - action = "Bad pointer to"; - break; - case MEMORY_CORRUPTED: - err = 1; - action = "Corrupted block of"; - break; - default: - action = "Unknown operation on"; - break; - } - - Log(err ? LOG_ERR : LOG_DEBUG, - "%s:%d: %s %lu bytes of memory at %p.", - MemoryInfoGetFile(i), MemoryInfoGetLine(i), - action, MemoryInfoGetSize(i), - MemoryInfoGetPointer(i)); - - if (a != MEMORY_ALLOCATE && a != MEMORY_REALLOCATE) - { - MemoryHexDump(i, HexDump, NULL); - } - - if (err) - { - raise(SIGINT); - } -} - static HttpServer *server = NULL; static void diff --git a/tools/src/json.c b/tools/src/json.c index 546334f..27be1d3 100644 --- a/tools/src/json.c +++ b/tools/src/json.c @@ -30,7 +30,9 @@ #include #include #include + #include +#include #define FLAG_ENCODE (1 << 0) #define FLAG_SELECT (1 << 1) @@ -42,7 +44,7 @@ usage(char *prog) } static void -query(char *select, HashMap * json) +query(char *select, HashMap * json, int canonical) { char *key; JsonValue *rootVal = JsonValueObject(json); @@ -170,7 +172,15 @@ query(char *select, HashMap * json) if (val) { - JsonEncodeValue(val, StreamStdout(), JSON_PRETTY); + if (canonical) + { + CanonicalJsonEncodeValue(val, StreamStdout()); + } + else + { + JsonEncodeValue(val, StreamStdout(), JSON_PRETTY); + } + StreamPutc(StreamStdout(), '\n'); } @@ -182,11 +192,19 @@ query(char *select, HashMap * json) } static void -encode(char *str) +encode(char *str, int canonical) { JsonValue *val = JsonValueString(str); - JsonEncodeValue(val, StreamStdout(), JSON_DEFAULT); + if (canonical) + { + CanonicalJsonEncodeValue(val, StreamStdout()); + } + else + { + JsonEncodeValue(val, StreamStdout(), JSON_DEFAULT); + } + JsonValueFree(val); StreamPutc(StreamStdout(), '\n'); } @@ -200,8 +218,10 @@ Main(Array * args) char *input = NULL; ArgParseState arg; + int canonical = 0; + ArgParseStateInit(&arg); - while ((ch = ArgParse(&arg, args, "s:e:")) != -1) + while ((ch = ArgParse(&arg, args, "cs:e:")) != -1) { switch (ch) { @@ -213,6 +233,9 @@ Main(Array * args) flag = FLAG_ENCODE; input = arg.optArg; break; + case 'c': + canonical = 1; + break; default: usage(ArrayGet(args, 0)); return 1; @@ -233,13 +256,21 @@ Main(Array * args) switch (flag) { case FLAG_SELECT: - query(input, json); /* This will implicitly free json */ + query(input, json, canonical); /* This will implicitly free json */ break; case FLAG_ENCODE: - encode(input); + encode(input, canonical); break; default: - JsonEncode(json, StreamStdout(), JSON_PRETTY); + if (canonical) + { + CanonicalJsonEncode(json, StreamStdout()); + } + else + { + JsonEncode(json, StreamStdout(), JSON_PRETTY); + } + StreamPutc(StreamStdout(), '\n'); JsonFree(json); break;