Json now uses Int64 for integers.

This should fix all timestamp errors on 32-bit systems in Cytoplasm and
Telodendria.
This commit is contained in:
Jordan Bancino 2023-08-13 03:11:40 +00:00
parent 2382638005
commit 1c32e18c74
17 changed files with 153 additions and 78 deletions

View file

@ -27,6 +27,7 @@
#include <Str.h> #include <Str.h>
#include <Util.h> #include <Util.h>
#include <Int.h> #include <Int.h>
#include <Int64.h>
#include <stdio.h> #include <stdio.h>
#include <stddef.h> #include <stddef.h>
@ -43,7 +44,7 @@ struct JsonValue
HashMap *object; HashMap *object;
Array *array; Array *array;
char *string; char *string;
long integer; Int64 integer;
double floating; double floating;
int boolean:1; int boolean:1;
} as; } as;
@ -200,7 +201,7 @@ JsonValueAsString(JsonValue * value)
} }
JsonValue * JsonValue *
JsonValueInteger(long integer) JsonValueInteger(Int64 integer)
{ {
JsonValue *value; JsonValue *value;
@ -216,12 +217,12 @@ JsonValueInteger(long integer)
return value; return value;
} }
long Int64
JsonValueAsInteger(JsonValue * value) JsonValueAsInteger(JsonValue * value)
{ {
if (!value || value->type != JSON_INTEGER) if (!value || value->type != JSON_INTEGER)
{ {
return 0; return Int64Create(0, 0);
} }
return value->as.integer; return value->as.integer;
@ -605,6 +606,8 @@ JsonEncodeValue(JsonValue * value, Stream * out, int level)
Array *arr; Array *arr;
int length = 0; int length = 0;
char ibuf[INT64_STRBUF];
switch (value->type) switch (value->type)
{ {
case JSON_OBJECT: case JSON_OBJECT:
@ -641,7 +644,8 @@ JsonEncodeValue(JsonValue * value, Stream * out, int level)
length += JsonEncodeString(value->as.string, out); length += JsonEncodeString(value->as.string, out);
break; break;
case JSON_INTEGER: case JSON_INTEGER:
length += StreamPrintf(out, "%ld", value->as.integer); Int64Str(value->as.integer, 10, ibuf, INT64_STRBUF);
length += StreamPrintf(out, "%s", ibuf);
break; break;
case JSON_FLOAT: case JSON_FLOAT:
length += StreamPrintf(out, "%f", value->as.floating); length += StreamPrintf(out, "%f", value->as.floating);
@ -979,7 +983,7 @@ JsonTokenSeek(JsonParserState * state)
break; break;
} }
if (state->tokenLen >= allocated) if (state->tokenLen + 1 >= allocated)
{ {
char *tmp; char *tmp;
@ -1119,6 +1123,10 @@ JsonDecodeValue(JsonParserState * state)
JsonValue *value; JsonValue *value;
char *strValue; char *strValue;
Int64 iValue;
size_t i;
int neg;
switch (state->tokenType) switch (state->tokenType)
{ {
case TOKEN_OBJECT_OPEN: case TOKEN_OBJECT_OPEN:
@ -1138,7 +1146,32 @@ JsonDecodeValue(JsonParserState * state)
Free(strValue); Free(strValue);
break; break;
case TOKEN_INTEGER: case TOKEN_INTEGER:
value = JsonValueInteger(atol(state->token)); iValue = Int64Create(0, 0);
i = 0;
neg = 0;
while (state->token[i])
{
int d;
if (i == 0 && !neg && state->token[i] == '-')
{
neg = 1;
i++;
continue;
}
d = state->token[i] - '0';
iValue = Int64Mul(iValue, Int64Create(0, 10));
iValue = Int64Add(iValue, Int64Create(0, d));
i++;
}
if (neg)
{
iValue = Int64Neg(iValue);
}
value = JsonValueInteger(iValue);
break; break;
case TOKEN_FLOAT: case TOKEN_FLOAT:
value = JsonValueFloat(atof(state->token)); value = JsonValueFloat(atof(state->token));

View file

@ -122,25 +122,11 @@ typedef signed long Int64;
#define Int64Neg(x) (Int64Add(Int64Not(x), Int64Create(0, 1))) #define Int64Neg(x) (Int64Add(Int64Not(x), Int64Create(0, 1)))
/** /**
* For platforms that do not have a native integer large enough to * The internal bit representation of a signed integer is identical
* store a 64 bit integer, this struct is used. i[0] contains the low * to an unsigned integer, the difference is in the algorithms and
* bits of integer, and i[1] contains the high bits of the integer. * the way the bits are interpreted.
* .Pp
* This struct should not be accessed directly, because UInt64 may not
* actually be this struct, it might be an actual integer type. For
* maximum portability, only use the functions defined here to
* manipulate 64 bit integers.
*/ */
typedef struct typedef UInt64 Int64;
{
/*
* Unsigned, because we will deal with the sign bits ourselves.
* This also allows well-defined casting between signed and
* unsigned integers.
*/
UInt32 i[2];
} Int64;
/** /**
* Create a new signed 64 bit integer using the given high and low * Create a new signed 64 bit integer using the given high and low

View file

@ -71,6 +71,7 @@
#include <HashMap.h> #include <HashMap.h>
#include <Array.h> #include <Array.h>
#include <Stream.h> #include <Stream.h>
#include <Int64.h>
#include <stdio.h> #include <stdio.h>
#include <stddef.h> #include <stddef.h>
@ -101,7 +102,7 @@ typedef enum JsonType
JSON_OBJECT, /* Maps to a HashMap of JsonValues */ JSON_OBJECT, /* Maps to a HashMap of JsonValues */
JSON_ARRAY, /* Maps to an Array of JsonValues */ JSON_ARRAY, /* Maps to an Array of JsonValues */
JSON_STRING, /* Maps to a null-terminated C string */ JSON_STRING, /* Maps to a null-terminated C string */
JSON_INTEGER, /* Maps to a C long */ JSON_INTEGER, /* Maps to an Int64 */
JSON_FLOAT, /* Maps to a C double */ JSON_FLOAT, /* Maps to a C double */
JSON_BOOLEAN /* Maps to a C integer of either 0 or 1 */ JSON_BOOLEAN /* Maps to a C integer of either 0 or 1 */
} JsonType; } JsonType;
@ -151,7 +152,7 @@ extern char * JsonValueAsString(JsonValue *);
* Encode a number as a JSON value that can be added to an object or * Encode a number as a JSON value that can be added to an object or
* an array. * an array.
*/ */
extern JsonValue * JsonValueInteger(long); extern JsonValue * JsonValueInteger(Int64);
/** /**
* Unwrap a JSON value that represents a number. This function will * Unwrap a JSON value that represents a number. This function will
@ -159,7 +160,7 @@ extern JsonValue * JsonValueInteger(long);
* misleading. Check the type of the value before making assumptions * misleading. Check the type of the value before making assumptions
* about its value. * about its value.
*/ */
extern long JsonValueAsInteger(JsonValue *); extern Int64 JsonValueAsInteger(JsonValue *);
/** /**
* Encode a floating point number as a JSON value that can be added * Encode a floating point number as a JSON value that can be added

View file

@ -443,6 +443,7 @@ Main(Array * args)
StreamPrintf(headerFile, "#include <Array.h>\n"); StreamPrintf(headerFile, "#include <Array.h>\n");
StreamPrintf(headerFile, "#include <HashMap.h>\n"); StreamPrintf(headerFile, "#include <HashMap.h>\n");
StreamPrintf(headerFile, "#include <Int64.h>\n");
StreamPutc(headerFile, '\n'); StreamPutc(headerFile, '\n');
@ -491,7 +492,7 @@ Main(Array * args)
} }
else if (StrEquals(fieldType, "integer")) else if (StrEquals(fieldType, "integer"))
{ {
cType = "long"; cType = "Int64";
} }
else if (StrEquals(fieldType, "boolean")) else if (StrEquals(fieldType, "boolean"))
{ {
@ -664,7 +665,7 @@ Main(Array * args)
if (StrEquals(fieldType, "integer")) if (StrEquals(fieldType, "integer"))
{ {
cType = "long"; cType = "Int64";
} }
else if (StrEquals(fieldType, "float")) else if (StrEquals(fieldType, "float"))
{ {
@ -907,7 +908,7 @@ Main(Array * args)
if (StrEquals(fieldType, "integer")) if (StrEquals(fieldType, "integer"))
{ {
cType = "long"; cType = "Int64";
} }
else if (StrEquals(fieldType, "float")) else if (StrEquals(fieldType, "float"))
{ {

View file

@ -30,6 +30,7 @@
#include <Db.h> #include <Db.h>
#include <HttpServer.h> #include <HttpServer.h>
#include <Log.h> #include <Log.h>
#include <Int64.h>
#include <stdlib.h> #include <stdlib.h>
#include <ctype.h> #include <ctype.h>
@ -82,7 +83,7 @@
tConfig->err = "Expected " key " to be of type JSON_INTEGER"; \ tConfig->err = "Expected " key " to be of type JSON_INTEGER"; \
goto error; \ goto error; \
} \ } \
into = JsonValueAsInteger(value); \ into = Int64Low(JsonValueAsInteger(value)); \
} \ } \
else \ else \
{ \ { \
@ -146,9 +147,9 @@ ConfigParseListen(Config * tConfig, Array * listen)
obj = JsonValueAsObject(val); obj = JsonValueAsObject(val);
serverCfg->port = JsonValueAsInteger(HashMapGet(obj, "port")); serverCfg->port = Int64Low(JsonValueAsInteger(HashMapGet(obj, "port")));
serverCfg->threads = JsonValueAsInteger(HashMapGet(obj, "threads")); serverCfg->threads = Int64Low(JsonValueAsInteger(HashMapGet(obj, "threads")));
serverCfg->maxConnections = JsonValueAsInteger(HashMapGet(obj, "maxConnections")); serverCfg->maxConnections = Int64Low(JsonValueAsInteger(HashMapGet(obj, "maxConnections")));
if (!serverCfg->port) if (!serverCfg->port)
{ {
@ -450,7 +451,7 @@ ConfigCreateDefault(Db * db)
listeners = ArrayCreate(); listeners = ArrayCreate();
listen = HashMapCreate(); listen = HashMapCreate();
HashMapSet(listen, "port", JsonValueInteger(8008)); HashMapSet(listen, "port", JsonValueInteger(Int64Create(0, 8008)));
HashMapSet(listen, "tls", JsonValueBoolean(0)); HashMapSet(listen, "tls", JsonValueBoolean(0));
ArrayAdd(listeners, JsonValueObject(listen)); ArrayAdd(listeners, JsonValueObject(listen));
HashMapSet(json, "listen", JsonValueArray(listeners)); HashMapSet(json, "listen", JsonValueArray(listeners));

View file

@ -26,7 +26,7 @@
#include <Schema/Filter.h> #include <Schema/Filter.h>
HashMap * HashMap *
FilterApply(Filter *filter, HashMap *event) FilterApply(Filter * filter, HashMap * event)
{ {
return NULL; return NULL;
} }

View file

@ -247,7 +247,7 @@ start:
} }
token = StrRandom(32); token = StrRandom(32);
info = RegTokenCreate(matrixArgs.db, token, NULL, 0, 1, USER_ALL); info = RegTokenCreate(matrixArgs.db, token, NULL, UInt64Create(0, 0), Int64Create(0, 1), USER_ALL);
if (!info) if (!info)
{ {
Free(token); Free(token);
@ -259,8 +259,8 @@ start:
RegTokenClose(info); RegTokenClose(info);
RegTokenFree(info); RegTokenFree(info);
/* Don't free token, because we need to print it when logging is /* Don't free token, because we need to print it when logging
* set up. */ * is set up. */
} }
Log(LOG_NOTICE, "Loading configuration..."); Log(LOG_NOTICE, "Loading configuration...");
@ -339,7 +339,8 @@ start:
goto finish; goto finish;
} }
/* If a token was created with a default config, print it to the log */ /* If a token was created with a default config, print it to the
* log */
if (token) if (token)
{ {
Log(LOG_NOTICE, "Admin Registration token: %s", token); Log(LOG_NOTICE, "Admin Registration token: %s", token);
@ -384,14 +385,14 @@ start:
if (serverCfg->flags & HTTP_FLAG_TLS) if (serverCfg->flags & HTTP_FLAG_TLS)
{ {
if (!UtilLastModified(serverCfg->tlsCert)) if (UInt64Eq(UtilLastModified(serverCfg->tlsCert), UInt64Create(0, 0)))
{ {
Log(LOG_ERR, "%s: %s", strerror(errno), serverCfg->tlsCert); Log(LOG_ERR, "%s: %s", strerror(errno), serverCfg->tlsCert);
exit = EXIT_FAILURE; exit = EXIT_FAILURE;
goto finish; goto finish;
} }
if (!UtilLastModified(serverCfg->tlsKey)) if (UInt64Eq(UtilLastModified(serverCfg->tlsKey), UInt64Create(0, 0)))
{ {
Log(LOG_ERR, "%s: %s", strerror(errno), serverCfg->tlsKey); Log(LOG_ERR, "%s: %s", strerror(errno), serverCfg->tlsKey);
exit = EXIT_FAILURE; exit = EXIT_FAILURE;

View file

@ -31,14 +31,15 @@
#include <Util.h> #include <Util.h>
#include <Str.h> #include <Str.h>
#include <User.h> #include <User.h>
#include <Int64.h>
int int
RegTokenValid(RegTokenInfo * token) RegTokenValid(RegTokenInfo * token)
{ {
HashMap *tokenJson; HashMap *tokenJson;
int uses, used; Int64 uses, used;
unsigned long expiration; UInt64 expiration;
if (!token || !RegTokenExists(token->db, token->name)) if (!token || !RegTokenExists(token->db, token->name))
{ {
@ -50,8 +51,9 @@ RegTokenValid(RegTokenInfo * token)
used = JsonValueAsInteger(HashMapGet(tokenJson, "used")); used = JsonValueAsInteger(HashMapGet(tokenJson, "used"));
expiration = JsonValueAsInteger(HashMapGet(tokenJson, "expires_on")); expiration = JsonValueAsInteger(HashMapGet(tokenJson, "expires_on"));
return (!expiration || (UtilServerTs() <= expiration)) && return (UInt64Eq(expiration, UInt64Create(0, 0)) ||
(uses == -1 || used < uses); UInt64Geq(UtilServerTs(), expiration)) &&
(Int64Eq(uses, Int64Neg(Int64Create(0, 1))) || Int64Lt(used, uses));
} }
void void
RegTokenUse(RegTokenInfo * token) RegTokenUse(RegTokenInfo * token)
@ -63,12 +65,13 @@ RegTokenUse(RegTokenInfo * token)
return; return;
} }
if (token->uses >= 0 && token->used >= token->uses) if (Int64Geq(token->uses, Int64Create(0, 0)) &&
Int64Geq(token->used, token->uses))
{ {
return; return;
} }
token->used++; token->used = Int64Add(token->used, Int64Create(0, 1));
/* Write the information to the hashmap */ /* Write the information to the hashmap */
tokenJson = DbJson(token->ref); tokenJson = DbJson(token->ref);
@ -196,12 +199,12 @@ RegTokenVerify(char *token)
} }
RegTokenInfo * RegTokenInfo *
RegTokenCreate(Db * db, char *name, char *owner, unsigned long expires, int uses, int privileges) RegTokenCreate(Db * db, char *name, char *owner, UInt64 expires, Int64 uses, int privileges)
{ {
RegTokenInfo *ret; RegTokenInfo *ret;
HashMap *tokenJson; HashMap *tokenJson;
unsigned long timestamp = UtilServerTs(); UInt64 timestamp = UtilServerTs();
if (!db || !name) if (!db || !name)
{ {
@ -211,13 +214,13 @@ RegTokenCreate(Db * db, char *name, char *owner, unsigned long expires, int uses
/* -1 indicates infinite uses; zero and all positive values are a /* -1 indicates infinite uses; zero and all positive values are a
* valid number of uses; althought zero would be rather useless. * valid number of uses; althought zero would be rather useless.
* Anything less than -1 doesn't make sense. */ * Anything less than -1 doesn't make sense. */
if (uses < -1) if (Int64Lt(uses, Int64Neg(Int64Create(0, 1))))
{ {
return NULL; return NULL;
} }
/* Verify the token */ /* Verify the token */
if (!RegTokenVerify(name) || (expires > 0 && expires < timestamp)) if (!RegTokenVerify(name) || (UInt64Gt(expires, UInt64Create(0, 0)) && UInt64Lt(expires, timestamp)))
{ {
return NULL; return NULL;
} }
@ -233,7 +236,7 @@ RegTokenCreate(Db * db, char *name, char *owner, unsigned long expires, int uses
} }
ret->name = StrDuplicate(name); ret->name = StrDuplicate(name);
ret->owner = StrDuplicate(owner); ret->owner = StrDuplicate(owner);
ret->used = 0; ret->used = Int64Create(0, 0);
ret->uses = uses; ret->uses = uses;
ret->created = timestamp; ret->created = timestamp;
ret->expires = expires; ret->expires = expires;

View file

@ -40,7 +40,7 @@ struct Room
}; };
Room * Room *
RoomCreate(Db * db, RoomCreateRequest *req) RoomCreate(Db * db, RoomCreateRequest * req)
{ {
return NULL; return NULL;
} }

View file

@ -93,7 +93,7 @@ ROUTE_IMPL(RouteAliasDirectory, path, argp)
HashMap *newAlias; HashMap *newAlias;
/* TODO: Validate alias domain and make sure it matches /* TODO: Validate alias domain and make sure it matches
server name and is well formed. */ * server name and is well formed. */
if (JsonGet(aliases, 2, "alias", alias)) if (JsonGet(aliases, 2, "alias", alias))
{ {
@ -117,7 +117,8 @@ ROUTE_IMPL(RouteAliasDirectory, path, argp)
goto finish; goto finish;
} }
/* TODO: Validate room ID to make sure it is well formed. */ /* TODO: Validate room ID to make sure it is well
* formed. */
newAlias = HashMapCreate(); newAlias = HashMapCreate();
HashMapSet(newAlias, "createdBy", JsonValueString(UserGetName(user))); HashMapSet(newAlias, "createdBy", JsonValueString(UserGetName(user)));

View file

@ -139,7 +139,7 @@ ROUTE_IMPL(RouteFilter, path, argp)
DbRef *ref; DbRef *ref;
char *filterId; char *filterId;
Filter filter = { 0 }; Filter filter = {0};
char *parseErr; char *parseErr;
HashMap *filterJson; HashMap *filterJson;

View file

@ -23,6 +23,7 @@
*/ */
#include <Routes.h> #include <Routes.h>
#include <Int64.h>
#include <User.h> #include <User.h>
#include <Memory.h> #include <Memory.h>
#include <Str.h> #include <Str.h>
@ -80,10 +81,25 @@ ROUTE_IMPL(RouteProcControl, path, argp)
case HTTP_GET: case HTTP_GET:
if (StrEquals(op, "stats")) if (StrEquals(op, "stats"))
{ {
size_t allocated = MemoryAllocated();
Int64 a;
response = HashMapCreate(); response = HashMapCreate();
if (sizeof(size_t) == sizeof(Int64))
{
UInt32 high = (UInt32) (allocated >> 32);
UInt32 low = (UInt32) (allocated);
a = Int64Create(high, low);
}
else
{
a = Int64Create(0, allocated);
}
HashMapSet(response, "version", JsonValueString(TELODENDRIA_VERSION)); HashMapSet(response, "version", JsonValueString(TELODENDRIA_VERSION));
HashMapSet(response, "memory_allocated", JsonValueInteger(MemoryAllocated())); HashMapSet(response, "memory_allocated", JsonValueInteger(a));
goto finish; goto finish;
} }

View file

@ -491,7 +491,7 @@ UiaCleanup(MatrixHttpHandlerArgs * args)
char *session = ArrayGet(sessions, i); char *session = ArrayGet(sessions, i);
DbRef *ref = DbLock(args->db, 2, "user_interactive", session); DbRef *ref = DbLock(args->db, 2, "user_interactive", session);
unsigned long lastAccess; UInt64 lastAccess;
if (!ref) if (!ref)
{ {
@ -506,7 +506,7 @@ UiaCleanup(MatrixHttpHandlerArgs * args)
/* If last access was greater than 15 minutes ago, remove this /* If last access was greater than 15 minutes ago, remove this
* session */ * session */
if (UtilServerTs() - lastAccess > 1000 * 60 * 15) if (UInt64Gt(UInt64Sub(UtilServerTs(), lastAccess), UInt64Create(0, 1000 * 60 * 15)))
{ {
DbDelete(args->db, 2, "user_interactive", session); DbDelete(args->db, 2, "user_interactive", session);
Log(LOG_DEBUG, "Deleted session %s", session); Log(LOG_DEBUG, "Deleted session %s", session);

View file

@ -27,6 +27,8 @@
#include <Str.h> #include <Str.h>
#include <Sha.h> #include <Sha.h>
#include <Json.h> #include <Json.h>
#include <Int64.h>
#include <UInt64.h>
#include <string.h> #include <string.h>
@ -128,7 +130,7 @@ UserAuthenticate(Db * db, char *accessToken)
char *userName; char *userName;
char *deviceId; char *deviceId;
long expires; UInt64 expires;
if (!db || !accessToken) if (!db || !accessToken)
{ {
@ -152,7 +154,8 @@ UserAuthenticate(Db * db, char *accessToken)
return NULL; return NULL;
} }
if (expires && UtilServerTs() >= (unsigned long) expires) if (UInt64Neq(expires, UInt64Create(0, 0)) &&
UInt64Geq(UtilServerTs(), expires))
{ {
UserUnlock(user); UserUnlock(user);
DbUnlock(db, atRef); DbUnlock(db, atRef);
@ -190,7 +193,7 @@ UserCreate(Db * db, char *name, char *password)
User *user = NULL; User *user = NULL;
HashMap *json = NULL; HashMap *json = NULL;
unsigned long ts = UtilServerTs(); UInt64 ts = UtilServerTs();
/* TODO: Put some sort of password policy(like for example at least /* TODO: Put some sort of password policy(like for example at least
* 8 chars, or maybe check it's entropy)? */ * 8 chars, or maybe check it's entropy)? */
@ -495,11 +498,11 @@ UserAccessTokenGenerate(User * user, char *deviceId, int withRefresh)
if (withRefresh) if (withRefresh)
{ {
token->lifetime = 1000 * 60 * 60 * 24 * 7; /* 1 Week */ token->lifetime = Int64Create(0, 1000 * 60 * 60 * 24 * 7); /* 1 Week */
} }
else else
{ {
token->lifetime = 0; token->lifetime = Int64Create(0, 0);
} }
return token; return token;
@ -528,9 +531,9 @@ UserAccessTokenSave(Db * db, UserAccessToken * token)
HashMapSet(json, "user", JsonValueString(token->user)); HashMapSet(json, "user", JsonValueString(token->user));
HashMapSet(json, "device", JsonValueString(token->deviceId)); HashMapSet(json, "device", JsonValueString(token->deviceId));
if (token->lifetime) if (Int64Neq(token->lifetime, Int64Create(0, 0)))
{ {
HashMapSet(json, "expires", JsonValueInteger(UtilServerTs() + token->lifetime)); HashMapSet(json, "expires", JsonValueInteger(UInt64Add(UtilServerTs(), token->lifetime)));
} }
return DbUnlock(db, ref); return DbUnlock(db, ref);

View file

@ -40,6 +40,7 @@
*/ */
#include <Db.h> #include <Db.h>
#include <Int64.h>
/** /**
* This structure describes a registration token that is in the * This structure describes a registration token that is in the
@ -64,23 +65,23 @@ typedef struct RegTokenInfo
/* /*
* How many times the token was used. * How many times the token was used.
*/ */
int used; Int64 used;
/* /*
* How many uses are allowed. * How many uses are allowed.
*/ */
int uses; Int64 uses;
/* /*
* Timestamp when this token was created. * Timestamp when this token was created.
*/ */
unsigned long created; UInt64 created;
/* /*
* Timestamp when this token expires, or 0 if it does not * Timestamp when this token expires, or 0 if it does not
* expire. * expire.
*/ */
unsigned long expires; UInt64 expires;
/* /*
* A bit field describing the privileges this token grants. See * A bit field describing the privileges this token grants. See
@ -123,7 +124,7 @@ extern RegTokenInfo * RegTokenGetInfo(Db *, char *);
* structure will be returned. Otherwise, NULL will be returned. * structure will be returned. Otherwise, NULL will be returned.
*/ */
extern RegTokenInfo * extern RegTokenInfo *
RegTokenCreate(Db *, char *, char *, unsigned long, int, int); RegTokenCreate(Db *, char *, char *, UInt64, Int64, int);
/** /**
* Free the memory associated with the registration token. This should * Free the memory associated with the registration token. This should

View file

@ -38,8 +38,8 @@
* users, among many other tasks. * users, among many other tasks.
*/ */
#include <Int64.h>
#include <Db.h> #include <Db.h>
#include <Json.h> #include <Json.h>
/** /**
@ -74,7 +74,7 @@ typedef struct UserAccessToken
char *user; char *user;
char *string; char *string;
char *deviceId; char *deviceId;
long lifetime; Int64 lifetime;
} UserAccessToken; } UserAccessToken;
/** /**

View file

@ -69,14 +69,42 @@ query(char *select, HashMap * json, int canonical)
{ {
if (StrEquals(keyName + 1, "length")) if (StrEquals(keyName + 1, "length"))
{ {
UInt64 len;
switch (JsonValueType(val)) switch (JsonValueType(val))
{ {
case JSON_ARRAY: case JSON_ARRAY:
val = JsonValueInteger(ArraySize(JsonValueAsArray(val))); if (sizeof(size_t) == sizeof(UInt64))
{
size_t slen = ArraySize(JsonValueAsArray(val));
UInt32 high = slen >> 32;
UInt32 low = slen;
len = UInt64Create(high, low);
}
else
{
len = UInt64Create(0, ArraySize(JsonValueAsArray(val)));
}
val = JsonValueInteger(len);
ArrayAdd(cleanUp, val); ArrayAdd(cleanUp, val);
break; break;
case JSON_STRING: case JSON_STRING:
val = JsonValueInteger(strlen(JsonValueAsString(val))); if (sizeof(size_t) == sizeof(UInt64))
{
size_t slen = strlen(JsonValueAsString(val));
UInt32 high = slen >> 32;
UInt32 low = slen;
len = UInt64Create(high, low);
}
else
{
len = UInt64Create(0, strlen(JsonValueAsString(val)));
}
val = JsonValueInteger(len);
ArrayAdd(cleanUp, val); ArrayAdd(cleanUp, val);
break; break;
default: default: