-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathDataSerializer.cpp
129 lines (97 loc) · 3.57 KB
/
DataSerializer.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#include "DataSerializer.h"
#include "Logger.h"
#include "utils/stdlib.h"
#include "rapidjson/document.h"
#include "rapidjson/filereadstream.h"
#include "rapidjson/filewritestream.h"
#include "rapidjson/writer.h"
#include <cstdio>
#ifdef _MSC_VER
#pragma warning( disable : 4996 ) // warning C4996: 'fopen': This function or variable may be unsafe.
#endif
namespace
{
constexpr size_t FileStreamBufferSize = 32768;
}
class DataSerializerDocument : public rapidjson::Document
{
};
DataSerializer::Document::Document() :
m_ptrDocument(std::make_unique<DataSerializerDocument>())
{
m_ptrDocument->SetObject();
}
DataSerializer::Document::~Document() = default;
void DataSerializer::Document::add(const std::string_view name, const std::string_view value)
{
const rapidjson::Document::StringRefType nameRef(name.data(), static_cast<rapidjson::SizeType>(name.size()));
const rapidjson::Document::StringRefType valueRef(value.data(), static_cast<rapidjson::SizeType>(value.size()));
auto& allocator = m_ptrDocument->GetAllocator();
m_ptrDocument->AddMember(nameRef, valueRef, allocator);
}
const DataSerializerDocument& DataSerializer::Document::get_internal_document() const
{
return *m_ptrDocument;
}
bool DataSerializer::load(const std::string& filename, const std::function<ItemVisitorProc>& visitor)
{
stdlib_extra::FileOwner file(std::fopen(filename.c_str(), "rb"));
if (file.m_file == nullptr)
{
LOG_ERROR << "Failed opening the file for reading: " << filename << std::endl;
return false;
}
char readBuffer[FileStreamBufferSize];
rapidjson::FileReadStream stream(file.m_file, readBuffer, sizeof(readBuffer));
rapidjson::Document doc;
doc.ParseStream(stream);
file.close();
if (doc.HasParseError())
{
LOG_ERROR << "File parsing failed: " << filename << std::endl;
return false;
}
if (!doc.IsObject())
{
LOG_ERROR << "JSON root element is not an object. Type: " << static_cast<int>(doc.GetType()) << std::endl;
return false;
}
const auto iterEnd = doc.MemberEnd();
for (auto iter = doc.MemberBegin(); iter != iterEnd; ++iter)
{
const auto& name = iter->name;
if (!name.IsString())
{
LOG_ERROR << "JSON object element name is not a string. Type: "
<< static_cast<int>(name.GetType()) << std::endl;
return false;
}
const auto& value = iter->value;
if (!value.IsString())
{
LOG_ERROR << "JSON object element value is not a string. Type: "
<< static_cast<int>(value.GetType()) << "; name: " << name.GetString() << std::endl;
return false;
}
const std::string_view nameView = { name.GetString(), name.GetStringLength() };
const std::string_view valueView = { value.GetString(), value.GetStringLength() };
visitor(nameView, valueView);
}
return true;
}
bool DataSerializer::save(const std::string& filename, const Document& document)
{
stdlib_extra::FileOwner file(std::fopen(filename.c_str(), "wb"));
if (file.m_file == nullptr)
{
LOG_ERROR << "Failed opening the file for writing: " << filename << std::endl;
return false;
}
char writeBuffer[FileStreamBufferSize];
rapidjson::FileWriteStream stream(file.m_file, writeBuffer, sizeof(writeBuffer));
rapidjson::Writer<rapidjson::FileWriteStream> writer(stream);
const auto& internalDocument = document.get_internal_document();
internalDocument.Accept(writer);
file.close();
return true;
}