forked from Telodendria/Telodendria
Fix CanonicalJson and ArraySort.
This commit is contained in:
parent
1fa07d2d3c
commit
539fde773f
7 changed files with 81 additions and 106 deletions
|
@ -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
|
||||
|
|
4
TODO.txt
4
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
|
||||
-----------------
|
||||
|
|
|
@ -30,29 +30,32 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -55,6 +55,7 @@
|
|||
|
||||
#include <HashMap.h>
|
||||
#include <Stream.h>
|
||||
#include <Json.h>
|
||||
|
||||
/**
|
||||
* 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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -34,74 +34,6 @@
|
|||
#include <Db.h>
|
||||
#include <Json.h>
|
||||
|
||||
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
|
||||
|
|
|
@ -30,7 +30,9 @@
|
|||
#include <HashMap.h>
|
||||
#include <Str.h>
|
||||
#include <Memory.h>
|
||||
|
||||
#include <Json.h>
|
||||
#include <CanonicalJson.h>
|
||||
|
||||
#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;
|
||||
|
|
Loading…
Reference in a new issue