#ifndef _XLSX_CLASS_
#define _XLSX_CLASS_
/*
* 代码整理:
* 工作中实现的一个读取配置的工具,Any.hpp未提供
* 通过闭包擦除类型,让容器包罗万象
* 提供类型转换,得益于模板编译期特性因此拥有强大的纠错能力
* 框架之上,寸草不生,框架之下,芸芸众生;
*/
#include<string>
#include"../Auxiliary/Any.hpp"
//#include"../Auxiliary/Result.hpp"
#include<assert.h>
#include<map>
#include<vector>
#include<fstream>
#include<algorithm>
#include<vector>
struct ParseCls
{
static bool isInMask(const int& index, const std::vector<std::pair<int, int> >& vec_mask)
{
for (auto& t : vec_mask)
{
if (index > t.first && index < t.second)
{
return true;
}
}
return false;
}
static bool split_string(const std::string& str, const std::string& delim, std::vector<std::string>& vecret)
{
size_t start = 0;
size_t index = str.find_first_of(delim, start);
while (index != std::string::npos)
{
vecret.push_back(str.substr(start, index - start));
start = index + 1;
index = str.find_first_of(delim, start);
}
if (index - start > 0)
{
vecret.push_back(str.substr(start, index - start));
}
return true;
}
static bool split_value(const std::string& str, const std::string& delim, const std::string& startdelim, const std::string& enddelim, std::vector<std::string>& vecret)
{
std::vector<std::pair<int, int> > vec_mask;
size_t mask_start = 0;
size_t mask_index = 0;
while (true)
{
mask_start = str.find_first_of(startdelim, mask_start);
if (mask_start != std::string::npos)
{
mask_index = str.find_first_of(enddelim, mask_start + 1);
if (mask_index == std::string::npos)
{
std::cout << "err: split_value -> Missing match character " << startdelim << std::endl;
assert(false);
//符号不匹配
}
vec_mask.push_back(std::make_pair(mask_start, mask_index));
mask_start = mask_index + 1;
}
else
{
break;
}
}
size_t start = 0;
size_t index = str.find_first_of(delim, start);
while (isInMask(index, vec_mask))
{
index = str.find_first_of(delim, index + 1);
}
while (index != std::string::npos)
{
vecret.push_back(str.substr(start, index - start));
start = index + 1;
index = str.find_first_of(delim, start);
while (isInMask(index, vec_mask))
{
index = str.find_first_of(delim, index + 1);
}
}
if (index - start > 0)
{
vecret.push_back(str.substr(start, index - start));
}
return true;
}
static bool inner_split_value(const std::string& str, const std::string& startdelim, const std::string& enddelim, std::vector<std::string>& vecret)
{
std::vector<std::pair<int, int> > vec_mask;
size_t mask_start = 0;
size_t mask_index = 0;
while (true)
{
mask_start = str.find_first_of(startdelim, mask_start);
if (mask_start != std::string::npos)
{
mask_index = str.find_first_of(enddelim, mask_start + 1);
if (mask_index == std::string::npos)
{
std::cout << "err: inner_split_value -> Missing match character " << startdelim << std::endl;
assert(false);
//符号不匹配
}
vec_mask.push_back(std::make_pair(mask_start + 1, mask_index));
mask_start = mask_index + 1;
}
else
{
break;
}
}
for (auto& v : vec_mask)
{
vecret.push_back(str.substr(v.first, v.second - v.first));
}
return true;
}
};
template<class T>
struct DataType
{
static Any value(const std::string& va)
{
std::cout << "err: Unsupported data type -> " << va << std::endl;
assert(false);
return Any();
}
};
template<> struct DataType<int>
{
static Any value(const std::string& va)
{
return Any(std::stoi(va));
}
};
template<> struct DataType<std::string>
{
static Any value(const std::string& va)
{
return Any(va);
}
};
template<> struct DataType<double>
{
static Any value(const std::string& va)
{
return Any(std::stod(va));
}
};
template<> struct DataType<float>
{
static Any value(const std::string& va)
{
return Any(std::stof(va));
}
};
template<> struct DataType<std::vector<std::vector<int> > >
{
static Any value(const std::string& va)
{
std::vector<std::string> vec_point_str;
std::vector<std::vector<int> > vec_point_value;
if (ParseCls::inner_split_value(va, "{", "}", vec_point_str))
{
for (auto& vp : vec_point_str)
{
std::vector<std::string> vec_value_str;
std::vector<int> vec_value;
if (ParseCls::split_string(vp, ",", vec_value_str))
{
for (auto& v : vec_value_str)
{
vec_value.push_back(std::stoi(v));
}
vec_point_value.push_back(vec_value);
}
}
return Any(vec_point_value);
}
else
{
assert(false);
return Any();
}
}
};
template<>
struct DataType<std::vector<std::vector<double> > >
{
static Any value(const std::string& va)
{
std::vector<std::string> vec_point_str;
std::vector<std::vector<double> > vec_point_value;
if (ParseCls::inner_split_value(va, "{", "}", vec_point_str))
{
for (auto& vp : vec_point_str)
{
std::vector<std::string> vec_value_str;
std::vector<double> vec_value;
if (ParseCls::split_string(vp, ",", vec_value_str))
{
for (auto& v : vec_value_str)
{
vec_value.push_back(std::stod(v));
}
vec_point_value.push_back(vec_value);
}
}
return Any(vec_point_value);
}
else
{
assert(false);
return Any();
}
}
};
class Object
{
private:
int Parse(std::vector<std::string>& vecType, std::vector<std::string> vecVaribl,
std::vector<std::string>& vec_value, std::map<std::string, Any>& map_varible)
{
int index = 0;
int key = -1;
for (auto& t : vecType)
{
if (t == "int")
{
map_varible.insert(std::make_pair(vecVaribl[index], DataType<int>::value(vec_value[index])));
}
else if (t == "string")
{
map_varible.insert(std::make_pair(vecVaribl[index], DataType<std::string>::value(vec_value[index])));
}
else if (t == "double")
{
map_varible.insert(std::make_pair(vecVaribl[index], DataType<double>::value(vec_value[index])));
}
else if (t == "float")
{
map_varible.insert(std::make_pair(vecVaribl[index], DataType<float>::value(vec_value[index])));
}
else if (t == "list<list<int>>")
{
map_varible.insert(std::make_pair(vecVaribl[index], DataType<std::vector<std::vector<int> > >::value(vec_value[index])));
}
else if (t == "vector<vector<int>>")
{
map_varible.insert(std::make_pair(vecVaribl[index], DataType<std::vector<std::vector<int> > >::value(vec_value[index])));
}
else if (t == "vector<vector<double>>")
{
map_varible.insert(std::make_pair(vecVaribl[index], DataType<std::vector<std::vector<double> > >::value(vec_value[index])));
}
else if (t == "list<list<double>>")
{
map_varible.insert(std::make_pair(vecVaribl[index], DataType<std::vector<std::vector<double> > >::value(vec_value[index])));
}
else
{
std::cout << "err: Unsupported data type -> " << t << std::endl;
assert(false);
}
index++;
}
return map_varible["index"].AnyCast<int>();
}
public:
bool ParseType(const std::string& type)
{
ParseCls::split_string(type, ",", vecType);
for (auto& v : vecType)
{
std::transform(v.begin(), v.end(), v.begin(), ::tolower);
}
return true;
}
bool ParseVriable(const std::string& varible)
{
ParseCls::split_string(varible, ",", vecVarible);
return true;
}
bool ParseValue(const int& row, const std::string& value)
{
std::vector<std::string> vec_value;
ParseCls::split_value(value, ",", "\"", "\"", vec_value);
if (verifyValue(vec_value))
{
std::map<std::string, Any> vec_varible;
int key = Parse(vecType, vecVarible, vec_value, vec_varible);
vec_Value.insert(std::make_pair(key, vec_varible));
rowkey.insert(std::make_pair(row,key));
return true;
}
std::cout << "err->" << value.c_str() << std::endl;
return false;
}
bool verifyValue(std::vector<std::string>& vec_value)
{
assert(vec_value.size() == vecType.size());
assert(vecVarible.size() == vecType.size());
for (auto& var : vec_value)
{
if (var.empty())
{
return false;
}
}
return true;
}
template<class _Ty>
_Ty& getValue(const int&id, const std::string& varName)
{
return (vec_Value[id])[varName].AnyCast<_Ty>();
}
template<class _Ty>
_Ty& getValue(const int& row, const int& col)
{
return (vec_Value[rowkey[row]])[vecVarible[col]].AnyCast<_Ty>();
}
template<class _Ty>
bool getWholeValueByColumu(std::vector<_Ty>& value,const std::string& varName)
{
for (auto& var : vec_Value)
{
value.push_back(var.second[varName].AnyCast<_Ty>());
}
return true;
}
template<class _Ty>
bool getWholeValueByColumu(std::vector<_Ty>& value, const int& col)
{
const std::string& varname = vecVarible[col];
for (auto& var : vec_Value)
{
value.push_back(var.second[varname].AnyCast<_Ty>());
}
return true;
}
size_t getRowCount()
{
return vec_Value.size();
}
size_t getColumuCount()
{
return vecVarible.size();
}
private:
std::vector<std::string> vecType;
std::vector<std::string> vecVarible;
std::map<int, std::map<std::string, Any> > vec_Value;
std::map<int, int> rowkey;
};
class XlsxClass
{
public:
bool registerClass(const std::string& clsName)
{
if (!_map_class.insert(std::map<std::string, std::shared_ptr<Object>>::value_type(clsName, std::shared_ptr<Object>(new Object()))).second)
{
std::cout << "err: registerClass Failed -> " << clsName << "Maybe the category already exists " << std::endl;
assert(false);
return false;
}
return true;
}
std::shared_ptr<Object> operator[](const std::string& clsName)
{
std::shared_ptr<Object> p = _map_class[clsName];
if (!p)
{
std::cout << "err: operator[] Failed -> " << clsName << "Maybe the clsName does not exists " << std::endl;
assert(false);
return NULL;
}
return p;
}
void clear()
{
_map_class.clear();
}
private:
std::map<std::string, std::shared_ptr<Object> > _map_class;
};
class XlsxClassReader
{
public:
void AddCsvFile(const std::string& ClassName, const std::string& file)
{
xls.registerClass(ClassName);
std::ifstream csvFile(file);
std::shared_ptr<Object> ptrObj = xls[ClassName];
if (!ptrObj)
{
std::cout << "err: AddCsvFile Failed -> " << file.c_str() << std::endl;
assert(false);
}
char str[360];
int index = 0;
int row = 3;
while (csvFile.getline(str, 360))
{
std::string value(str);
value.erase(std::remove(value.begin(), value.end(), ' '), value.end());
value.erase(std::remove(value.begin(), value.end(), ' '), value.end());
if (value.empty())
{
index++;
continue;
}
if (index == 0)
{
}
else if (index == 1)
{
xls[ClassName]->ParseVriable(value);
}
else if (index == 2)
{
xls[ClassName]->ParseType(value);
}
else
{
xls[ClassName]->ParseValue(row,value);
row++;
}
index++;
}
}
public:
template<typename _Ty>
_Ty& getValue(const std::string& clsName, const int& objid, const std::string& varName)
{
return xls[clsName]->getValue<_Ty>(objid, varName);
}
template<typename _Ty>
_Ty& getValue(const std::string& clsName, const int& row, const int& col)
{
return xls[clsName]->getValue<_Ty>(row + 3, col);
}
template<typename _Ty>
void getWholeListListValueByColumu(const std::string& clsName, std::vector<_Ty>& value, const int& col)
{
xls[clsName]->getWholeValueByColumu<_Ty>(value, col);
}
template<typename _Ty>
void getWholeListListValueByColumu(const std::string& clsName, std::vector<_Ty>& value, const std::string& varName)
{
xls[clsName]->getWholeValueByColumu<_Ty>(value, varName);
}
size_t getRowCount(const std::string& clsName)
{
return xls[clsName]->getRowCount();
}
size_t getColumuCount(const std::string& clsName)
{
return xls[clsName]->getColumuCount();
}
private:
XlsxClass xls;
};
class SingleXlsxClass
{
public:
bool registerClass(const std::string& clsName)
{
if (!_map_class.insert(std::map<std::string, std::shared_ptr<Object>>::value_type(clsName, std::shared_ptr<Object>(new Object()))).second)
{
std::cout << "err: registerClass Failed -> " << clsName << "Maybe the category already exists " << std::endl;
assert(false);
return false;
}
return true;
}
std::shared_ptr<Object> operator[](const std::string& clsName)
{
std::shared_ptr<Object> p = _map_class[clsName];
if (!p)
{
std::cout << "err: operator[] Failed -> " << clsName << "Maybe the clsName does not exists " << std::endl;
assert(false);
return NULL;
}
return p;
}
private:
std::map<std::string, std::shared_ptr<Object> > _map_class;
};
class SingleXlsxClassReader
{
public:
SingleXlsxClassReader()
{
}
SingleXlsxClassReader(const std::string& file)
{
SetCsvFile(file);
}
void SetCsvFile(const std::string& file)
{
xls.clear();
xls.registerClass("default");
std::ifstream csvFile(file);
std::shared_ptr<Object> ptrObj = xls["default"];
if (!ptrObj)
{
std::cout << "err: AddCsvFile Failed -> " << file.c_str() << std::endl;
assert(false);
}
char str[360];
int index = 0;
int row = 3;
while (csvFile.getline(str, 360))
{
std::string value(str);
value.erase(std::remove(value.begin(), value.end(), ' '), value.end());
value.erase(std::remove(value.begin(), value.end(), ' '), value.end());
if (value.empty())
{
index++;
continue;
}
if (index == 0)
{
}
else if (index == 1)
{
xls["default"]->ParseVriable(value);
}
else if (index == 2)
{
xls["default"]->ParseType(value);
}
else
{
xls["default"]->ParseValue(row, value);
row++;
}
index++;
}
}
public:
template<typename _Ty>
_Ty& getValue( const int& objid, const std::string& varName)
{
return xls["default"]->getValue<_Ty>(objid, varName);
}
template<typename _Ty>
_Ty& getValue(const int& row, const int& col)
{
return xls["default"]->getValue<_Ty>(row + 3, col);
}
template<typename _Ty>
void getWholeListListValueByColumu( std::vector<_Ty>& value, const int& col)
{
xls["default"]->getWholeValueByColumu<_Ty>(value, col);
}
template<typename _Ty>
void getWholeListListValueByColumu(std::vector<_Ty>& value, const std::string& varName)
{
xls["default"]->getWholeValueByColumu<_Ty>(value, varName);
}
size_t getRowCount()
{
return xls["default"]->getRowCount();
}
size_t getColumuCount()
{
return xls["default"]->getColumuCount();
}
private:
XlsxClass xls;
};
#endif