예제 #1
0
파일: list.c 프로젝트: LeoMirots/Lists
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;
}
예제 #2
0
파일: list.c 프로젝트: LeoMirots/Lists
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;
}
예제 #3
0
파일: list.c 프로젝트: LeoMirots/Lists
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;
}
예제 #4
0
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());
} 
예제 #5
0
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);
} 
예제 #6
0
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);
} 
예제 #7
0
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;
}
예제 #8
0
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());
} 
예제 #9
0
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());
} 
예제 #10
0
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());
} 
예제 #11
0
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();
}