Page Menu
Home
Phabricator (Chris)
Search
Configure Global Search
Log In
Files
F118991
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
31 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/src/ITreeSerializer.h b/src/ITreeSerializer.h
index 517bd35..09fd24e 100644
--- a/src/ITreeSerializer.h
+++ b/src/ITreeSerializer.h
@@ -1,77 +1,81 @@
/*
* Copyright (C) 2011-2012 Me and My Shadow
*
* This file is part of Me and My Shadow.
*
* Me and My Shadow is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Me and My Shadow is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Me and My Shadow. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ITREESERIALIZER_H
#define ITREESERIALIZER_H
#include <string>
#include <vector>
#include <iostream>
#include <fstream>
#include "ITreeStorage.h"
+//An abstract class which is used to read/write data from TreeStorage to various file formats.
+//Currently only one file format is implemented, i.e. POASerializer. (Theoretically you can write a XMLSerializer.)
class ITreeSerializer{
public:
//Method used to read a node from an inputstream.
//fin: The inputstream to read from.
//objOut: The TreeStorageNode in which the result will come.
//loadSubNodeOnly: Boolean if only the subNodes should be loaded.
//Returns: False if there's an error while reading the node.
virtual bool readNode(std::istream& fin,ITreeStorageBuilder* objOut,bool loadSubNodeOnly=false)=0;
+
//Method used to write to an outputstream.
//obj: Pointer to the TreeStorageNode containing the data.
//fout: The output stream to write to.
- //writeHeader: TODO: ???
+ //writeHeader: Write the header to the file (e.g. XML file; not that POA file doesn't have a header).
//saveSubNodeOnly: Boolean if only the subNodes should be saved.
virtual void writeNode(ITreeStorageReader* obj,std::ostream& fout,bool writeHeader=true,bool saveSubNodeOnly=false)=0;
public:
//Method used to load a node from a file.
//fileName: The file to load from.
//objOut: The object to place the result in.
//loadSubNodeOnly: Boolean if only the subNodes should be loaded.
//Returns: False if there's an error while reading the node.
bool loadNodeFromFile(const char* fileName,ITreeStorageBuilder* objOut,bool loadSubNodeOnly=false){
//Open an inputstream.
std::ifstream f(fileName);
//If it failed then we return.
if(!f)
return false;
//It didn't fail so let the readNode method handle the rest.
return readNode(f,objOut,loadSubNodeOnly);
}
+
//Method used to write a node to a file.
//fileName: The file to save to.
//obj: Pointer to the TreeStorageNode containing the data.
- //writeHeader: TODO: ???
+ //writeHeader: Write the header to the file (e.g. XML file; not that POA file doesn't have a header).
//saveSubNodeOnly: Boolean if only the subNodes should be saved.
bool saveNodeToFile(const char* fileName,ITreeStorageReader* obj,bool writeHeader=true,bool saveSubNodeOnly=false){
//Open an outputstream.
std::ofstream f(fileName);
//If it failed then we return.
if(!f)
return false;
//It didn't fail so let the writeNode method handle the rest.
writeNode(obj,f,writeHeader,saveSubNodeOnly);
return true;
}
};
#endif
diff --git a/src/ITreeStorage.h b/src/ITreeStorage.h
index aa115b8..f6c7ff1 100644
--- a/src/ITreeStorage.h
+++ b/src/ITreeStorage.h
@@ -1,71 +1,86 @@
/*
* Copyright (C) 2011-2012 Me and My Shadow
*
* This file is part of Me and My Shadow.
*
* Me and My Shadow is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Me and My Shadow is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Me and My Shadow. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ITREESTORAGE_H
#define ITREESTORAGE_H
#include <string>
#include <vector>
+//An abstract class which is used to transfer the data from file to TreeStorage.
+//NOTE: Usually you should simply use the TreeStorageNode class.
+//You only need to use this class when you want to store the data in a customized way.
+//Another use case is you only want to read some of the property in the file, by using early exit feature.
class ITreeStorageBuilder{
public:
//Destructor.
virtual ~ITreeStorageBuilder(){}
//Set the name of the TreeStorageNode.
//name: The name to give.
- virtual void setName(std::string& name)=0;
+ //return value: true means early exit, i.e. doesn't read the file further.
+ virtual bool setName(std::string& name)=0;
+
//Set the value of the TreeStorageNode.
//value: The value to give.
- virtual void setValue(std::vector<std::string>& value)=0;
+ //return value: true means early exit, i.e. doesn't read the file further.
+ virtual bool setValue(std::vector<std::string>& value) = 0;
//Method that should create a new node in the TreeStorageNode and add it to it's subnodes.
- //Returns a pointer to the new TreeStorageNode.
+ //Returns a pointer to the new TreeStorageNode. NULL means early exit, i.e. doesn't read the file further.
virtual ITreeStorageBuilder* newNode()=0;
+
//Method that should add a new attribute to the TreeStorageNode.
//name: The name of the new attribute.
//value: The value(s) of the new attribute.
- virtual void newAttribute(std::string& name,std::vector<std::string>& value)=0;
-
+ //return value: true means early exit, i.e. doesn't read the file further.
+ virtual bool newAttribute(std::string& name, std::vector<std::string>& value) = 0;
};
+//An abstract class which is used to transfer the data from TreeStorage to file.
+//NOTE: Usually you should simply use the TreeStorageNode class.
+//You only need to use this class when you want to store the data in a customized way.
class ITreeStorageReader{
public:
//Destructor.
virtual ~ITreeStorageReader(){}
//Sets the parameter name to the name of the TreeStorageNode.
//name: The string to fill with the name;
virtual void getName(std::string& name)=0;
+
//Sets the parameter value to the value(s) of the TreeStorageNode.
//value: The vector to fill with the value(s);
virtual void getValue(std::vector<std::string>& value)=0;
//Method used for iterating through the attributes of the TreeStorageNode.
- //pUserData: Pointer TODO???
+ //pUserData: A user pointer, usually stores information about the iterator itself. NULL means get the first attribute.
//name: The string fill with the name of the attribute.
//value: Vector to fill with the value(s) of the attribute.
+ //return value: The new value of the user pointer. NULL means there are no more attributes.
virtual void* getNextAttribute(void* pUserData,std::string& name,std::vector<std::string>& value)=0;
+
//Method used for iterating through the subnodes of the TreeStorageNode.
- //pUserData: Pointer TODO???
+ //pUserData: A user pointer, usually stores information about the iterator itself. NULL means get the first node.
//obj: Pointer that will be pointed to the nextNode, if present.
+ //return value: The new value of the user pointer. NULL means there are no more nodes.
virtual void* getNextNode(void* pUserData,ITreeStorageReader*& obj)=0;
-
};
+
#endif
diff --git a/src/POASerializer.cpp b/src/POASerializer.cpp
index f7097d4..0f19f34 100644
--- a/src/POASerializer.cpp
+++ b/src/POASerializer.cpp
@@ -1,485 +1,504 @@
/*
* Copyright (C) 2011-2012 Me and My Shadow
*
* This file is part of Me and My Shadow.
*
* Me and My Shadow is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Me and My Shadow is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Me and My Shadow. If not, see <http://www.gnu.org/licenses/>.
*/
#include "POASerializer.h"
#include <sstream>
using namespace std;
static void readString(std::istream& fin,std::string& string){
//This method is used for reading a string from an input stream.
//fin: The input stream to read from.
//string: String to place the result in.
//The current character.
int c;
c=fin.get();
//Check if there's a '"'.
if(c=='\"'){
//There's a '"' so place every character we encounter in the string without parsing.
while((!fin.eof()) & (!fin.fail())){
//First we get the next character to prevent putting the '"' in the string.
c=fin.get();
//Check if there's a '"' since that could mean the end of the string.
if(c=='\"'){
//Get the next character and check if that's also an '"'.
c=fin.get();
if(c!='\"'){
//We have two '"' after each other meaning an escaped '"'.
//We unget one so there will be one '"' placed in the string.
fin.unget();
return;
}
}
//Every other character can be put in the string.
string.push_back(c);
}
}else{
//There are no quotes around the string so we need to be carefull detecting if the string has ended.
do{
switch(c){
//Check for characters that mean the end of the string.
case EOF:
case ' ':
case '\r':
case '\n':
case '\t':
return;
//Check for characters that are part of the POA file format.
//If so we first unget one character to prevent problems parsing the rest of the file.
case ',':
case '=':
case '(':
case ')':
case '{':
case '}':
case '#':
fin.unget();
return;
default:
//In any other case the character is normal so we put it in the string.
string.push_back(c);
}
//Get the next character.
c=fin.get();
}while((!fin.eof()) & (!fin.fail()));
}
}
static void skipWhitespaces(std::istream& fin){
//This function will read from the input stream until there's something else than whitespaces.
//fin: The input stream to read from.
//The current character.
int c;
while((!fin.eof()) & (!fin.fail())){
//Get the character.
c=fin.get();
//Check if it's one of the whitespace characters.
switch(c){
case EOF:
case ' ':
case '\r':
case '\n':
case '\t':
break;
default:
//Anything other means that the whitespaces have ended.
//Unget the last character and return.
fin.unget();
return;
}
}
}
static void skipComment(std::istream& fin){
//This function will read from the input stream until the end of a line (also end of the comment).
//fin: The input stream to read from.
//The current character.
int c;
while((!fin.eof()) & (!fin.fail())){
//Get the character.
c=fin.get();
//Check if it's a new line (end of comment).
if(c=='\r'||c=='\n'){
fin.unget();
break;
}
}
}
bool POASerializer::readNode(std::istream& fin,ITreeStorageBuilder* objOut,bool loadSubNodeOnly){
//The current character.
int c;
//The current mode of reading.
- //0=read name
- //1=read attribute value
- //2=read subnode value
- //16=add attribute
- //17=add subnode
- int mode;
+ enum ReadMode {
+ ReadName = 0,
+ ReadAttributeValue = 1,
+ ReadSubnodeValue = 2,
+ AddFirst = 16,
+ AddAttribute = 16,
+ AddSubnode = 17,
+ } mode = ReadName;
//Before reading make sure that the input stream isn't null.
if(!fin) return false;
//Vector containing the stack of TreeStorageNodes.
vector<ITreeStorageBuilder*> stack;
//A vector for the names and a vector for the values.
vector<string> names,values;
//Check if we only need to load subNodes.
//If so then put the objOut as the first TreeStorageNode.
if(loadSubNodeOnly) stack.push_back(objOut);
//Loop through the files.
while((!fin.eof()) && (!fin.fail())){
//Get a character.
c=fin.get();
//Check what it is and what to do with that character.
switch(c){
case EOF:
case ' ':
case '\r':
case '\n':
case '\t':
//We skip whitespaces.
break;
case '#':
//A comment so skip it.
skipComment(fin);
break;
case '}':
//A closing bracket so do one step back in the stack.
//There must be a TreeStorageNode left if not return false.
if(stack.empty()) return false;
//Remove the last entry of the stack.
stack.pop_back();
//Check if the stack is empty, if so than the reading of the node is done.
if(stack.empty()) return true;
objOut=stack.back();
break;
default:
//It isn't a special character but part of a name/value, so unget it.
fin.unget();
{
//Clear the names and values vectors, start reading new names/values.
names.clear();
values.clear();
//Set the mode to the read name mode.
- mode=0;
+ mode=ReadName;
//Keep reading characters, until we break out the while loop or there's an error.
while((!fin.eof()) & (!fin.fail())){
//The string containing the name.
string s;
//First skip the whiteSpaces.
skipWhitespaces(fin);
//Now get the string.
readString(fin,s);
//Check the mode.
switch(mode){
- case 0:
+ case ReadName:
//Mode is 0(read names) so put the string in the names vector.
names.push_back(s);
break;
- case 1:
- case 2:
+ case ReadAttributeValue:
+ case ReadSubnodeValue:
//Mode is 1 or 2 so put the string in the values vector.
values.push_back(s);
break;
}
//Again skip whitespaces.
skipWhitespaces(fin);
//Now read the next character.
c=fin.get();
switch(c){
case ',':
//A comma means one more name or value.
break;
case '=':
//An '=' can only occur after a name (mode=0).
- if(mode==0){
+ if(mode==ReadName){
//The next string will be a value so set mode to 1.
- mode=1;
+ mode=ReadAttributeValue;
}else{
//In any other case there's something wrong so return false.
return false;
}
break;
case '(':
//An '(' can only occur after a name (mode=0).
- if(mode==0){
+ if(mode==ReadName){
//The next string will be a value of a block so set mode to 2.
- mode=2;
+ mode=ReadSubnodeValue;
}else{
//In any other case there's something wrong so return false.
return false;
}
break;
case ')':
//A ')' can only occur after an attribute (mode=2).
- if(mode==2){
+ if(mode==ReadSubnodeValue){
//The next will be a new subNode so set mode to 17.
- mode=17;
+ mode=AddSubnode;
}else{
//In any other case there's something wrong so return false.
return false;
}
break;
case '{':
//A '{' can only mean a new subNode (mode=17).
fin.unget();
- mode=17;
+ mode=AddSubnode;
break;
default:
//The character is not special so unget it.
fin.unget();
- mode=16;
+ mode=AddAttribute;
break;
}
//We only need to break out if the mode is 16(add attribute) or 17(add subnode)
- if(mode>=16) break;
+ if(mode>=AddFirst) break;
}
//Check the mode.
switch(mode){
- case 16:
+ case AddAttribute:
//The mode is 16 so we need to change the names and values into attributes.
//The stack mustn't be empty.
if(stack.empty()) return false;
//Make sure that the result TreeStorageNode isn't null.
if(objOut!=NULL){
//Check if the names vector is empty, if so add an empty name.
if(names.empty()) names.push_back("");
//Put an empty value for every valueless name.
while(values.size()<names.size()) values.push_back("");
//Now loop through the names.
for(unsigned int i=0;i<names.size()-1;i++){
//Temp vector that will contain the values.
vector<string> v;
v.push_back(values[i]);
//And add the attribute.
- objOut->newAttribute(names[i],v);
+ if (objOut->newAttribute(names[i], v)) {
+ //Early exit.
+ return true;
+ }
}
if(names.size()>1) values.erase(values.begin(),values.begin()+(names.size()-1));
- objOut->newAttribute(names.back(),values);
+ if (objOut->newAttribute(names.back(), values)) {
+ //Early exit.
+ return true;
+ }
}
break;
- case 17:
+ case AddSubnode:
//The mode is 17 so we need to add a subNode.
{
//Check if the names vector is empty, if so add an empty name.
if(names.empty()) names.push_back("");
else if(names.size()>1){
if(stack.empty()) return false;
while(values.size()<names.size()) values.push_back("");
for(unsigned int i=0;i<names.size()-1;i++){
vector<string> v;
v.push_back(values[i]);
- objOut->newAttribute(names[i],v);
+ if (objOut->newAttribute(names[i], v)) {
+ //Early exit.
+ return true;
+ }
}
values.erase(values.begin(),values.begin()+(names.size()-1));
}
//Create a new subNode.
ITreeStorageBuilder* objNew=NULL;
//If the stack is empty the new subNode will be the result TreeStorageNode.
if(stack.empty()) objNew=objOut;
//If not the new subNode will be a subNode of the result TreeStorageNode.
- else if(objOut!=NULL) objNew=objOut->newNode();
+ else if (objOut != NULL) {
+ objNew = objOut->newNode();
+ if (objNew == NULL) {
+ //Early exit.
+ return true;
+ }
+ }
//Add it to the stack.
stack.push_back(objNew);
if(objNew!=NULL){
//Add the name and the values.
- objNew->setName(names.back());
- objNew->setValue(values);
+ if (objNew->setName(names.back()) || objNew->setValue(values)) {
+ //Early exit.
+ return true;
+ }
}
objOut=objNew;
//Skip the whitespaces.
skipWhitespaces(fin);
//And get the next character.
c=fin.get();
if(c!='{'){
//The character isn't a '{' meaning the block hasn't got a body.
fin.unget();
stack.pop_back();
//Check if perhaps we're done, stack=empty.
if(stack.empty()) return true;
objOut=stack.back();
}
}
break;
default:
//The mode isn't 16 or 17 but still broke out the while loop.
//Something's wrong so return false.
return false;
}
}
break;
}
}
return true;
}
static void writeString(std::ostream& fout,std::string& s){
//This method will write a string.
//fout: The output stream to write to.
//s: The string to write.
//new: check if the string is empty
if(s.empty()){
//because of the new changes of loader, we should output 2 quotes '""'
fout<<"\"\"";
}else
//Check if the string contains any special character that needs escaping.
if(s.find_first_of(" \r\n\t,=(){}#\"")!=string::npos){
//It does so we put '"' around them.
fout<<'\"';
//The current character.
int c;
//Loop through the characters.
for(unsigned int i=0;i<s.size();i++){
c=s[i];
//If there's a '"' character it needs to be counter escaped. ("")
if(c=='\"'){
fout<<"\"\"";
}else{
//If it isn't we can just write away the character.
fout<<(char)c;
}
}
fout<<'\"';
}else{
//It doesn't contain any special characters so we can write it away.
fout<<s;
}
}
static void writeStringArray(std::ostream& fout,std::vector<std::string>& s){
//This method will write a away an array of strings.
//fout: The output stream to write to.
//s: Vector containing the strings to write.
//Loop the strings.
for(unsigned int i=0;i<s.size();i++){
//If it's the second or more there must be a ",".
if(i>0) fout<<',';
//Now write the string.
writeString(fout,s[i]);
}
}
static void pWriteNode(ITreeStorageReader* obj,std::ostream& fout,int indent,bool saveSubNodeOnly){
//Write the TreeStorageNode to the given output stream.
//obj: The TreeStorageNode to write away.
//fout: The output stream to write to.
//indent: Integer containing the number of indentations are needed.
//saveSubNodeOnly: Boolean if only the subNodes need to be saved.
//Boolean if the node has subNodes.
bool haveSubNodes=false;
void* lpUserData=NULL;
ITreeStorageReader* objSubNode=NULL;
string s;
vector<string> v;
//---
if(obj==NULL) return;
//---
if(!saveSubNodeOnly){
for(int i=0;i<indent;i++) fout<<'\t';
s.clear();
obj->getName(s);
writeString(fout,s);
fout<<'(';
v.clear();
obj->getValue(v);
writeStringArray(fout,v);
fout<<')';
indent++;
}
//attributes
lpUserData=NULL;
for(;;){
s.clear();
v.clear();
lpUserData=obj->getNextAttribute(lpUserData,s,v);
if(lpUserData==NULL) break;
if(!haveSubNodes && !saveSubNodeOnly) fout<<"{\n";
haveSubNodes=true;
for(int i=0;i<indent;i++) fout<<'\t';
writeString(fout,s);
fout<<'=';
writeStringArray(fout,v);
fout<<'\n';
}
//subnodes
lpUserData=NULL;
for(;;){
lpUserData=obj->getNextNode(lpUserData,objSubNode);
if(lpUserData==NULL) break;
if(objSubNode!=NULL){
if(!haveSubNodes && !saveSubNodeOnly) fout<<"{\n";
haveSubNodes=true;
pWriteNode(objSubNode,fout,indent,false);
}
}
//---
if(!saveSubNodeOnly){
indent--;
if(haveSubNodes){
for(int i=0;i<indent;i++) fout<<'\t';
fout<<'}';
}
fout<<'\n';
}
}
void POASerializer::writeNode(ITreeStorageReader* obj,std::ostream& fout,bool writeHeader,bool saveSubNodeOnly){
//Make sure that the output stream isn't null.
if(!fout) return;
//It isn't so start writing the node.
pWriteNode(obj,fout,0,saveSubNodeOnly);
}
diff --git a/src/TreeStorageNode.cpp b/src/TreeStorageNode.cpp
index 1a06d10..e220978 100644
--- a/src/TreeStorageNode.cpp
+++ b/src/TreeStorageNode.cpp
@@ -1,156 +1,159 @@
/*
* Copyright (C) 2011-2012 Me and My Shadow
*
* This file is part of Me and My Shadow.
*
* Me and My Shadow is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Me and My Shadow is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Me and My Shadow. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef WIN32
#include <stdint.h>
#include <unistd.h>
#endif
#include "TreeStorageNode.h"
#include "MD5.h"
#include <string.h>
using namespace std;
TreeStorageNode::~TreeStorageNode(){
//The deconstructor will just calls destroy().
destroy();
}
void TreeStorageNode::destroy(){
//Loop through the subnodes and delete them.
for(unsigned int i=0;i<subNodes.size();i++){
delete subNodes[i];
}
//Now clear some stuff.
name.clear();
value.clear();
attributes.clear();
subNodes.clear();
}
-void TreeStorageNode::setName(std::string& name){
+bool TreeStorageNode::setName(std::string& name){
this->name=name;
+ return false;
}
void TreeStorageNode::getName(std::string& name){
name=this->name;
}
-void TreeStorageNode::setValue(std::vector<std::string>& value){
+bool TreeStorageNode::setValue(std::vector<std::string>& value){
this->value=value;
+ return false;
}
void TreeStorageNode::getValue(std::vector<std::string>& value){
value=this->value;
}
ITreeStorageBuilder* TreeStorageNode::newNode(){
TreeStorageNode* obj=new TreeStorageNode;
subNodes.push_back(obj);
return obj;
}
-void TreeStorageNode::newAttribute(std::string& name,std::vector<std::string>& value){
+bool TreeStorageNode::newAttribute(std::string& name,std::vector<std::string>& value){
//Put the attribute in the attributes map.
attributes[name]=value;
+ return false;
}
void* TreeStorageNode::getNextAttribute(void* pUserData,std::string& name,std::vector<std::string>& value){
if(pUserData==NULL) objAttrIterator=attributes.begin();
if(objAttrIterator!=attributes.end()){
name=objAttrIterator->first;
value=objAttrIterator->second;
++objAttrIterator;
return &objAttrIterator;
}else{
return NULL;
}
}
void* TreeStorageNode::getNextNode(void* pUserData,ITreeStorageReader*& obj){
intptr_t i=(intptr_t)pUserData;
//Check if the pointer is in range of the subNodes vector.
if(i<(int)subNodes.size()){
obj=subNodes[i];
return (void*)(i+1);
}else{
return NULL;
}
}
static void md5AppendString(Md5& md5,const string& s){
unsigned int sz=s.size();
unsigned char c[4];
c[0]=sz;
c[1]=sz>>8;
c[2]=sz>>16;
c[3]=sz>>24;
md5.update(c,4);
if(sz>0) md5.update(s.c_str(),sz);
}
static void md5AppendVector(Md5& md5,const vector<string>& v){
unsigned int sz=v.size();
unsigned char c[4];
c[0]=sz;
c[1]=sz>>8;
c[2]=sz>>16;
c[3]=sz>>24;
md5.update(c,4);
for(unsigned int i=0;i<sz;i++){
md5AppendString(md5,v[i]);
}
}
static void md5AppendMap(Md5& md5,const map<string,vector<string> >& m){
unsigned int sz=m.size();
unsigned char c[4];
c[0]=sz;
c[1]=sz>>8;
c[2]=sz>>16;
c[3]=sz>>24;
md5.update(c,4);
for(map<string,vector<string> >::const_iterator it=m.begin();it!=m.end();++it){
md5AppendString(md5,it->first);
md5AppendVector(md5,it->second);
}
}
unsigned char* TreeStorageNode::calcMD5(unsigned char* md){
unsigned char digest[16];
Md5 md5;
md5.init();
md5AppendString(md5,name);
md5AppendVector(md5,value);
md5AppendMap(md5,attributes);
for(unsigned int i=0;i<subNodes.size();i++){
TreeStorageNode *node=subNodes[i];
if(node==NULL){
memset(digest,0,16);
}else{
node->calcMD5(digest);
}
md5.update(digest,16);
}
return md5.final(md);
}
diff --git a/src/TreeStorageNode.h b/src/TreeStorageNode.h
index 49b0ccc..ca6a3fc 100644
--- a/src/TreeStorageNode.h
+++ b/src/TreeStorageNode.h
@@ -1,93 +1,93 @@
/*
* Copyright (C) 2011-2012 Me and My Shadow
*
* This file is part of Me and My Shadow.
*
* Me and My Shadow is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Me and My Shadow is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Me and My Shadow. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TREESTORAGENODE_H
#define TREESTORAGENODE_H
#include "ITreeStorage.h"
#include <map>
#include <vector>
#include <string>
//This class is used to store data in a tree-structured way.
//Every (TreeStorage)Node has a vector with subNodes and every Node contains a hashmap with attributes.
class TreeStorageNode:public ITreeStorageBuilder,public ITreeStorageReader{
private:
//Iterator used to iterate the hashmap with attributes.
//Used by the methods getNextAttribute and getNextNode.
std::map<std::string,std::vector<std::string> >::iterator objAttrIterator;
public:
//Vector containing the subnodes of the TreeStorageNode.
std::vector<TreeStorageNode*> subNodes;
//String containing the name of the TreeStorageNode.
std::string name;
//Vector containing the value(s) of the TreeStorageNode.
std::vector<std::string> value;
//Hashmap containing the attributes of the TreeStorageNode.
std::map<std::string,std::vector<std::string> > attributes;
//Constructor.
TreeStorageNode(){}
//Destructor.
virtual ~TreeStorageNode();
//This method is used to destroy the TreeStorageNode.
//Also called when the deconstructor is called.
void destroy();
//Set the name of the TreeStorageNode.
//name: The name to give.
- virtual void setName(std::string& name);
+ virtual bool setName(std::string& name);
//Sets the parameter name to the name of the TreeStorageNode.
//name: The string to fill with the name;
virtual void getName(std::string& name);
//Set the value of the TreeStorageNode.
//value: The value to give.
- virtual void setValue(std::vector<std::string>& value);
+ virtual bool setValue(std::vector<std::string>& value);
//Sets the parameter value to the value of the TreeStorageNode.
//value: The string to fill with the name;
virtual void getValue(std::vector<std::string>& value);
//Creates a new node in the TreeStorageNode.
//The new node will be added to the subnodes.
//Returns: a pointer to the new node.
virtual ITreeStorageBuilder* newNode();
//Creates a new attribute in the TreeStorageNode.
//The attribute will be added to the attributes map.
//name: The name for the new attribute.
//value: The value for the new attribute.
- virtual void newAttribute(std::string& name,std::vector<std::string>& value);
+ virtual bool newAttribute(std::string& name,std::vector<std::string>& value);
//Method used for iterating through the attributes of the TreeStorageNode.
- //pUserData: Pointer TODO???
+ //pUserData: Pointer to the iterator.
//name: The string fill with the name of the attribute.
//value: Vector to fill with the value(s) of the attribute.
virtual void* getNextAttribute(void* pUserData,std::string& name,std::vector<std::string>& value);
//Method used for iterating through the subnodes of the TreeStorageNode.
- //pUserData: Pointer TODO???
+ //pUserData: Pointer to the iterator.
//obj: Pointer that will be pointed to the nextNode, if present.
virtual void* getNextNode(void* pUserData,ITreeStorageReader*& obj);
//Calculate the MD5 of node based on the data structure.
//places the message digest in md,
//which must have space for 16 bytes of output (or NULL).
unsigned char* calcMD5(unsigned char* md);
};
#endif
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sat, May 16, 8:29 PM (1 d, 19 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
63813
Default Alt Text
(31 KB)
Attached To
Mode
R79 meandmyshadow
Attached
Detach File
Event Timeline