std::set<ValueKey> JsonDb::Transaction::Walk() { std::set<ValueKey> keys; // initialize the iterator if(!vlcurfirst(db.get())) throw std::runtime_error("Failed to initialize database iterator"); CharPtr key; while((key = CharPtr(vlcurkey(db.get(), NULL))) != NULL) { keys.insert(*(ValueKey const *)key.get()); vlcurnext(db.get()); } return keys; }
ValuePointer JsonDb::Transaction::Retrieve(ValueKey key) { if(key == null_key) return null_element; // std::cout << "Retrieve: key=" << key << std::endl; // Then retrieve the actual data int value_size; CharPtr val = CharPtr(vlget(db.get(), (char const *)&key, sizeof(ValueKey), &value_size)); if(val.get() == NULL) return ValuePointer(); if(value_size <= 0) throw std::runtime_error((boost::format("Element has an invalid size: %d") % key).str().c_str()); std::string val_str(val.get(), value_size); std::istringstream input(val_str); ValuePointer result = Value::Unserialize(key, input); return result; }
JSONParserBase::Token JSONParser<CharT>::readNumber() { MOZ_ASSERT(current < end); MOZ_ASSERT(JS7_ISDEC(*current) || *current == '-'); /* * JSONNumber: * /^-?(0|[1-9][0-9]+)(\.[0-9]+)?([eE][\+\-]?[0-9]+)?$/ */ bool negative = *current == '-'; /* -? */ if (negative && ++current == end) { error("no number after minus sign"); return token(Error); } const CharPtr digitStart = current; /* 0|[1-9][0-9]+ */ if (!JS7_ISDEC(*current)) { error("unexpected non-digit"); return token(Error); } if (*current++ != '0') { for (; current < end; current++) { if (!JS7_ISDEC(*current)) break; } } /* Fast path: no fractional or exponent part. */ if (current == end || (*current != '.' && *current != 'e' && *current != 'E')) { mozilla::Range<const CharT> chars(digitStart.get(), current - digitStart); if (chars.length() < strlen("9007199254740992")) { // If the decimal number is shorter than the length of 2**53, (the // largest number a double can represent with integral precision), // parse it using a decimal-only parser. This comparison is // conservative but faster than a fully-precise check. double d = ParseDecimalNumber(chars); return numberToken(negative ? -d : d); } double d; const CharT* dummy; if (!GetPrefixInteger(cx, digitStart.get(), current.get(), 10, &dummy, &d)) return token(OOM); MOZ_ASSERT(current == dummy); return numberToken(negative ? -d : d); } /* (\.[0-9]+)? */ if (current < end && *current == '.') { if (++current == end) { error("missing digits after decimal point"); return token(Error); } if (!JS7_ISDEC(*current)) { error("unterminated fractional number"); return token(Error); } while (++current < end) { if (!JS7_ISDEC(*current)) break; } } /* ([eE][\+\-]?[0-9]+)? */ if (current < end && (*current == 'e' || *current == 'E')) { if (++current == end) { error("missing digits after exponent indicator"); return token(Error); } if (*current == '+' || *current == '-') { if (++current == end) { error("missing digits after exponent sign"); return token(Error); } } if (!JS7_ISDEC(*current)) { error("exponent part is missing a number"); return token(Error); } while (++current < end) { if (!JS7_ISDEC(*current)) break; } } double d; const CharT* finish; if (!js_strtod(cx, digitStart.get(), current.get(), &finish, &d)) return token(OOM); MOZ_ASSERT(current == finish); return numberToken(negative ? -d : d); }
JSONParserBase::Token JSONParser<CharT>::readString() { MOZ_ASSERT(current < end); MOZ_ASSERT(*current == '"'); /* * JSONString: * /^"([^\u0000-\u001F"\\]|\\(["/\\bfnrt]|u[0-9a-fA-F]{4}))*"$/ */ if (++current == end) { error("unterminated string literal"); return token(Error); } /* * Optimization: if the source contains no escaped characters, create the * string directly from the source text. */ CharPtr start = current; for (; current < end; current++) { if (*current == '"') { size_t length = current - start; current++; JSFlatString* str = (ST == JSONParser::PropertyName) ? AtomizeChars(cx, start.get(), length) : NewStringCopyN<CanGC>(cx, start.get(), length); if (!str) return token(OOM); return stringToken(str); } if (*current == '\\') break; if (*current <= 0x001F) { error("bad control character in string literal"); return token(Error); } } /* * Slow case: string contains escaped characters. Copy a maximal sequence * of unescaped characters into a temporary buffer, then an escaped * character, and repeat until the entire string is consumed. */ StringBuffer buffer(cx); do { if (start < current && !buffer.append(start.get(), current.get())) return token(OOM); if (current >= end) break; char16_t c = *current++; if (c == '"') { JSFlatString* str = (ST == JSONParser::PropertyName) ? buffer.finishAtom() : buffer.finishString(); if (!str) return token(OOM); return stringToken(str); } if (c != '\\') { --current; error("bad character in string literal"); return token(Error); } if (current >= end) break; switch (*current++) { case '"': c = '"'; break; case '/': c = '/'; break; case '\\': c = '\\'; break; case 'b': c = '\b'; break; case 'f': c = '\f'; break; case 'n': c = '\n'; break; case 'r': c = '\r'; break; case 't': c = '\t'; break; case 'u': if (end - current < 4 || !(JS7_ISHEX(current[0]) && JS7_ISHEX(current[1]) && JS7_ISHEX(current[2]) && JS7_ISHEX(current[3]))) { // Point to the first non-hexadecimal character (which may be // missing). if (current == end || !JS7_ISHEX(current[0])) ; // already at correct location else if (current + 1 == end || !JS7_ISHEX(current[1])) current += 1; else if (current + 2 == end || !JS7_ISHEX(current[2])) current += 2; else if (current + 3 == end || !JS7_ISHEX(current[3])) current += 3; else MOZ_CRASH("logic error determining first erroneous character"); error("bad Unicode escape"); return token(Error); } c = (JS7_UNHEX(current[0]) << 12) | (JS7_UNHEX(current[1]) << 8) | (JS7_UNHEX(current[2]) << 4) | (JS7_UNHEX(current[3])); current += 4; break; default: current--; error("bad escaped character"); return token(Error); } if (!buffer.append(c)) return token(OOM); start = current; for (; current < end; current++) { if (*current == '"' || *current == '\\' || *current <= 0x001F) break; } } while (current < end); error("unterminated string"); return token(Error); }