summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@nokia.com>2011-12-08 14:10:02 +0100
committerHicks James <jamey.hicks@nokia.com>2011-12-08 22:46:40 +0100
commitccaad46ec8852d65fcff4d90bd2f4de90b97f403 (patch)
tree8623c8c3e3db377a436e11b384ac5243607ace77
parent96f70bcffdeaf306a74ae3bdbae71628834352c0 (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.h94
-rw-r--r--src/qjsonarray.cpp3
-rw-r--r--src/qjsonobject.cpp41
-rw-r--r--src/qjsonvalue.cpp20
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: