Skip to content

Commit 0fc17b6

Browse files
committed
Fixed #1 read from binary file also added unit-test
1 parent 6e98b41 commit 0fc17b6

File tree

9 files changed

+269
-15
lines changed

9 files changed

+269
-15
lines changed

src/wsjcpp_obj_tree.cpp

Lines changed: 182 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ WsjcppObjTreeNode::WsjcppObjTreeNode(WsjcppObjTree *pTree, uint16_t nType) {
1111
m_pTree = pTree;
1212
m_pParent = nullptr;
1313
m_nType = nType;
14-
// TODO regestry in global factory
1514
}
1615

1716
// ---------------------------------------------------------------------
@@ -92,8 +91,71 @@ WsjcppObjTree::~WsjcppObjTree() {
9291

9392
bool WsjcppObjTree::readTreeFromFile(const std::string &sFilename, std::string &sError) {
9493
if (!WsjcppCore::fileExists(sFilename)) {
94+
sError = "File not exists";
9595
return false;
9696
}
97+
98+
clearNodes();
99+
std::ifstream f;
100+
f.open(sFilename.c_str(), std::ios::in | std::ios::binary);
101+
102+
uint32_t nTreeSize = 0;
103+
if (!this->readUInt32(f, nTreeSize, sError)) {
104+
return false;
105+
}
106+
107+
if (!this->readUInt32(f, m_nLastId, sError)) {
108+
return false;
109+
}
110+
111+
std::map<uint32_t, WsjcppObjTreeNode *> mapTempIdToNode;
112+
for (int i = 0; i < nTreeSize; i++) {
113+
uint16_t nNodeType = 0;
114+
if (!this->readUInt16(f, nNodeType, sError)) {
115+
return false;
116+
}
117+
118+
if (m_mapFabricTreeNode.find(nNodeType) == m_mapFabricTreeNode.end()) {
119+
sError = "On read file could not found node type: " + std::to_string(nNodeType);
120+
return false;
121+
}
122+
123+
// read parent id
124+
uint32_t nParentId = 0;
125+
if (!this->readUInt32(f, nParentId, sError)) {
126+
return false;
127+
}
128+
WsjcppObjTreeNode *pParentNode = nullptr; // TODO find by Id
129+
130+
if (mapTempIdToNode.find(nParentId) != mapTempIdToNode.end()) {
131+
pParentNode = mapTempIdToNode[nParentId];
132+
}
133+
134+
// read node id
135+
uint32_t nNodeId = 0;
136+
if (!this->readUInt32(f, nNodeId, sError)) {
137+
return false;
138+
}
139+
140+
141+
if (nNodeId > m_nLastId) {
142+
sError = "Node id '" + std::to_string(nNodeId) + "' could not more then last id " + std::to_string(m_nLastId);
143+
return false;
144+
}
145+
146+
WsjcppObjTreeNode *pNode = m_mapFabricTreeNode[nNodeType]->create();
147+
pNode->setId(nNodeId);
148+
pNode->setParent(pParentNode);
149+
if (pParentNode != nullptr) {
150+
pParentNode->addChild(pNode);
151+
}
152+
if (!pNode->readDataPartFromFile(f, sError)) {
153+
return false;
154+
}
155+
mapTempIdToNode[nNodeId] = pNode;
156+
m_vNodes.push_back(pNode);
157+
}
158+
f.close();
97159
return true;
98160
}
99161

@@ -222,24 +284,43 @@ std::string WsjcppObjTree::toString() { // for printing
222284
// ---------------------------------------------------------------------
223285

224286
void WsjcppObjTree::writeUInt32(std::ofstream &f, uint32_t nVal) {
287+
const char *pBuffer = reinterpret_cast<const char *>(&nVal);
288+
f.write(pBuffer, 4);
289+
}
290+
291+
// ---------------------------------------------------------------------
292+
293+
bool WsjcppObjTree::readUInt32(std::ifstream &f, uint32_t &nVal, std::string &sError) {
225294
// not for multithreading
226-
// TODO redesign to reinterpret_cast<const char *>(&m_nValue);
227-
static unsigned char arrInteger[4];
228-
arrInteger[0] = (nVal >> 24) & 0xFF;
229-
arrInteger[1] = (nVal >> 16) & 0xFF;
230-
arrInteger[2] = (nVal >> 8) & 0xFF;
231-
arrInteger[3] = nVal & 0xFF;
232-
f.write((const char *)arrInteger, 4);
295+
static char arrInteger[4];
296+
f.read(arrInteger, 4);
297+
if (!f) {
298+
sError = "Could not read. File broken. Can read " + std::to_string(f.gcount());
299+
return false;
300+
}
301+
nVal = *reinterpret_cast<uint32_t*>(arrInteger);
302+
return true;
233303
}
234304

235305
// ---------------------------------------------------------------------
236306

237307
void WsjcppObjTree::writeUInt16(std::ofstream &f, uint16_t nVal) {
308+
const char *pBuffer = reinterpret_cast<const char *>(&nVal);
309+
f.write(pBuffer, 2);
310+
}
311+
312+
// ---------------------------------------------------------------------
313+
314+
bool WsjcppObjTree::readUInt16(std::ifstream &f, uint16_t &nVal, std::string &sError) {
238315
// not for multithreading
239-
static unsigned char arrShort[2];
240-
arrShort[0] = (nVal >> 8) & 0xFF;
241-
arrShort[1] = nVal & 0xFF;
242-
f.write((const char *)arrShort, 2);
316+
static char arrShort[2];
317+
f.read(arrShort, 2);
318+
if (!f) {
319+
sError = "Could not read. File broken. Can read " + std::to_string(f.gcount());
320+
return false;
321+
}
322+
nVal = *reinterpret_cast<uint16_t*>(arrShort);
323+
return true;
243324
}
244325

245326
// ---------------------------------------------------------------------
@@ -337,6 +418,28 @@ const char *WsjcppObjTreeNodeString::getData() {
337418

338419
// ---------------------------------------------------------------------
339420

421+
bool WsjcppObjTreeNodeString::readDataPartFromFile(std::ifstream &f, std::string &sError) {
422+
uint32_t nStringLen = 0;
423+
char arrInteger[4];
424+
f.read(arrInteger, 4);
425+
if (!f) {
426+
sError = "WsjcppObjTreeNodeString. Could not read string len. File broken. Can read " + std::to_string(f.gcount());
427+
return false;
428+
}
429+
nStringLen = *reinterpret_cast<uint32_t*>(arrInteger);
430+
char *pStr = new char[nStringLen];
431+
f.read(pStr, nStringLen);
432+
if (!f) {
433+
delete pStr;
434+
sError = "WsjcppObjTreeNodeString. Could not read string data. File broken. Can read " + std::to_string(f.gcount());
435+
return false;
436+
}
437+
m_sValue = std::string(pStr, nStringLen);
438+
return true;
439+
}
440+
441+
// ---------------------------------------------------------------------
442+
340443
std::string WsjcppObjTreeNodeString::toString(const std::string &sIntent) {
341444
return "string: " + m_sValue;
342445
}
@@ -376,6 +479,28 @@ const char *WsjcppObjTreeNodeInteger::getData() {
376479

377480
// ---------------------------------------------------------------------
378481

482+
bool WsjcppObjTreeNodeInteger::readDataPartFromFile(std::ifstream &f, std::string &sError) {
483+
// size
484+
// TODO remove - because this not need
485+
char arrBytes[4];
486+
f.read(arrBytes, 4);
487+
if (!f) {
488+
sError = "WsjcppObjTreeNodeInteger. Could not read string len. File broken. Can read " + std::to_string(f.gcount());
489+
return false;
490+
}
491+
// value
492+
f.read(arrBytes, 4);
493+
if (!f) {
494+
sError = "WsjcppObjTreeNodeInteger. Could not read string len. File broken. Can read " + std::to_string(f.gcount());
495+
return false;
496+
}
497+
static_assert(sizeof(uint32_t) == 4, "Expected sizeof(uint32_t) == 4");
498+
m_nValue = *reinterpret_cast<uint32_t*>(arrBytes);
499+
return true;
500+
}
501+
502+
// ---------------------------------------------------------------------
503+
379504
std::string WsjcppObjTreeNodeInteger::toString(const std::string &sIntent) {
380505
return "int: " + std::to_string(m_nValue);
381506
}
@@ -415,6 +540,28 @@ const char *WsjcppObjTreeNodeFloat::getData() {
415540

416541
// ---------------------------------------------------------------------
417542

543+
bool WsjcppObjTreeNodeFloat::readDataPartFromFile(std::ifstream &f, std::string &sError) {
544+
static_assert(sizeof(float) == 4, "Expected sizeof(float) == 4");
545+
// size
546+
// TODO remove - because this not need
547+
char arrBytes[4];
548+
f.read(arrBytes, 4);
549+
if (!f) {
550+
sError = "WsjcppObjTreeNodeInteger. Could not read string len. File broken. Can read " + std::to_string(f.gcount());
551+
return false;
552+
}
553+
// value
554+
f.read(arrBytes, 4);
555+
if (!f) {
556+
sError = "WsjcppObjTreeNodeFloat. Could not read string len. File broken. Can read " + std::to_string(f.gcount());
557+
return false;
558+
}
559+
m_nValue = *reinterpret_cast<float*>(arrBytes);
560+
return true;
561+
}
562+
563+
// ---------------------------------------------------------------------
564+
418565
std::string WsjcppObjTreeNodeFloat::toString(const std::string &sIntent) {
419566
return "float: " + std::to_string(m_nValue);
420567
}
@@ -454,6 +601,29 @@ const char *WsjcppObjTreeNodeDouble::getData() {
454601

455602
// ---------------------------------------------------------------------
456603

604+
bool WsjcppObjTreeNodeDouble::readDataPartFromFile(std::ifstream &f, std::string &sError) {
605+
static_assert(sizeof(double) == 8, "Expected sizeof(double) == 8");
606+
// size
607+
// TODO remove - because this not need
608+
char arrBytes4[4];
609+
f.read(arrBytes4, 4);
610+
if (!f) {
611+
sError = "WsjcppObjTreeNodeInteger. Could not read string len. File broken. Can read " + std::to_string(f.gcount());
612+
return false;
613+
}
614+
// value
615+
char arrBytes[8];
616+
f.read(arrBytes, 8);
617+
if (!f) {
618+
sError = "WsjcppObjTreeNodeDouble. Could not read string len. File broken. Can read " + std::to_string(f.gcount());
619+
return false;
620+
}
621+
m_nValue = *reinterpret_cast<double*>(arrBytes);
622+
return true;
623+
}
624+
625+
// ---------------------------------------------------------------------
626+
457627
std::string WsjcppObjTreeNodeDouble::toString(const std::string &sIntent) {
458628
return "double: " + std::to_string(m_nValue);
459629
}

src/wsjcpp_obj_tree.h

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ class WsjcppObjTreeNode {
2626
// virtual zero methods will be deny create basic class
2727
virtual int getDataSize() = 0;
2828
virtual const char *getData() = 0;
29+
virtual bool readDataPartFromFile(std::ifstream &f, std::string &sError) = 0;
30+
2931
virtual std::string toString(const std::string &sIntent = "") = 0;
3032

3133
WsjcppObjTreeNode *getParent();
@@ -41,9 +43,9 @@ class WsjcppObjTreeNode {
4143
private:
4244
WsjcppObjTree *m_pTree;
4345
WsjcppObjTreeNode *m_pParent;
44-
uint32_t m_nId;
46+
uint32_t m_nId; // it uniq identified node in a list
4547
std::vector<WsjcppObjTreeNode *> m_vChilds;
46-
uint16_t m_nType;
48+
uint16_t m_nType;
4749
};
4850

4951
class IFabricWsjcppObjTreeNode {
@@ -116,11 +118,14 @@ class WsjcppObjTree {
116118
private:
117119
std::string TAG;
118120
std::vector<WsjcppObjTreeNode *> m_vNodes;
119-
int m_nLastId;
121+
uint32_t m_nLastId; // Need for future if will be implemented function of remove nodes
120122
std::map<uint16_t, IFabricWsjcppObjTreeNode*> m_mapFabricTreeNode;
121123

122124
void writeUInt32(std::ofstream &f, uint32_t nVal);
125+
bool readUInt32(std::ifstream &f, uint32_t &nVal, std::string &sError);
126+
123127
void writeUInt16(std::ofstream &f, uint16_t nVal);
128+
bool readUInt16(std::ifstream &f, uint16_t &nVal, std::string &sError);
124129

125130
std::string toStringRecoursiveChilds(WsjcppObjTreeNode *pNode, const std::string &sIntent);
126131
};
@@ -171,6 +176,7 @@ class WsjcppObjTreeNodeString : public WsjcppObjTreeNode {
171176
// WsjcppObjTreeNode
172177
virtual int getDataSize() override;
173178
virtual const char *getData() override;
179+
virtual bool readDataPartFromFile(std::ifstream &f, std::string &sError) override;
174180
virtual std::string toString(const std::string &sIntent = "") override;
175181

176182
private:
@@ -191,6 +197,7 @@ class WsjcppObjTreeNodeInteger : public WsjcppObjTreeNode {
191197
// WsjcppObjTreeNode
192198
virtual int getDataSize() override;
193199
virtual const char *getData() override;
200+
virtual bool readDataPartFromFile(std::ifstream &f, std::string &sError) override;
194201
virtual std::string toString(const std::string &sIntent = "") override;
195202

196203
private:
@@ -210,6 +217,7 @@ class WsjcppObjTreeNodeFloat : public WsjcppObjTreeNode {
210217
// WsjcppObjTreeNode
211218
virtual int getDataSize() override;
212219
virtual const char *getData() override;
220+
virtual bool readDataPartFromFile(std::ifstream &f, std::string &sError) override;
213221
virtual std::string toString(const std::string &sIntent = "") override;
214222

215223
private:
@@ -230,6 +238,7 @@ class WsjcppObjTreeNodeDouble : public WsjcppObjTreeNode {
230238
// WsjcppObjTreeNode
231239
virtual int getDataSize() override;
232240
virtual const char *getData() override;
241+
virtual bool readDataPartFromFile(std::ifstream &f, std::string &sError) override;
233242
virtual std::string toString(const std::string &sIntent = "") override;
234243

235244
private:

unit-tests.wsjcpp/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ list (APPEND WSJCPP_SOURCES "../unit-tests.wsjcpp/src/unit_test_write_tree.h")
4242
list (APPEND WSJCPP_SOURCES "../unit-tests.wsjcpp/src/unit_test_write_tree.cpp")
4343
list (APPEND WSJCPP_SOURCES "../unit-tests.wsjcpp/src/unit_test_find_nodes.h")
4444
list (APPEND WSJCPP_SOURCES "../unit-tests.wsjcpp/src/unit_test_find_nodes.cpp")
45+
list (APPEND WSJCPP_SOURCES "../unit-tests.wsjcpp/src/unit_test_read_tree.h")
46+
list (APPEND WSJCPP_SOURCES "../unit-tests.wsjcpp/src/unit_test_read_tree.cpp")
4547

4648
include(${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.user-custom.txt)
4749

296 Bytes
Binary file not shown.
0 Bytes
Binary file not shown.
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#include "unit_test_read_tree.h"
2+
#include <vector>
3+
#include <wsjcpp_core.h>
4+
#include <wsjcpp_obj_tree.h>
5+
6+
REGISTRY_WSJCPP_UNIT_TEST(UnitTestReadTree)
7+
8+
UnitTestReadTree::UnitTestReadTree()
9+
: WsjcppUnitTestBase("UnitTestReadTree") {
10+
}
11+
12+
// ---------------------------------------------------------------------
13+
14+
void UnitTestReadTree::init() {
15+
// nothing
16+
}
17+
18+
// ---------------------------------------------------------------------
19+
20+
class CompStruct : public WsjcppObjTree {
21+
public:
22+
CompStruct() {
23+
addSupportType<WsjcppObjTreeNodeString>();
24+
addSupportType<WsjcppObjTreeNodeInteger>();
25+
addSupportType<WsjcppObjTreeNodeFloat>();
26+
addSupportType<WsjcppObjTreeNodeDouble>();
27+
}
28+
};
29+
30+
bool UnitTestReadTree::run() {
31+
bool bTestSuccess = true;
32+
33+
// TODO will be chnaged this to keeped files on the disk
34+
CompStruct comp;
35+
36+
std::string sFilename = "./data/readtreetest/example1.obj-tree";
37+
std::string sError;
38+
bool bWrote = comp.readTreeFromFile(sFilename, sError);
39+
compareB(bTestSuccess, "read from file", bWrote, true);
40+
41+
WsjcppLog::info(TAG, "\n" + comp.toString());
42+
43+
// char *pBuffer = nullptr;
44+
// int nBufferSize = 0;
45+
// WsjcppCore::readFileToBuffer(sFilename, &pBuffer, nBufferSize);
46+
47+
// compareN(bTestSuccess, "read to file", nBufferSize, 296);
48+
49+
return bTestSuccess;
50+
}
51+
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#ifndef UNIT_TEST_READ_TREE_H
2+
#define UNIT_TEST_READ_TREE_H
3+
4+
#include <wsjcpp_unit_tests.h>
5+
6+
// Description: TODO
7+
class UnitTestReadTree : public WsjcppUnitTestBase {
8+
public:
9+
UnitTestReadTree();
10+
virtual void init();
11+
virtual bool run();
12+
};
13+
14+
#endif // UNIT_TEST_READ_TREE_H
15+

0 commit comments

Comments
 (0)