Better handling of bad file format
This commit is contained in:
parent
4e4225f29d
commit
fad215ee3c
3 changed files with 611 additions and 89 deletions
|
|
@ -1,15 +1,46 @@
|
|||
#ifndef FILEDAT_H
|
||||
#define FILEDAT_H
|
||||
|
||||
#include "stringTools.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
//TESTS NEEDED
|
||||
#include <cstring>
|
||||
|
||||
class file_format_error : public std::exception
|
||||
{
|
||||
public:
|
||||
file_format_error(const std::string& what, const std::string& origin, const char* data, int where) { desc=what; index=where; filename=origin; cdat=data; }
|
||||
|
||||
const char * what () const throw () {return desc.c_str();}
|
||||
const int where () const throw () {return index;}
|
||||
const char * data() const throw () {return cdat;}
|
||||
const char * origin() const throw () {return filename.c_str();}
|
||||
private:
|
||||
std::string desc;
|
||||
int index;
|
||||
std::string filename;
|
||||
const char* cdat;
|
||||
};
|
||||
|
||||
class chunk_format_error : public std::exception
|
||||
{
|
||||
public:
|
||||
chunk_format_error(std::string const& what, int where) { desc=what; index=where; }
|
||||
|
||||
const char * what () const throw () {return desc.c_str();}
|
||||
const int where () const throw () {return index;}
|
||||
private:
|
||||
std::string desc;
|
||||
int index;
|
||||
};
|
||||
|
||||
void printFileException(file_format_error& exc);
|
||||
void printErrorIndex(const char* in, const int index, const std::string& message, const std::string& origin);
|
||||
|
||||
class Filedat;
|
||||
|
||||
class AbstractChunk
|
||||
{
|
||||
|
|
@ -28,20 +59,30 @@ protected:
|
|||
class Chunk
|
||||
{
|
||||
public:
|
||||
Chunk() { m_achunk=nullptr; }
|
||||
Chunk(char* const in) { m_achunk=nullptr; set(std::string(in)); }
|
||||
Chunk(std::string const& in) { m_achunk=nullptr; set(in); }
|
||||
Chunk(Chunk const& in) { m_achunk=nullptr; set(in); }
|
||||
Chunk(const char* in, const int in_size, int offset=0, Filedat* data=nullptr)
|
||||
{ m_achunk=nullptr; set(in, in_size, offset, data);}
|
||||
Chunk(std::string const& in, int offset=0, Filedat* data=nullptr)
|
||||
{ m_achunk=nullptr; set(in, offset, data);}
|
||||
|
||||
Chunk(Chunk const& in) { m_achunk=nullptr; set(in);}
|
||||
|
||||
void clear() { if(m_achunk!=nullptr) delete m_achunk; m_achunk=nullptr; }
|
||||
~Chunk() { clear(); }
|
||||
|
||||
void set(std::string const& in);
|
||||
void set(Chunk const& in); //TO OPTIMIZE
|
||||
Filedat* parent() const { return m_parent; }
|
||||
int offset() const { return m_offset; }
|
||||
|
||||
|
||||
void set(const char* in, const int in_size, int offset=0, Filedat* data=nullptr);
|
||||
void set(std::string const& in, int offset=0, Filedat* data=nullptr) { this->set(in.c_str(), in.size(), offset, data); }
|
||||
|
||||
void set(Chunk const& in) { this->set(in.strval(), in.offset(), in.parent()); } // TODO
|
||||
|
||||
std::string strval(unsigned int alignment=0, std::string const& aligner="\t") const;
|
||||
|
||||
|
||||
// bool concatenate(Chunk const& chk); //concatenates chunks
|
||||
bool addToChunk(std::string const& name, Chunk const& val); //adds if datachunk
|
||||
inline bool addToChunk(std::pair<std::string, Chunk> const& pair) { return add(pair.first, pair.second); } //adds if datachunk
|
||||
bool addToChunk(std::vector<std::pair<std::string, Chunk>> const& vec); //adds if datachunk
|
||||
bool addToList(Chunk const& val); //adds if list
|
||||
bool addToList(std::vector<Chunk> const& vec); //adds if list
|
||||
|
|
@ -66,15 +107,19 @@ public:
|
|||
Chunk& operator[](std::string const& a) const { return subChunkRef(a); }
|
||||
Chunk& operator[](unsigned int a) const { return subChunkRef(a); }
|
||||
Chunk& operator=(Chunk const& a) { set(a); return *this; }
|
||||
inline bool operator+=(std::pair<std::string, Chunk> const& a) { return addToChunk(a); }
|
||||
inline bool operator+=(std::vector<std::pair<std::string, Chunk>> const& a) { return addToChunk(a); }
|
||||
inline bool operator+=(Chunk const& a) { return addToList(a); }
|
||||
inline bool operator+=(std::vector<Chunk> const& a) { return addToList(a); }
|
||||
inline bool operator+=(std::pair<std::string, Chunk> const& a) { return add(a); }
|
||||
inline bool operator+=(std::vector<std::pair<std::string, Chunk>> const& a) { return add(a); }
|
||||
inline bool operator+=(Chunk const& a) { return add(a); }
|
||||
inline bool operator+=(std::vector<Chunk> const& a) { return add(a); }
|
||||
// inline bool operator*=(Chunk const& a) { concatenate(a); }
|
||||
|
||||
//add operator+ and operator*
|
||||
|
||||
|
||||
protected:
|
||||
Filedat* m_parent;
|
||||
int m_offset;
|
||||
|
||||
AbstractChunk* m_achunk;
|
||||
};
|
||||
|
||||
|
|
@ -117,24 +162,37 @@ public:
|
|||
|
||||
bool readTest() const;
|
||||
|
||||
bool importFile();
|
||||
void importFile();
|
||||
bool exportFile(std::string const& path="", std::string const& aligner="\t") const;
|
||||
|
||||
void clear();
|
||||
|
||||
std::string filePath() const { return m_filePath; }
|
||||
void setFilePath(std::string const& in) { m_filePath=in; }
|
||||
inline std::string filePath() const { return m_filePath; }
|
||||
inline void setFilePath(std::string const& in) { m_filePath=in; }
|
||||
|
||||
std::string strval() const;
|
||||
std::string strval(std::string const& aligner="\t") const;
|
||||
|
||||
inline Chunk* pchunk() const { return m_dataChunk; }
|
||||
inline Chunk& chunk() const { return *m_dataChunk; }
|
||||
Chunk* pchunk() const { return m_dataChunk; }
|
||||
Chunk& chunk() const { return *m_dataChunk; }
|
||||
|
||||
inline Chunk* pdata() const { return m_dataChunk; }
|
||||
inline Chunk& data() const { return *m_dataChunk; }
|
||||
|
||||
inline const std::string& stringdata() const { return m_data; }
|
||||
inline const char* c_data() const { return m_data.c_str(); }
|
||||
|
||||
Chunk& operator[](const std::string& index)
|
||||
{
|
||||
return m_dataChunk->subChunkRef(index);
|
||||
}
|
||||
Chunk& operator[](const int index)
|
||||
{
|
||||
return m_dataChunk->subChunkRef(index);
|
||||
}
|
||||
|
||||
private:
|
||||
std::string m_filePath;
|
||||
std::string m_data;
|
||||
Chunk* m_dataChunk;
|
||||
};
|
||||
|
||||
|
|
|
|||
569
src/Filedat.cpp
569
src/Filedat.cpp
|
|
@ -2,6 +2,51 @@
|
|||
|
||||
#include <exception>
|
||||
|
||||
bool _isRead(char in)
|
||||
{
|
||||
bool out=false;
|
||||
if(in>=33 && in<=126)
|
||||
out=true;
|
||||
return out;
|
||||
}
|
||||
|
||||
std::string _repeatString(const std::string& str, const unsigned int n)
|
||||
{
|
||||
std::string ret;
|
||||
for(unsigned int i=0 ; i<n ; i++)
|
||||
ret += str;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void printFileException(file_format_error& exc)
|
||||
{
|
||||
printErrorIndex(exc.data(), exc.where(), exc.what(), exc.origin());
|
||||
}
|
||||
|
||||
void printErrorIndex(const char* in, const int index, const std::string& message, const std::string& origin)
|
||||
{
|
||||
int i=0, j=0; // j: last newline
|
||||
int line=1; //n: line #
|
||||
int in_size=strlen(in);
|
||||
while(i < in_size && i < index)
|
||||
{
|
||||
if(in[i] == '\n')
|
||||
{
|
||||
line++;
|
||||
j=i+1;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
while(i < in_size && in[i]!='\n')
|
||||
{
|
||||
i++;
|
||||
}
|
||||
std::cerr << origin << ": Error\nLine " << line << " col " << index-j << ": " << message << std::endl;
|
||||
std::cerr << std::string(in+j, i-j) << std::endl;
|
||||
std::cerr << _repeatString(" ", index-j) << '^' << std::endl;
|
||||
}
|
||||
|
||||
|
||||
Filedat::Filedat()
|
||||
{
|
||||
m_dataChunk = nullptr;
|
||||
|
|
@ -15,10 +60,7 @@ Filedat::Filedat(std::string const& in)
|
|||
|
||||
Filedat::~Filedat()
|
||||
{
|
||||
if(m_dataChunk!=nullptr)
|
||||
{
|
||||
delete m_dataChunk;
|
||||
}
|
||||
this->clear();
|
||||
}
|
||||
|
||||
void Filedat::clear()
|
||||
|
|
@ -39,21 +81,32 @@ bool Filedat::readTest() const
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Filedat::importFile()
|
||||
void Filedat::importFile()
|
||||
{
|
||||
std::ifstream stream(m_filePath);
|
||||
if(!stream)
|
||||
return false;
|
||||
{
|
||||
throw std::runtime_error("Cannot open file '" + m_filePath + '\'');
|
||||
}
|
||||
|
||||
m_data="";
|
||||
std::string line;
|
||||
|
||||
std::string str, line;
|
||||
while(stream)
|
||||
{
|
||||
getline(stream, line);
|
||||
str += (line + '\n');
|
||||
m_data += (line + '\n');
|
||||
}
|
||||
|
||||
this->clear();
|
||||
m_dataChunk = new Chunk(str);
|
||||
return true;
|
||||
try
|
||||
{
|
||||
m_dataChunk = new Chunk(m_data.c_str(), m_data.size(), 0, this);
|
||||
}
|
||||
catch(chunk_format_error& e)
|
||||
{
|
||||
throw file_format_error(e.what(), m_filePath, m_data.c_str(), e.where());
|
||||
}
|
||||
}
|
||||
|
||||
bool Filedat::exportFile(std::string const& path, std::string const& aligner) const
|
||||
|
|
@ -65,61 +118,433 @@ bool Filedat::exportFile(std::string const& path, std::string const& aligner) co
|
|||
stream.open(path);
|
||||
if(!stream)
|
||||
return false;
|
||||
stream << this->strval();
|
||||
stream << this->strval(aligner);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string Filedat::strval() const
|
||||
std::string Filedat::strval(std::string const& aligner) const
|
||||
{
|
||||
if(m_dataChunk == nullptr)
|
||||
return "";
|
||||
else
|
||||
return m_dataChunk->strval();
|
||||
return m_dataChunk->strval(0, aligner);
|
||||
}
|
||||
|
||||
void Chunk::set(Chunk const& in)
|
||||
std::string _getname(const char* in, const int in_size, int* start, int* val_size, int* end)
|
||||
{
|
||||
this->set(in.strval());
|
||||
int i=0;
|
||||
|
||||
*start = in_size; //default no value
|
||||
*end = in_size; //default end
|
||||
*val_size=0; //default no value
|
||||
|
||||
while(i<in_size)
|
||||
{
|
||||
if(i+1<in_size && in[i] == '/' && in[i+1] == '/')
|
||||
while(i<in_size && in[i] != '\n')
|
||||
i++;
|
||||
|
||||
if(_isRead(in[i]))
|
||||
break;
|
||||
|
||||
i++;
|
||||
}
|
||||
if(i >= in_size) //ends without value
|
||||
return "";
|
||||
|
||||
int j=i; //name start
|
||||
while(i<in_size && in[i] != '=') //skip to =
|
||||
i++;
|
||||
if(i >= in_size) //no =
|
||||
{
|
||||
throw chunk_format_error("Tag has no value", j);
|
||||
}
|
||||
|
||||
if(i == j) //nothing preceding =
|
||||
throw chunk_format_error("Value has no tag", i);
|
||||
|
||||
int k=i-1; //name end
|
||||
while( !_isRead(in[k]) )
|
||||
k--;
|
||||
std::string name=std::string(in+j, k-j+1);
|
||||
|
||||
i++;
|
||||
while(i < in_size && !_isRead(in[i]))
|
||||
i++;
|
||||
if(i >= in_size) //no value
|
||||
{
|
||||
*start=i;
|
||||
*val_size=0;
|
||||
*end=i;
|
||||
return name;
|
||||
}
|
||||
if(in[i] == '\"') //"" val
|
||||
{
|
||||
i++;
|
||||
*start=i; //value starts
|
||||
j=0; //size
|
||||
while(i+j < in_size && in[i+j]!='\"')
|
||||
{
|
||||
if(in[i]+j=='\\')
|
||||
j++;
|
||||
j++;
|
||||
}
|
||||
if(i+j >= in_size) // no closing "
|
||||
throw chunk_format_error("Double quote does not close", i-1);
|
||||
*val_size=j;
|
||||
*end=i+j+1;
|
||||
return name;
|
||||
}
|
||||
if(in[i] == '\'') //"" val
|
||||
{
|
||||
i++;
|
||||
*start=i; //value starts
|
||||
j=0; //size
|
||||
while(i+j < in_size && in[i+j]!='\'')
|
||||
{
|
||||
if(in[i]+j=='\\')
|
||||
j++;
|
||||
j++;
|
||||
}
|
||||
if(i+j >= in_size) // no closing '
|
||||
throw chunk_format_error("Single quote does not close", i-1);
|
||||
*val_size=j;
|
||||
*end=i+j+1;
|
||||
return name;
|
||||
}
|
||||
if(in[i] == '{')
|
||||
{
|
||||
*start=i;
|
||||
j=1;
|
||||
int counter=0;
|
||||
while( i+j < in_size && !( counter == 0 && in[i+j]=='}') )
|
||||
{
|
||||
if(i+j+1<in_size && in[i+j] == '/' && in[i+j+1] == '/')
|
||||
while(i+j<in_size && in[i+j] != '\n')
|
||||
j++;
|
||||
if(in[i+j]=='\\')
|
||||
j++;
|
||||
if(in[i+j]=='{')
|
||||
counter++;
|
||||
if(in[i+j]=='}')
|
||||
counter--;
|
||||
j++;
|
||||
}
|
||||
if(i+j >= in_size) //reached end without closing
|
||||
throw chunk_format_error("Brace does not close", i);
|
||||
j++;
|
||||
*val_size=j;
|
||||
*end=i+j;
|
||||
return name;
|
||||
}
|
||||
if(in[i] == '[')
|
||||
{
|
||||
*start=i;
|
||||
j=1;
|
||||
int counter=0;
|
||||
while( i+j < in_size && !( counter == 0 && in[i+j]==']') )
|
||||
{
|
||||
if(i+j+1<in_size && in[i+j] == '/' && in[i+j+1] == '/')
|
||||
while(i+j<in_size && in[i+j] != '\n')
|
||||
j++;
|
||||
if(in[i+j]=='\\')
|
||||
j++;
|
||||
if(in[i+j]=='[')
|
||||
counter++;
|
||||
if(in[i+j]==']')
|
||||
counter--;
|
||||
j++;
|
||||
}
|
||||
if(i+j >= in_size) //reached end without closing
|
||||
throw chunk_format_error("Bracket does not close", i);
|
||||
j++;
|
||||
*val_size=j;
|
||||
*end=i+j;
|
||||
return name;
|
||||
}
|
||||
{ // no encapsulation: go to end of line
|
||||
*start=i; //value starts
|
||||
j=0; //size
|
||||
while(i+j < in_size && in[i+j]!='\n')
|
||||
{
|
||||
if(in[i]+j=='\\')
|
||||
j++;
|
||||
j++;
|
||||
}
|
||||
while( !_isRead(in[i+j]) )
|
||||
j--;
|
||||
*val_size=j+1;
|
||||
*end=i+j+1;
|
||||
return name;
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
void Chunk::set(std::string const& in)
|
||||
std::string _getlist(const char* in, const int in_size, int* start, int* end)
|
||||
{
|
||||
this->clear();
|
||||
std::string str=ridUnread(in);
|
||||
if(str[0]=='[')
|
||||
int i=0;
|
||||
std::string ret;
|
||||
|
||||
while(i<in_size)
|
||||
{
|
||||
std::vector<std::string> vstr = readList(in);
|
||||
ChunkList* cl = new ChunkList();
|
||||
for(auto it : vstr)
|
||||
{
|
||||
cl->list.push_back(new Chunk(it));
|
||||
}
|
||||
m_achunk=cl;
|
||||
if(i+1<in_size && in[i] == '/' && in[i+1] == '/')
|
||||
while(i<in_size && in[i] != '\n')
|
||||
i++;
|
||||
|
||||
if(_isRead(in[i]))
|
||||
break;
|
||||
|
||||
i++;
|
||||
}
|
||||
else if(str[0]=='{')
|
||||
|
||||
*start=i;
|
||||
if(i >= in_size) //ends without value
|
||||
{
|
||||
str=decapsulate(str);
|
||||
std::pair<std::string, std::string> pstr;
|
||||
int ti=0;
|
||||
DataChunk* dc = new DataChunk();
|
||||
while(str.size()>0 && ti>=0)
|
||||
{
|
||||
pstr = readValue(str,0,&ti);
|
||||
if(ti>=0)
|
||||
{
|
||||
dc->values.insert(std::make_pair(pstr.first , new Chunk(pstr.second)));
|
||||
if(ti > (int) str.size())
|
||||
throw std::runtime_error("Wrong file format at:\n" + str);
|
||||
str=str.substr(ti,str.size()-ti);
|
||||
}
|
||||
}
|
||||
m_achunk=dc;
|
||||
*end = in_size;
|
||||
return "";
|
||||
}
|
||||
else
|
||||
if(in[i] == ',') //value is empty
|
||||
{
|
||||
*end=i+1;
|
||||
return "";
|
||||
}
|
||||
|
||||
int j=0;
|
||||
if(in[i] == '\"') //"" val
|
||||
{
|
||||
i++;
|
||||
j=0; //size
|
||||
while(i+j < in_size && in[i+j]!='\"')
|
||||
{
|
||||
if(in[i]+j=='\\')
|
||||
j++;
|
||||
j++;
|
||||
}
|
||||
if(i+j >= in_size) // no closing "
|
||||
throw chunk_format_error("Double quote does not close", i-1);
|
||||
ret = std::string(in+i, j);
|
||||
*end=i+j+1;
|
||||
}
|
||||
else if(in[i] == '\'') //"" val
|
||||
{
|
||||
i++;
|
||||
j=0; //size
|
||||
while(i+j < in_size && in[i+j]!='\'')
|
||||
{
|
||||
if(in[i]+j=='\\')
|
||||
j++;
|
||||
j++;
|
||||
}
|
||||
if(i+j >= in_size) // no closing '
|
||||
throw chunk_format_error("Single quote does not close", i-1);
|
||||
ret = std::string(in+i, j);
|
||||
*end=i+j+1;
|
||||
}
|
||||
else if(in[i] == '{')
|
||||
{
|
||||
j=1;
|
||||
int counter=0;
|
||||
while( i+j < in_size && !( counter == 0 && in[i+j]=='}') )
|
||||
{
|
||||
if(i+j+1<in_size && in[i+j] == '/' && in[i+j+1] == '/')
|
||||
while(i+j<in_size && in[i+j] != '\n')
|
||||
j++;
|
||||
if(in[i+j]=='\\')
|
||||
j++;
|
||||
if(in[i+j]=='{')
|
||||
counter++;
|
||||
if(in[i+j]=='}')
|
||||
counter--;
|
||||
j++;
|
||||
}
|
||||
if(i+j >= in_size) //reached end without closing
|
||||
throw chunk_format_error("Brace does not close", i);
|
||||
j++;
|
||||
ret = std::string(in+i, j);
|
||||
*end=i+j;
|
||||
}
|
||||
else if(in[i] == '[')
|
||||
{
|
||||
j=1;
|
||||
int counter=0;
|
||||
while( i+j < in_size && !( counter == 0 && in[i+j]==']') )
|
||||
{
|
||||
if(i+j+1<in_size && in[i+j] == '/' && in[i+j+1] == '/')
|
||||
while(i+j<in_size && in[i+j] != '\n')
|
||||
j++;
|
||||
if(in[i+j]=='\\')
|
||||
j++;
|
||||
if(in[i+j]=='[')
|
||||
counter++;
|
||||
if(in[i+j]==']')
|
||||
counter--;
|
||||
j++;
|
||||
}
|
||||
if(i+j >= in_size) //reached end without closing
|
||||
throw chunk_format_error("Bracket does not close", i);
|
||||
j++;
|
||||
ret = std::string(in+i, j);
|
||||
*end=i+j;
|
||||
}
|
||||
else // no encapsulation: go to next ,
|
||||
{
|
||||
j=0; //size
|
||||
while(i+j < in_size && in[i+j]!=',')
|
||||
{
|
||||
if(in[i+j]=='\\')
|
||||
j++;
|
||||
j++;
|
||||
}
|
||||
if(i+j < in_size)
|
||||
{
|
||||
while( !_isRead(in[i+j]) )
|
||||
j--;
|
||||
}
|
||||
ret = std::string(in+i,j);
|
||||
*end=i+j;
|
||||
}
|
||||
|
||||
i = *end;
|
||||
while(i < in_size && !_isRead(in[i]))
|
||||
i++;
|
||||
if( i>= in_size ) //last char
|
||||
{
|
||||
*end=i;
|
||||
return ret;
|
||||
}
|
||||
else if(in[i] ==',') //comma as expected
|
||||
{
|
||||
*end=i+1;
|
||||
return ret;
|
||||
}
|
||||
else //Unexpected char
|
||||
throw chunk_format_error("Expecting comma", i);
|
||||
|
||||
}
|
||||
|
||||
void Chunk::set(const char* in, const int in_size, int offset, Filedat* data)
|
||||
{
|
||||
this->clear(); //reset everything
|
||||
this->m_parent=data;
|
||||
this->m_offset=offset;
|
||||
|
||||
int i=0;
|
||||
|
||||
while(i<in_size && !_isRead(in[i])) //skip unread char
|
||||
i++;
|
||||
|
||||
if(i >= in_size) //empty: make an empty strval
|
||||
{
|
||||
DataVal* cv = new DataVal();
|
||||
cv->val = in;
|
||||
m_achunk=cv;
|
||||
cv->val = "";
|
||||
return;
|
||||
}
|
||||
else if( in[i] == '{')
|
||||
{
|
||||
i++;
|
||||
int val_end=in_size-1;
|
||||
while(!_isRead(in[val_end])) //skip unread char
|
||||
val_end--;
|
||||
if(in[val_end] != '}')
|
||||
throw chunk_format_error("Expecting closing brace", val_end-1);
|
||||
|
||||
DataChunk* tch = new DataChunk();
|
||||
m_achunk = tch;
|
||||
|
||||
std::string name;
|
||||
std::string val;
|
||||
while(i < val_end)
|
||||
{
|
||||
int start=0;
|
||||
int _size=0;
|
||||
int end=0;
|
||||
|
||||
std::string newstr=std::string(in+i, val_end-i);
|
||||
try
|
||||
{
|
||||
name = _getname(newstr.c_str(), newstr.size(), &start, &_size, &end);
|
||||
val = newstr.substr(start, _size);
|
||||
}
|
||||
catch(chunk_format_error& e)
|
||||
{
|
||||
throw chunk_format_error(e.what(), e.where()+i);
|
||||
}
|
||||
|
||||
if( name == "" ) //no more values
|
||||
break;
|
||||
|
||||
try
|
||||
{
|
||||
tch->values.insert(std::make_pair(name, new Chunk(val.c_str(),val.size(), offset + start+i, m_parent) ));
|
||||
}
|
||||
catch(chunk_format_error& e)
|
||||
{
|
||||
throw chunk_format_error(e.what(), e.where() + start + i );
|
||||
}
|
||||
|
||||
i += end;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
else if( in[i] == '[')
|
||||
{
|
||||
i++;
|
||||
int val_end=in_size-1;
|
||||
while(!_isRead(in[val_end])) //skip unread char
|
||||
val_end--;
|
||||
if(in[val_end] != ']')
|
||||
throw chunk_format_error("Expecting closing bracket", val_end-1);
|
||||
|
||||
ChunkList* tch = new ChunkList();
|
||||
m_achunk = tch;
|
||||
|
||||
int end=0,start=0;
|
||||
while( i < val_end )
|
||||
{
|
||||
std::string val;
|
||||
std::string newstr=std::string(in+i, val_end-i);
|
||||
try
|
||||
{
|
||||
val = _getlist(newstr.c_str(), newstr.size(), &start, &end);
|
||||
}
|
||||
catch(chunk_format_error& e)
|
||||
{
|
||||
throw chunk_format_error(e.what(), e.where()+i);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
tch->list.push_back(new Chunk(val.c_str(),val.size(), offset + start+i, m_parent) );
|
||||
}
|
||||
catch(chunk_format_error& e)
|
||||
{
|
||||
throw chunk_format_error(e.what(), e.where() + start + i );
|
||||
}
|
||||
|
||||
i+=end;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
else // string value
|
||||
{
|
||||
int val_end=in_size;
|
||||
val_end--;
|
||||
while(!_isRead(in[val_end])) //skip unread char
|
||||
val_end--;
|
||||
|
||||
DataVal* tch = new DataVal();
|
||||
m_achunk = tch;
|
||||
|
||||
tch->val = std::string(in+i,val_end-i+1);
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -175,7 +600,7 @@ bool Chunk::addToList(std::vector<Chunk> const& vec)
|
|||
if(this->type()!=AbstractChunk::chunk && this->type()!=AbstractChunk::none)
|
||||
return false;
|
||||
for(auto it : vec)
|
||||
this->addToList(it);
|
||||
this->add(it);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -192,14 +617,14 @@ std::string Chunk::strval(unsigned int alignment, std::string const& aligner) co
|
|||
std::string ret="{\n";
|
||||
for(auto it : cp->values)
|
||||
{
|
||||
ret += repeatString(aligner,alignment+1);
|
||||
ret += _repeatString(aligner,alignment+1);
|
||||
ret += it.first;
|
||||
ret += '=';
|
||||
if(it.second!=nullptr)
|
||||
ret += it.second->strval(alignment+1, aligner);
|
||||
ret += '\n';
|
||||
}
|
||||
ret += repeatString(aligner, alignment);
|
||||
ret += _repeatString(aligner, alignment);
|
||||
ret += '}';
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -209,13 +634,13 @@ std::string Chunk::strval(unsigned int alignment, std::string const& aligner) co
|
|||
std::string ret="[\n";
|
||||
for(auto it : lp->list)
|
||||
{
|
||||
ret += repeatString(aligner, alignment+1);
|
||||
ret += _repeatString(aligner, alignment+1);
|
||||
if(it!=nullptr)
|
||||
ret += it->strval(alignment+1, aligner);
|
||||
ret += ",\n";
|
||||
}
|
||||
ret.erase(ret.end()-2);
|
||||
ret += repeatString(aligner, alignment);
|
||||
ret += _repeatString(aligner, alignment);
|
||||
ret += ']';
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -265,21 +690,57 @@ Chunk* Chunk::subChunkPtr(unsigned int a) const
|
|||
Chunk& Chunk::subChunkRef(std::string const& in) const
|
||||
{
|
||||
if(this->type()!=AbstractChunk::chunk)
|
||||
throw std::runtime_error("Chunk isn't a {}:" + this->strval());
|
||||
{
|
||||
if(m_parent != nullptr)
|
||||
{
|
||||
throw file_format_error("Element isn't a {}", m_parent->filePath(), m_parent->c_data(), m_offset );
|
||||
}
|
||||
else
|
||||
{
|
||||
throw chunk_format_error("Chunk isn't a {}", m_offset);
|
||||
}
|
||||
}
|
||||
DataChunk* dc = dynamic_cast<DataChunk*>(m_achunk);
|
||||
auto fi = dc->values.find(in);
|
||||
if(fi == dc->values.end())
|
||||
throw std::runtime_error("Chunk doesn't have '" + in + "' flag:\n" + this->strval());
|
||||
{
|
||||
if(m_parent != nullptr)
|
||||
{
|
||||
throw file_format_error("Chunk doesn't have '" + in + "' flag", m_parent->filePath(), m_parent->c_data(), m_offset );
|
||||
}
|
||||
else
|
||||
{
|
||||
throw chunk_format_error("Chunk doesn't have '" + in + "' flag", m_offset );
|
||||
}
|
||||
}
|
||||
return *fi->second;
|
||||
}
|
||||
|
||||
Chunk& Chunk::subChunkRef(unsigned int a) const
|
||||
{
|
||||
if(this->type()!=AbstractChunk::list)
|
||||
throw std::runtime_error("Chunk isn't a []:" + this->strval());
|
||||
{
|
||||
if(m_parent != nullptr)
|
||||
{
|
||||
throw file_format_error("Element isn't a {}", m_parent->filePath(), m_parent->c_data(), m_offset );
|
||||
}
|
||||
else
|
||||
{
|
||||
throw chunk_format_error("Chunk isn't a {}", m_offset);
|
||||
}
|
||||
}
|
||||
ChunkList* cl = dynamic_cast<ChunkList*>(m_achunk);
|
||||
if(a >= cl->list.size())
|
||||
throw std::runtime_error("List size is below " + std::to_string(a) + ":\n" + this->strval());
|
||||
{
|
||||
if(m_parent != nullptr)
|
||||
{
|
||||
throw file_format_error("List size is below " + std::to_string(a), m_parent->filePath(), m_parent->c_data(), m_offset );
|
||||
}
|
||||
else
|
||||
{
|
||||
throw chunk_format_error("List size is below " + std::to_string(a), m_offset );
|
||||
}
|
||||
}
|
||||
return *cl->list[a];
|
||||
}
|
||||
|
||||
|
|
|
|||
33
src/main.cpp
33
src/main.cpp
|
|
@ -7,6 +7,8 @@
|
|||
#include "Filedat.hpp"
|
||||
#include "options.hpp"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
|
||||
|
|
@ -39,25 +41,16 @@ int main(int argc, char* argv[])
|
|||
}
|
||||
|
||||
printf("Loading config file '%s'\n", arg[0].c_str());
|
||||
bool import_ok;
|
||||
try
|
||||
{
|
||||
import_ok = file.importFile();
|
||||
file.importFile();
|
||||
|
||||
if(import_ok)
|
||||
for(int i=0 ; i<file.chunk().listSize() ; i++)
|
||||
{
|
||||
for(int i=0 ; i<file.chunk().listSize() ; i++)
|
||||
{
|
||||
Device *newDevice = new Device;
|
||||
newDevice->import_chunk(file.chunk()[i]);
|
||||
device_list.push_back(newDevice);
|
||||
printf("Loaded %d commands for device '%s'\n", newDevice->nb_command, newDevice->name.c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Unknown config file error\n");
|
||||
return 2;
|
||||
Device *newDevice = new Device;
|
||||
newDevice->import_chunk(file[i]);
|
||||
device_list.push_back(newDevice);
|
||||
printf("Loaded %d commands for device '%s'\n", newDevice->nb_command, newDevice->name.c_str());
|
||||
}
|
||||
|
||||
printf("Starting scan for devices\n");
|
||||
|
|
@ -69,6 +62,16 @@ int main(int argc, char* argv[])
|
|||
}
|
||||
|
||||
}
|
||||
catch (file_format_error& e)
|
||||
{
|
||||
printErrorIndex(e.data(), e.where(), e.what(), e.origin());
|
||||
return 11;
|
||||
}
|
||||
catch (chunk_format_error& e)
|
||||
{
|
||||
std::cerr << "Chunk Error: " << e.what() << std::endl ;
|
||||
return 11;
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
std::cerr << "Exception: " << e.what() << std::endl;
|
||||
|
|
|
|||
Loading…
Reference in a new issue