2015-05-10 2 views
3

Я пытаюсь работать с rapidjson.Есть ли способ использовать quickjson с std :: string эффективно?

Я хочу сгенерировать строку и добавить ее к rapidjson::Value, который является объектом.

Я использовал std :: string при работе с qjson, но в случае quickjson это кажется неуместным. Я не хочу генерировать строку, а затем копировать ее, срок жизни объекта объекта перед объектом (rapidjson::Value) lifetime (поэтому generated_string.c_str() - это не случай). В json может быть \ 0, поэтому char* с нулевым символом также не является решением.

Итак, я должен написать собственный тип строки? Или используйте что-то вроде

auto create_string_object() -> rapidjson::GenericStringRef<char> 
{ 
    size_t len; 
    char* result; 
    // generate char* result with length len 
    const char* return_value = result; 
    return rapidjson::StringRef(return_value,len); 
} 
auto create_object_object(rapidjson::Document::AllocatorType &allocator) -> rapidjson::Value 
{ 
    // ... 
    rapidjson::Value result(rapidjson::kObjectType); 
    rapidjson::Value tmp; // tmp = create_string_object() will not compile 
    tmp = create_string_object(); 
    result.AddMember("key", tmp, allocator); 
    // ... 
} 

Или есть другие способы работы со строками? Мне это кажется трудным. Мы не можем переместить строку в rapidjson::Value из-за различных структур внутри этого Value, мы не можем установить указатель внутри Value на c_str(), потому что строка будет уничтожена до Value. Даже с GenericStringRef<char> Я должен переписать почти все работы со строками.

Кстати, почему RAPIDJSON_HAS_STDSTRING - 0 по умолчанию? Некоторые проблемы с работой? Я вижу, что я могу скопировать строку в rapidjson::Value и скопировать указатель, если я знаю, что срок службы строки закончится до значения времени жизни.

UPD: Теперь я вижу, что rapidjson освобождает только строки, которые были скопированы:

//! Destructor. 
    /*! Need to destruct elements of array, members of object, or copy-string. 
    */ 
    ~GenericValue() { 
     if (Allocator::kNeedFree) { // Shortcut by Allocator's trait 
      switch(flags_) { 
      case kArrayFlag: 
       for (GenericValue* v = data_.a.elements; v != data_.a.elements + data_.a.size; ++v) 
        v->~GenericValue(); 
       Allocator::Free(data_.a.elements); 
       break; 

      case kObjectFlag: 
       for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m) 
       m->~Member(); 
       Allocator::Free(data_.o.members); 
       break; 

      case kCopyStringFlag: 
       Allocator::Free(const_cast<Ch*>(data_.s.str)); 
       break; 

      default: 
       break; // Do nothing for other types. 
      } 
     } 
    } 

Так, как это было сказано в ответ, используя GenericStringRef таким образом, например, в моем коде здесь плохо идея, потому что в таком случае я должен сам управлять памятью.

ответ

6

Я не совсем понимаю вопрос. Но я пытаюсь прояснить некоторые вещи здесь.

  1. GenericStringRef Используется для предотвращения копирования строк. Его следует использовать только в том случае, если известно, что срок службы строки является достаточным. Для динамически создаваемой строки обычно не следует использовать GenericStringRef.
  2. Установка RAPIDJSON_HAS_STDSTRING=1 в порядке. Он не включается по умолчанию, потому что его поддержка добавляется после раннего выпуска. И я не хочу, чтобы заголовок RapidJSON включал <string>, если пользователю это не нужно. Поскольку вы используете std::string, вы можете включить его. Это должно облегчить вам дело с std::string.
+0

Спасибо. Извините, после некоторого времени размышления я понял, что это плохой вопрос: если я хочу всегда работать с '' 'std :: string''' (и' '' quickjson'''), я должен скопировать строки в некоторых случаях, если я хочу избежать копирования, я должен использовать '' 'char *' '' или некоторые типы из '' 'quickjson''', как в вопросе. – ckorzhik

Смежные вопросы