list cons(element e) { list l = malloc(sizeof(item)); l->value.value = BuildValue(e); l->value.type = e.type; l->next = NULL; l->root = l; return l; }
element MinValue(list l) { element x = { BuildValue(head(l)), head(l).type }; for (size_t i = 0; tail(l) != NULL; ++i) { if (cmp(x, (head(tail(l)))) > 0) AssignElement(&x, head(tail(l))); l = tail(l); } return x; }
element MaxValue(list l) { element x = { BuildValue(head(l)), head(l).type }; while (empty(tail(l)) == false) { if (cmp(x, (head(tail(l)))) < 0) AssignElement(&x, head(tail(l))); l = tail(l); } return x; }
TEST(SliceContainerTest, FromSlice) { std::shared_ptr<Builder> builder = BuildValue("\"this is a string of 20 bytes\""); Slice slice = builder->slice(); SliceContainer sb(slice); ASSERT_EQ(sb.byteSize(), slice.byteSize()); ASSERT_EQ(0, memcmp(sb.data(), slice.begin(), slice.byteSize())); ASSERT_EQ(29UL, sb.byteSize()); ASSERT_TRUE(sb.slice().isString()); ASSERT_EQ("this is a string of 20 bytes", sb.slice().copyString()); ASSERT_NE(sb.data(), slice.begin()); }
TEST(SliceContainerTest, FromUInt8Longer) { std::shared_ptr<Builder> builder = BuildValue("[\"the eagle has landed\",\"test\",\"qux\"]"); uint8_t const* begin = builder->start(); Slice slice = builder->slice(); SliceContainer sb(begin, slice.byteSize()); ASSERT_EQ(sb.byteSize(), slice.byteSize()); ASSERT_EQ(0, memcmp(sb.data(), builder->start(), slice.byteSize())); ASSERT_TRUE(sb.slice().isArray()); ASSERT_NE(sb.data(), begin); }
TEST(SliceContainerTest, FromChar) { std::shared_ptr<Builder> builder = BuildValue("null"); uint8_t const* begin = builder->start(); Slice slice = builder->slice(); SliceContainer sb(reinterpret_cast<char const*>(begin), slice.byteSize()); ASSERT_EQ(sb.byteSize(), slice.byteSize()); ASSERT_EQ(0, memcmp(sb.data(), builder->start(), slice.byteSize())); ASSERT_EQ(1UL, sb.byteSize()); ASSERT_TRUE(sb.slice().isNull()); ASSERT_NE(sb.data(), begin); }
Value* JSONReader::JsonToValue(const std::string& json, bool check_root, bool allow_trailing_comma) { // 输入必须是UTF-8编码. if(!IsStringUTF8(json.c_str())) { error_code_ = JSON_UNSUPPORTED_ENCODING; return NULL; } // 从UTF8到wstring的转换会移除空字节(好事). std::wstring json_wide(UTF8ToWide(json)); start_pos_ = json_wide.c_str(); // 当输入的JSON字符串开头有UTF-8的Byte-Order-Mark(0xEF, 0xBB, 0xBF), // UTF8ToWide()函数会把它转换成BOM(U+FEFF). 为防止JSONReader::BuildValue() // 函数把它当成非法字符而返回NULL, 如果存在Unicode的BOM则先跳过. if(!json_wide.empty() && start_pos_[0]==0xFEFF) { ++start_pos_; } json_pos_ = start_pos_; allow_trailing_comma_ = allow_trailing_comma; stack_depth_ = 0; error_code_ = JSON_NO_ERROR; scoped_ptr<Value> root(BuildValue(check_root)); if(root.get()) { if(ParseToken().type == Token::END_OF_INPUT) { return root.release(); } else { SetErrorCode(JSON_UNEXPECTED_DATA_AFTER_ROOT, json_pos_); } } // "语法错误". if(error_code_ == 0) { SetErrorCode(JSON_SYNTAX_ERROR, json_pos_); } return NULL; }
TEST(SliceContainerTest, MoveConstruct) { std::shared_ptr<Builder> builder = BuildValue("\"this is a string of 20 bytes\""); Slice slice = builder->slice(); SliceContainer sb(slice.begin(), slice.byteSize()); SliceContainer sb2(std::move(sb)); ASSERT_TRUE(sb.slice().isNone()); // must be empty now ASSERT_EQ(1UL, sb.slice().byteSize()); ASSERT_EQ(29UL, sb2.byteSize()); ASSERT_TRUE(sb2.slice().isString()); ASSERT_EQ("this is a string of 20 bytes", sb2.slice().copyString()); ASSERT_NE(sb.slice().begin(), sb2.slice().begin()); }
TEST(SliceContainerTest, FromSliceLonger) { std::string s("[-1"); for (size_t i = 0; i < 2000; ++i) { s.push_back(','); s.append(std::to_string(i)); } s.push_back(']'); std::shared_ptr<Builder> builder = BuildValue(s); Slice slice = builder->slice(); SliceContainer sb(slice); ASSERT_EQ(sb.byteSize(), slice.byteSize()); ASSERT_EQ(0, memcmp(sb.data(), builder->start(), slice.byteSize())); ASSERT_TRUE(sb.slice().isArray()); ASSERT_NE(sb.data(), slice.begin()); }
TEST(SliceContainerTest, SizeLengthByteSize) { std::shared_ptr<Builder> builder = BuildValue("\"this is a string of 20 bytes\""); Slice slice = builder->slice(); SliceContainer sb(slice.begin(), slice.byteSize()); ASSERT_TRUE(sb.slice().isString()); ASSERT_EQ(29UL, sb.size()); ASSERT_EQ(29UL, sb.length()); ASSERT_EQ(29UL, sb.byteSize()); ASSERT_EQ(sb.data(), sb.begin()); Slice empty; sb = SliceContainer(empty); ASSERT_EQ(1UL, sb.size()); ASSERT_EQ(1UL, sb.length()); ASSERT_EQ(1UL, sb.byteSize()); ASSERT_EQ(sb.data(), sb.begin()); }
Value* JSONReader::BuildValue(bool is_root) { ++stack_depth_; if(stack_depth_ > kStackLimit) { SetErrorCode(JSON_TOO_MUCH_NESTING, json_pos_); return NULL; } Token token = ParseToken(); // 根token必须是数组或者对象. if(is_root && token.type!=Token::OBJECT_BEGIN && token.type!=Token::ARRAY_BEGIN) { SetErrorCode(JSON_BAD_ROOT_ELEMENT_TYPE, json_pos_); return NULL; } scoped_ptr<Value> node; switch(token.type) { case Token::END_OF_INPUT: case Token::INVALID_TOKEN: return NULL; case Token::NULL_TOKEN: node.reset(Value::CreateNullValue()); break; case Token::BOOL_TRUE: node.reset(Value::CreateBooleanValue(true)); break; case Token::BOOL_FALSE: node.reset(Value::CreateBooleanValue(false)); break; case Token::NUMBER: node.reset(DecodeNumber(token)); if(!node.get()) { return NULL; } break; case Token::STRING: node.reset(DecodeString(token)); if(!node.get()) { return NULL; } break; case Token::ARRAY_BEGIN: { json_pos_ += token.length; token = ParseToken(); node.reset(new ListValue()); while(token.type != Token::ARRAY_END) { Value* array_node = BuildValue(false); if(!array_node) { return NULL; } static_cast<ListValue*>(node.get())->Append(array_node); // list数据后面应该是逗号, 否则list结束. token = ParseToken(); if(token.type == Token::LIST_SEPARATOR) { json_pos_ += token.length; token = ParseToken(); // 按照JSON RFC结尾的逗号是不合法的, 但是有些人希望能宽松一些, // 所以做一些相应处理. if(token.type == Token::ARRAY_END) { if(!allow_trailing_comma_) { SetErrorCode(JSON_TRAILING_COMMA, json_pos_); return NULL; } // 结尾有逗号, 停止继续解析Array. break; } } else if(token.type != Token::ARRAY_END) { // 非预期数据, 直接返回. return NULL; } } if(token.type != Token::ARRAY_END) { return NULL; } break; } case Token::OBJECT_BEGIN: { json_pos_ += token.length; token = ParseToken(); node.reset(new DictionaryValue()); while(token.type != Token::OBJECT_END) { if(token.type != Token::STRING) { SetErrorCode(JSON_UNQUOTED_DICTIONARY_KEY, json_pos_); return NULL; } scoped_ptr<Value> dict_key_value(DecodeString(token)); if(!dict_key_value.get()) { return NULL; } // key转换成wstring. std::string dict_key; bool success = dict_key_value->GetAsString(&dict_key); DCHECK(success); json_pos_ += token.length; token = ParseToken(); if(token.type != Token::OBJECT_PAIR_SEPARATOR) { return NULL; } json_pos_ += token.length; token = ParseToken(); Value* dict_value = BuildValue(false); if(!dict_value) { return NULL; } static_cast<DictionaryValue*>(node.get())->SetWithoutPathExpansion( dict_key, dict_value); // key/value后面应该是逗号, 否则对象结束. token = ParseToken(); if(token.type == Token::LIST_SEPARATOR) { json_pos_ += token.length; token = ParseToken(); // 按照JSON RFC结尾的逗号是不合法的, 但是有些人希望能宽松一些, // 所以做一些相应处理. if(token.type == Token::OBJECT_END) { if(!allow_trailing_comma_) { SetErrorCode(JSON_TRAILING_COMMA, json_pos_); return NULL; } // 结尾有逗号, 停止继续解析Array. break; } } else if(token.type != Token::OBJECT_END) { // 非预期数据, 直接返回. return NULL; } } if(token.type != Token::OBJECT_END) { return NULL; } break; } default: // 非数据token. return NULL; } json_pos_ += token.length; --stack_depth_; return node.release(); }