1// Copyright (C) 2013 Google Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#include "json.h"
16
17#include <libaddressinput/util/basictypes.h>
18#include <libaddressinput/util/scoped_ptr.h>
19
20#include <cassert>
21#include <cstddef>
22#include <string>
23#include <vector>
24
25#include <rapidjson/document.h>
26#include <rapidjson/reader.h>
27
28namespace i18n {
29namespace addressinput {
30
31using rapidjson::Document;
32using rapidjson::kParseValidateEncodingFlag;
33using rapidjson::Value;
34
35class Json::JsonImpl {
36 public:
37  explicit JsonImpl(const std::string& json)
38      : document_(new Document),
39        value_(document_.get()),
40        dictionaries_(),
41        valid_(false) {
42    document_->Parse<kParseValidateEncodingFlag>(json.c_str());
43    valid_ = !document_->HasParseError() && document_->IsObject();
44  }
45
46  ~JsonImpl() {
47    for (std::vector<const Json*>::const_iterator it = dictionaries_.begin();
48         it != dictionaries_.end(); ++it) {
49      delete *it;
50    }
51  }
52
53  bool valid() const { return valid_; }
54
55  const std::vector<const Json*>& GetSubDictionaries() {
56    if (dictionaries_.empty()) {
57      for (Value::ConstMemberIterator member = value_->MemberBegin();
58           member != value_->MemberEnd(); ++member) {
59        if (member->value.IsObject()) {
60          dictionaries_.push_back(new Json(new JsonImpl(&member->value)));
61        }
62      }
63    }
64    return dictionaries_;
65  }
66
67  bool GetStringValueForKey(const std::string& key, std::string* value) const {
68    assert(value != NULL);
69
70    Value::ConstMemberIterator member = value_->FindMember(key.c_str());
71    if (member == NULL || !member->value.IsString()) {
72      return false;
73    }
74
75    value->assign(member->value.GetString(),
76                  member->value.GetStringLength());
77    return true;
78  }
79
80 private:
81  // Does not take ownership of |value|.
82  explicit JsonImpl(const Value* value)
83      : document_(),
84        value_(value),
85        dictionaries_(),
86        valid_(true) {
87    assert(value_ != NULL);
88    assert(value_->IsObject());
89  }
90
91  // An owned JSON document. Can be NULL if the JSON document is not owned.
92  const scoped_ptr<Document> document_;
93
94  // A JSON document that is not owned. Cannot be NULL. Can point to document_.
95  const Value* const value_;
96
97  // Owned JSON objects of sub-dictionaries.
98  std::vector<const Json*> dictionaries_;
99
100  // True if the JSON object was parsed successfully.
101  bool valid_;
102
103  DISALLOW_COPY_AND_ASSIGN(JsonImpl);
104};
105
106Json::Json() : impl_() {}
107
108Json::~Json() {}
109
110bool Json::ParseObject(const std::string& json) {
111  assert(impl_ == NULL);
112  impl_.reset(new JsonImpl(json));
113  if (!impl_->valid()) {
114    impl_.reset();
115  }
116  return impl_ != NULL;
117}
118
119const std::vector<const Json*>& Json::GetSubDictionaries() const {
120  assert(impl_ != NULL);
121  return impl_->GetSubDictionaries();
122}
123
124bool Json::GetStringValueForKey(const std::string& key,
125                                std::string* value) const {
126  assert(impl_ != NULL);
127  return impl_->GetStringValueForKey(key, value);
128}
129
130Json::Json(JsonImpl* impl) : impl_(impl) {}
131
132}  // namespace addressinput
133}  // namespace i18n
134