Home | History | Annotate | Download | only in util
      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 <cstring>
     23 #include <string>
     24 
     25 #include <rapidjson/document.h>
     26 #include <rapidjson/reader.h>
     27 
     28 namespace i18n {
     29 namespace addressinput {
     30 
     31 namespace {
     32 
     33 class Rapidjson : public Json {
     34  public:
     35   Rapidjson() : dict_() {}
     36 
     37   virtual ~Rapidjson() {}
     38 
     39   virtual bool ParseObject(const std::string& json) {
     40     scoped_ptr<rapidjson::Document> document(new rapidjson::Document);
     41     document->Parse<rapidjson::kParseValidateEncodingFlag>(json.c_str());
     42     if (!document->HasParseError() && document->IsObject()) {
     43       dict_.reset(document.release());
     44       return true;
     45     }
     46     return false;
     47   }
     48 
     49   virtual bool GetStringValueForKey(const std::string& key,
     50                                     std::string* value) const {
     51     assert(dict_ != NULL);
     52 
     53     // Owned by |dict_|.
     54     const rapidjson::Value::Member* member = dict_->FindMember(key.c_str());
     55     if (member == NULL || !member->value.IsString()) {
     56       return false;
     57     }
     58 
     59     if (value) {
     60       value->assign(member->value.GetString(), member->value.GetStringLength());
     61     }
     62 
     63     return true;
     64   }
     65 
     66   virtual bool GetJsonValueForKey(const std::string& key,
     67                                   scoped_ptr<Json>* value) const {
     68     assert(dict_ != NULL);
     69 
     70     // Owned by |dict_|.
     71     const rapidjson::Value::Member* member = dict_->FindMember(key.c_str());
     72     if (member == NULL || !member->value.IsObject()) {
     73       return false;
     74     }
     75 
     76     if (value) {
     77       scoped_ptr<rapidjson::Value> copy(new rapidjson::Value);
     78 
     79       // Rapidjson provides only move operations in public API, but implements
     80       // the move operation with a memcpy and delete:
     81       //
     82       // https://code.google.com/p/rapidjson/source/browse/trunk/include/rapidjson/document.h?r=131#173
     83       //
     84       // We need a copy of the object, so we use memcpy manually.
     85       memcpy(copy.get(), &member->value, sizeof(rapidjson::Value));
     86 
     87       value->reset(new Rapidjson(copy.Pass()));
     88     }
     89 
     90     return true;
     91   }
     92 
     93  protected:
     94   explicit Rapidjson(scoped_ptr<rapidjson::Value> dict)
     95       : dict_(dict.Pass()) {}
     96 
     97   // JSON value.
     98   scoped_ptr<rapidjson::Value> dict_;
     99 
    100   DISALLOW_COPY_AND_ASSIGN(Rapidjson);
    101 };
    102 
    103 }  // namespace
    104 
    105 Json::~Json() {}
    106 
    107 // static
    108 scoped_ptr<Json> Json::Build() {
    109   return scoped_ptr<Json>(new Rapidjson);
    110 }
    111 
    112 Json::Json() {}
    113 
    114 }  // namespace addressinput
    115 }  // namespace i18n
    116