2016-07-29 3 views
0

다음 방법에 문제가있어 내가 잘못하고있는 것을 알아 내려고 도움이 필요합니다.문서 값에 대한 참조를 반환하는 Rapidjson

문서의 값에 대한 참조를 반환하고 싶습니다. 함수 외부에서 문서를 전달하므로 json 파일을 읽을 때 "잃어 버리지"않습니다.

const rapidjson::Value& CTestManager::GetOperations(rapidjson::Document& document) 
{ 
    const Value Null(kObjectType); 

    if (m_Tests.empty()) 
     return Null; 

    if (m_current > m_Tests.size() - 1) 
     return Null; 

    Test& the_test = m_Tests[m_current]; 

    CMyFile fp(the_test.file.c_str()); // non-Windows use "r" 
    if (!fp.is_open()) 
     return Null; 

    u32 operations_count = 0; 

    CFileBuffer json(fp); 
    FileReadStream is(fp.native_handle(), json, json.size()); 

    if (document.ParseInsitu<kParseCommentsFlag>(json).HasParseError()) 
    { 
     (...) 
    } 
    else 
    { 
     if (!document.IsObject()) 
     { 
      (...) 
     } 
     else 
     { 
      auto tests = document.FindMember("td_tests"); 
      if (tests != document.MemberEnd()) 
      { 
       for (SizeType i = 0; i < tests->value.Size(); i++) 
       { 
        const Value& test = tests->value[i]; 

        if (test["id"].GetInt() == the_test.id) 
        { 
         auto it = test.FindMember("operations"); 
         if (it != test.MemberEnd()) 
         { 
          //return it->value; is this legitimate? 
          return test["operations"]; 
         } 

         return Null; 
        } 
       } 
      } 
     } 
    } 

    return Null; 
} 

I는 다음과 같이 호출하고 어떤 : 나는 함수 내 test["operations"]의 값을 검사 할 때

Document document; 
auto operations = TestManager().GetOperations(document); 

내가 기대 (거처 코드에서 제거 디버그 코드)를 모든 것을 볼 수 있습니다.

함수 밖에서 반환 된 값을 검사하면 해당 배열 (예상 한)임을 알 수 있습니다. 배열의 멤버 수 int 또한 올바르지 만 인쇄 할 때 나는 대신 가비지 만 봅니다.

값을 메서드 내부의 문자열에 "인쇄"할 때 예상했던대로 (예 : 잘 형성된 json) 얻을 수 있지만, 모든 키 바깥 쪽에서 "IIIIIIII"로 표시되면 값이 ' t 문자열이 올바르게 표시됩니다. 이 같이

rapidjson::StringBuffer strbuf2; 
    rapidjson::PrettyWriter<rapidjson::StringBuffer> writer2(strbuf2); 
    ops->Accept(writer2); 

내가 매개 변수로 값을받을 수있는 방법을 변경하기로 결정 일을하고 나는이 같은 전화 드렸습니다이

u32 CTestManager::GetOperationsEx(rapidjson::Document& document, rapidjson::Value& operations) 
{ 
    (...) 

    if (document.ParseInsitu<kParseCommentsFlag>(json).HasParseError()) 
    { 
     (...) 
    } 
    else 
    { 
     if (!document.IsObject()) 
     { 
      (...) 
     } 
     else 
     { 
      auto tests = document.FindMember("tests"); 
      if (tests != document.MemberEnd()) 
      { 
       for (SizeType i = 0; i < tests->value.Size(); i++) 
       { 
        const Value& test = tests->value[i]; 

        if (test["id"].GetInt() == the_test.id) 
        { 
         const Value& opv = test["operations"]; 

         Document::AllocatorType& allocator = document.GetAllocator(); 
         operations.CopyFrom(opv, allocator); //would Swap work? 
         return operations.Size(); 
        } 
       } 
      } 
     } 
    } 

    return 0; 
} 

처럼에 깊은 사본을하지 않았다 :

Document document; 
Value operations(kObjectType); 
u32 count = TestManager().GetOperationsEx(document, operations); 

하지만 ... 나는 같은 것을 얻습니다 !!!!

나는 그것이 어리석은 무엇 일 예정이다라는 것을 알고있다. 그러나 나는 그것에 손을 넣을 수 없다!

아이디어가 있으십니까?

답변

0

이 경우의 문제점은 ParseInSitu의 사용에 있습니다. GetOperations 중 하나가 존재하면 CFileBuffer이 범위를 잃고 정리됩니다. 파일에 대한 버퍼가 이동하면 json이 원래 위치에서 파싱되므로 데이터도 함께 이동합니다.