diff options
author | Lars Knoll <lars.knoll@nokia.com> | 2011-12-08 14:10:02 +0100 |
---|---|---|
committer | Hicks James <jamey.hicks@nokia.com> | 2011-12-08 22:46:40 +0100 |
commit | ccaad46ec8852d65fcff4d90bd2f4de90b97f403 (patch) | |
tree | 8623c8c3e3db377a436e11b384ac5243607ace77 | |
parent | 96f70bcffdeaf306a74ae3bdbae71628834352c0 (diff) |
Add a bit in Value to store whether key is latin1
We need a bit somewhere to store whether the key
is latin1 so that strings always have the same
structure (in keys and values).
Change-Id: I9930c02cc278172526eeaa0a94b48c4eda229801
Reviewed-by: Hicks James <jamey.hicks@nokia.com>
-rw-r--r-- | src/qjson_p.h | 94 | ||||
-rw-r--r-- | src/qjsonarray.cpp | 3 | ||||
-rw-r--r-- | src/qjsonobject.cpp | 41 | ||||
-rw-r--r-- | src/qjsonvalue.cpp | 20 |
4 files changed, 79 insertions, 79 deletions
diff --git a/src/qjson_p.h b/src/qjson_p.h index 57e108c..4df1b08 100644 --- a/src/qjson_p.h +++ b/src/qjson_p.h @@ -69,11 +69,26 @@ const uint QBJS_Tag = ('q' << 24) | ('b' << 16) | ('j' << 8) | 's'; static inline int alignedSize(int size) { return (size + 3) & ~3; } +static inline bool useCompressed(const QString &s) +{ + if (s.length() >= 0x8000) + return false; + const ushort *uc = (const ushort *)s.constData(); + const ushort *e = uc + s.length(); + while (uc < e) { + if (*uc > 0xff) + return false; + ++uc; + } + return true; +} + static inline int qStringSize(const QString &string, bool compress) { - if (compress) - return alignedSize(string.length()); - return alignedSize(sizeof(ushort)*string.length()); + int l = 2 + string.length(); + if (!compress) + l *= 2; + return alignedSize(l); } static inline void copyString(char *dest, const QString &str, bool compress) @@ -105,7 +120,7 @@ static inline int compressedNumber(double d) }; dbl = d; int exp = (int)((val & exponent_mask) >> exponent_off) - 1023; - if (exp < 0 || exp > 26) + if (exp < 0 || exp > 25) return INT_MAX; quint64 non_int = val & (fraction_mask >> exp); @@ -283,13 +298,14 @@ struct Value // this works around the problem union { struct { - int int_val : 28; - int unused : 4; + int unused : 5; + int int_val : 27; }; struct { - uint val : 28; - uint compressed : 1; uint type : 3; + uint latinOrIntValue : 1; + uint latinKey : 1; + uint val : 27; }; }; @@ -307,33 +323,38 @@ struct Value inline void setNull() { val = 0; - compressed = 0; + latinOrIntValue = 0; + latinKey = false; type = NullValue; } inline void setBool(bool b) { val = b; - compressed = false; + latinOrIntValue = false; + latinKey = false; type = BooleanValue; } inline void setInt(int i) { Q_ASSERT(i < 1e27 && i > -1e27); int_val = i; - compressed = true; + latinOrIntValue = true; + latinKey = false; type = NumberValue; } inline void setString(Base *b, offset off, const QString &str) { val = off; - compressed = false; + latinOrIntValue = false; + latinKey = false; type = StringValue; memcpy(((char *)b) + off, str.constData(), str.length()*sizeof(ushort)); } inline void setObject(Base *b, offset off, const Object *o) { val = off; - compressed = false; + latinOrIntValue = false; + latinKey = false; type = StringValue; memcpy(((char *)b) + off, o, o->size); } @@ -353,20 +374,31 @@ inline Value &Array::operator [](int i) struct Entry { uint size; Value value; - uint compressed : 1; - uint keyLength : 31; - ushort *keyData() const { return (ushort *)(this + 1); } - uchar *latin1KeyData() const { return (uchar *)(this + 1); } - // keydata - // value data follows key data - - String shallowKey() const { return String(keyData(), keyLength); } - Latin1String shallowLatin1Key() const { return Latin1String(latin1KeyData(), keyLength); } + ushort *keyData() const { return (ushort *)((const char *)this + sizeof(Entry) + sizeof(int)); } + uchar *latin1KeyData() const { return (uchar *)((const char *)this + sizeof(Entry) + sizeof(ushort)); } + // key + // value data follows key + + String shallowKey() const + { + Q_ASSERT(!value.latinKey); + int length = *(int *) ((const char *)this + sizeof(Entry)); + return String(keyData(), length); + } + Latin1String shallowLatin1Key() const + { + Q_ASSERT(value.latinKey); + int length = *(ushort *) ((const char *)this + sizeof(Entry)); + return Latin1String(latin1KeyData(), length); + } QString key() const { - if (compressed) - return QString::fromLatin1((const char *)latin1KeyData(), keyLength); - return QString((const QChar *)keyData(), keyLength); + if (value.latinKey) { + int length = *(ushort *) ((const char *)this + sizeof(Entry)); + return QString::fromLatin1((const char *)latin1KeyData(), length); + } + int length = *(int *) ((const char *)this + sizeof(Entry)); + return QString((const QChar *)keyData(), length); } }; @@ -374,7 +406,7 @@ inline int Object::indexOf(const QString &key) { for (int i = 0; i < (int)length; ++i) { Entry *e = entryAt(i); - if (e->compressed) { + if (e->value.latinKey) { if (e->shallowLatin1Key() == key) return i; } else { @@ -404,7 +436,7 @@ inline bool Value::toBoolean() const inline double Value::toNumber(const Base *b) const { Q_ASSERT(type == NumberValue); - if (compressed) + if (latinOrIntValue) return int_val; union { @@ -417,14 +449,14 @@ inline double Value::toNumber(const Base *b) const inline int Value::toInt() const { - Q_ASSERT(type == NumberValue && compressed); + Q_ASSERT(type == NumberValue && latinOrIntValue); return int_val; } inline QString Value::toString(const Base *b) const { char *d = data(b); - if (compressed) { + if (latinOrIntValue) { int l = *(ushort *)d; return QString::fromLatin1(d + sizeof(ushort), l); } @@ -435,7 +467,7 @@ inline QString Value::toString(const Base *b) const inline String Value::asString(const Base *b) const { - Q_ASSERT(type == StringValue && !compressed); + Q_ASSERT(type == StringValue && !latinOrIntValue); char *d = data(b); int l = *(int *)d; const ushort *c = (const ushort *)(d + sizeof(int)); @@ -444,7 +476,7 @@ inline String Value::asString(const Base *b) const inline Latin1String Value::asLatin1String(const Base *b) const { - Q_ASSERT(type == StringValue && compressed); + Q_ASSERT(type == StringValue && latinOrIntValue); char *d = data(b); ushort l = *(ushort *)d; const uchar *c = (const uchar *)(d + sizeof(ushort)); diff --git a/src/qjsonarray.cpp b/src/qjsonarray.cpp index 78ab35b..3b7c3df 100644 --- a/src/qjsonarray.cpp +++ b/src/qjsonarray.cpp @@ -154,7 +154,8 @@ void JsonArray::insert(int i, const JsonValue &value) int valueOffset = a->reserveSpace(valueSize, i, 1); Value &v = (*a)[i]; v.type = (value.t == UndefinedValue ? NullValue : value.t); - v.compressed = compressed; + v.latinOrIntValue = compressed; + v.latinKey = false; v.val = value.valueToStore(valueOffset); if (valueSize) value.copyData((char *)a + valueOffset, compressed); diff --git a/src/qjsonobject.cpp b/src/qjsonobject.cpp index f55701f..63df4ba 100644 --- a/src/qjsonobject.cpp +++ b/src/qjsonobject.cpp @@ -128,7 +128,7 @@ JsonValue JsonObject::value(const QString &key) const for (uint i = 0; i < o->length; ++i) { Entry *e = o->entryAt(i); - if (e->compressed) { + if (e->value.latinKey) { if (e->shallowLatin1Key() == key) return JsonValue(d, o, e->value); } else { @@ -139,20 +139,6 @@ JsonValue JsonObject::value(const QString &key) const return JsonValue(UndefinedValue); } -static bool useCompressed(const QString &s) -{ - if (s.length() >= 0x8000) - return false; - const ushort *uc = (const ushort *)s.constData(); - const ushort *e = uc + s.length(); - while (uc < e) { - if (*uc > 0xff) - return false; - ++uc; - } - return true; -} - void JsonObject::insert(const QString &key, const JsonValue &value) { if (value.t == UndefinedValue) { @@ -160,11 +146,11 @@ void JsonObject::insert(const QString &key, const JsonValue &value) return; } - bool compressed; - int valueSize = value.requiredStorage(&compressed); + bool latinOrIntValue; + int valueSize = value.requiredStorage(&latinOrIntValue); - bool compress = useCompressed(key); - int valueOffset = sizeof(Entry) + qStringSize(key, compress); + bool latinKey = useCompressed(key); + int valueOffset = sizeof(Entry) + qStringSize(key, latinKey); int requiredSize = valueOffset + valueSize; detach(requiredSize + sizeof(offset)); // offset for the new index entry @@ -179,22 +165,13 @@ void JsonObject::insert(const QString &key, const JsonValue &value) o->reserveSpace(requiredSize, pos, 1); Entry *e = o->entryAt(pos); e->size = requiredSize; - e->keyLength = key.length(); - e->compressed = compress; - if (compress) { - uchar *c = e->latin1KeyData(); - const ushort *uc = (const ushort *)key.constData(); - const ushort *e = uc + key.length(); - while (uc < e) - *c++ = *uc++; - } else { - memcpy(e->keyData(), key.constData(), sizeof(ushort)*key.length()); - } e->value.type = value.t; - e->value.compressed = compressed; + e->value.latinKey = latinKey; + e->value.latinOrIntValue = latinOrIntValue; e->value.val = value.valueToStore(d->offsetOf(e) + valueOffset); + copyString((char *)(e + 1), key, latinKey); if (valueSize) - value.copyData((char *)e + valueOffset, compressed); + value.copyData((char *)e + valueOffset, latinOrIntValue); } void JsonObject::remove(const QString &key) diff --git a/src/qjsonvalue.cpp b/src/qjsonvalue.cpp index bc5a626..af61b24 100644 --- a/src/qjsonvalue.cpp +++ b/src/qjsonvalue.cpp @@ -335,21 +335,11 @@ int JsonValue::requiredStorage(bool *compressed) const return 0; } return sizeof(double); - case StringValue: - if (stringData->size < 0x8000) { - QString s = toString(); - const ushort *uc = (const ushort *)s.constData(); - const ushort *e = uc + s.length(); - *compressed = true; - while (uc < e) { - if (*uc > 0xff) { - *compressed = false; - break; - } - ++uc; - } - } - return alignedSize(*compressed ? sizeof(ushort) + stringData->size : sizeof(uint) + sizeof(ushort)*stringData->size); + case StringValue: { + QString s = toString(); + *compressed = useCompressed(s); + return qStringSize(s, *compressed); + } case ArrayValue: return array ? array->size : sizeof(Array); case ObjectValue: |