#include "IniMemory.h"
#include "IniMemoryPrivate.h"
#include
#include
#include
#include
IniMemory::IniMemory():my(new IniMemoryPrivate(this))
{
strIniBuffer = nullptr;
my->listSection.clear();
}
IniMemory::IniMemory(char* strIni): my(new IniMemoryPrivate(this)), strIniBuffer(nullptr)
{
//将最后一个字符设置为换行
strIniBuffer = strIni;
//初始化失败,直接异常中断处理
if(!ReProcessIni()){
delete my;
my = nullptr;
throw "初始化失败,请检查ini内容是否合法。";
}
}
IniMemory::IniMemory(IniMemory& iniMemory): my(new IniMemoryPrivate(this)), strIniBuffer(nullptr)
{
//完全拷贝
this->strIniBuffer = iniMemory.strIniBuffer;
my->listSection = iniMemory.my->listSection;
}
IniMemory::~IniMemory()
{
if(my){
delete my;
my = nullptr;
}
}
IniMemory& IniMemory::operator=(char * buffer)
{
//如果空间不够,那么释放空间
if(nullptr == my){
my = new IniMemoryPrivate(this);
}
this->strIniBuffer = buffer;
//初始化失败,直接异常中断处理
if(!ReProcessIni()){
if(strIniBuffer){
strIniBuffer = nullptr;
}
my->listSection.clear();
}
return *this;
}
IniMemory& IniMemory::operator=(const IniMemory& iniMem)
{
if(&iniMem == this){
return *this;
}
if(nullptr == my){
my = new IniMemoryPrivate(this);
}
strIniBuffer = iniMem.strIniBuffer;
my->listSection = iniMem.my->listSection;
return *this;
}
bool IniMemory::SetBuffer(char *strIni)
{
this->strIniBuffer = strIni;
if(nullptr == my){
my = new IniMemoryPrivate(this);
}
//初始化失败,直接异常中断处理
if(!ReProcessIni()){
if(strIniBuffer){
strIniBuffer = nullptr;
}
my->listSection.clear();
}
return true;
}
std::string IniMemory::GetIniString(const std::string &strApp, const std::string &strKey, const std::string &strDefault)
{
if(my->listSection.empty()){
return strDefault;
}
//将strAppName转换成小写
std::string strAppName = strApp;
std::transform(strAppName.begin(), strAppName.end(), strAppName.begin(), ::tolower);
for (auto itIndex = my->listSection.begin(); itIndex != my->listSection.end(); itIndex++){
if(strAppName == itIndex->strSectionName){//找到了这个段
//继续查找属性
std::string strKeyName = strKey;
std::transform(strKeyName.begin(), strKeyName.end(), strKeyName.begin(), ::tolower);
for (auto itSubIndex = itIndex->listVarPair.begin(); itSubIndex != itIndex->listVarPair.end(); itSubIndex++){
//如果找到了这个属性,那么返回对应的值
if(strKeyName == itSubIndex->first){
return itSubIndex->second;
}
}
}
}
//如果没有找到对应的属性,那么直接返回默认值
return strDefault;
}
int IniMemory::GetIniInt(const std::string &strApp, const std::string &strKey, const int &nDefault)
{
if(my->listSection.empty()){
return nDefault;
}
//将strAppName转换成小写
std::string strAppName = strApp;
std::transform(strAppName.begin(), strAppName.end(), strAppName.begin(), ::tolower);
for (auto itIndex = my->listSection.begin(); itIndex != my->listSection.end(); itIndex++){
if(strAppName == itIndex->strSectionName){//找到了这个段
//继续查找属性
std::string strKeyName = strKey;
std::transform(strKeyName.begin(), strKeyName.end(), strKeyName.begin(), ::tolower);
for (auto itSubIndex = itIndex->listVarPair.begin(); itSubIndex != itIndex->listVarPair.end(); itSubIndex++){
//如果找到了这个属性,那么返回对应的值,将这个值转换成int类型返回
if(strKeyName == itSubIndex->first){
return ::atoi(itSubIndex->second.c_str());
}
}
}
}
//如果没有找到对应的属性,那么直接返回默认值
return nDefault;
}
bool IniMemory::WriteIniString(const std::string &strApp, const std::string &strKey, const std::string &strString)
{
//将strAppName转换成小写
std::string strAppName = strApp;
std::transform(strAppName.begin(), strAppName.end(), strAppName.begin(), ::tolower);
for (auto itIndex = my->listSection.begin(); itIndex != my->listSection.end(); itIndex++){
if(strAppName == itIndex->strSectionName){//找到了这个段
//继续查找属性
std::string strKeyName = strKey;
std::transform(strKeyName.begin(), strKeyName.end(), strKeyName.begin(), ::tolower);
for (auto itSubIndex = itIndex->listVarPair.begin(); itSubIndex != itIndex->listVarPair.end(); itSubIndex++){
//如果找到了这个属性,那么返回对应的值,将这个值转换成int类型返回
if(strKeyName == itSubIndex->first){
itSubIndex->second = strString;
//刷新缓冲区数据
return true;
}
}
itIndex->listVarPair.push_back(std::make_pair(std::string(strKeyName),std::string(strString)));
return true;
}
}
//插入一个新的段
IniMemoryPrivate::stSection section;
section.strSectionName = strApp;
my->listSection.push_back(section);
my->listSection.rbegin()->listVarPair.push_back(std::make_pair(std::string(strKey),std::string(strString)));
return true;
//如果没有找到对应的属性,那么直接返回默认值
}
bool IniMemory::WriteIniStringToNewBuffer(char *newBuffer, size_t nBufferSize, const std::string &strApp, const std::string &strKey, const std::string &strString)
{
//将strAppName转换成小写
std::string strAppName = strApp;
std::transform(strAppName.begin(), strAppName.end(), strAppName.begin(), ::tolower);
for (auto itIndex = my->listSection.begin(); itIndex != my->listSection.end(); itIndex++){
if(strAppName == itIndex->strSectionName){//找到了这个段
//继续查找属性
std::string strKeyName = strKey;
std::transform(strKeyName.begin(), strKeyName.end(), strKeyName.begin(), ::tolower);
for (auto itSubIndex = itIndex->listVarPair.begin(); itSubIndex != itIndex->listVarPair.end(); itSubIndex++){
//如果找到了这个属性,那么返回对应的值,将这个值转换成int类型返回
if(strKeyName == itSubIndex->first){
//保存这个值
std::string strTmp = itSubIndex->second;
//设置值
itSubIndex->second = strString;
//刷新缓冲区数据
bool bRes = FlushBuffer(newBuffer, nBufferSize);
//还原值
itSubIndex->second = strTmp;
return bRes;
}
}
itIndex->listVarPair.push_back(std::make_pair(std::string(strKeyName),std::string(strString)));
bool bRes = FlushBuffer(newBuffer, nBufferSize);
itIndex->listVarPair.pop_back();
return bRes;
}
}
//没有找到对应的段
IniMemoryPrivate::stSection section;
section.strSectionName = strApp;
my->listSection.push_back(section);
my->listSection.rbegin()->listVarPair.push_back(std::make_pair(std::string(strKey),std::string(strString)));
bool bRes = FlushBuffer(newBuffer, nBufferSize);
my->listSection.pop_back();
return bRes;
}
bool IniMemory::GetIniSection(std::list &strReturnedString)
{
if(my->listSection.empty()){
return false;
}
for (auto itIndex = my->listSection.begin(); itIndex != my->listSection.end(); itIndex++){
strReturnedString.push_back(itIndex->strSectionName);
}
return true;
}
bool IniMemory::GetIniSectionProperties(const std::string &strApp, std::list &strReturnedStringList)
{
if(my->listSection.empty()){
return false;
}
//查找这个块,找到了就将这个块里所有的变量全部放到这list里面
//将strAppName转换成小写
std::string strAppName = strApp;
std::transform(strAppName.begin(), strAppName.end(), strAppName.begin(), ::tolower);
for (auto itIndex = my->listSection.begin(); itIndex != my->listSection.end(); itIndex++){
if(strAppName == itIndex->strSectionName){//找到了这个段
for (auto itSubIndex = itIndex->listVarPair.begin(); itSubIndex != itIndex->listVarPair.end(); itSubIndex++){
//将所有属性放入list中
strReturnedStringList.push_back(itSubIndex->first);
}
return true;
}
}
//没有找到这个块
return false;
}
//重新解析
bool IniMemory::ReProcessIni()
{
if(nullptr == strIniBuffer){
return false;
}
my->listSection.clear();
char tmpBuffer[4096];
char* pEnd;
pEnd = strIniBuffer;
int n = 0;
while (*pEnd || 0 != n){
if('\n' == *pEnd || (0 != n && !(*pEnd))){
tmpBuffer[n] = '\0';
//获得了一行的内容,处理这一行
//判断是不是一个空行,注释行,是的话直接跳过
char* pBufferStart = tmpBuffer;
char* pBufferEnd =tmpBuffer + n - 1;
//处理前面的空格
while (' ' == *pBufferStart || '\t' == *pBufferStart){
pBufferStart++;
}
//处理末尾的空格符号
while (' ' == *pBufferEnd || '\r' == *pBufferEnd || '\t' == *pBufferEnd){
*pBufferEnd-- = '\0';
}
//如果是注释行,或者空行,那么直接跳过,处理下一行
if(';' == *pBufferStart || 0 == strlen(pBufferStart)){
;
}else if('[' == *pBufferStart){
pBufferStart++;
char* pos;
//判断是不是段名
//回这里如果找不到配对的],那么直接返false
if((pos = strchr(pBufferStart, ']'))){
char* check = pos+1;
*pos-- = '\0';
//这里我再处理一下空格
while (' ' == *pBufferStart || '\t' == *pBufferStart){
pBufferStart++;
}
while (' ' == *pos || '\t' == *pos){
*pos-- = '\0';
}
if(0 != strlen(pBufferStart)){
//将段名转换成小写
do{
*pos = tolower((int)*pos);
}while (pos-- != pBufferStart);
//得到了一个段名,那么申请一个新的stSection节点,将段名放入
IniMemoryPrivate::stSection section;
section.strSectionName = pBufferStart;
my->listSection.push_back(section);
}
//检查是不是合法的段名
while('\0' != *check){
if(';' == *check){
break;
}
if(' ' != *check && '\t' != *check){
my->listSection.clear();
strIniBuffer = nullptr;
return false;
}
check++;
}
}else{
strIniBuffer = nullptr;
return false;
}
}else{
//否则判断这一行是不是属性
char* pos = nullptr;
if((pos = strchr(pBufferStart, '='))){
//如果是一个变量,那么将该变量放入最后一个段的那个节点的list对中
char* pVarEnd = pos;
pVarEnd--;
//这里只需要把后面的空格去掉,因为前面的空格已经在最开始清除掉了
while (' ' == *pVarEnd || '\t' == *pVarEnd){
*pVarEnd-- = '\0';
}
//将变量名转换成小写
while (pVarEnd != pBufferStart){
*pVarEnd = ::tolower(*pVarEnd);
pVarEnd--;
}
*pVarEnd = ::tolower(*pVarEnd);
*pos++ = '\0';
while (' ' == *pos || '\t' == *pos){
pos++;
}
char* pSubPos = nullptr;
//注释忽略
if((pSubPos = strchr(pos, ';'))){
*pSubPos-- = '\0';
}
while (pSubPos && (' ' == *pSubPos || '\t' == *pSubPos)){
*pSubPos-- = '\0';
}
//设置如果变量名不空,那么放入
if(0 != strlen(pBufferStart)){
//全局的属性
if(0 == my->listSection.size()){
IniMemoryPrivate::stSection section;
section.strSectionName = "";
my->listSection.push_back(section);
}
//将该对值放入list中
my->listSection.rbegin()->listVarPair.push_back(std::make_pair(pBufferStart,pos));
}
}else{//说明不是段名,不是属性,也不是注释,那么要他干嘛,终止解析,game over
strIniBuffer = nullptr;
return false;
}
}
n = 0;
if('\n' == *pEnd){
pEnd++;
}
continue;
}else{
tmpBuffer[n] = *pEnd;
}
n++;
pEnd++;
}
strIniBuffer = nullptr;
return true;
}
size_t IniMemory::BufferSize()
{
//返回Buffer需要的大小
return my->CountNeedBuffer();
}
//将所有内容输出到新的缓冲区中
bool IniMemory::WriteToNewBuffer(char* NewBuffer, size_t nBufferSize)
{
return FlushBuffer(NewBuffer, nBufferSize);
}
//输出到新的缓冲区
bool IniMemory::FlushBuffer(char * newBuffer, size_t nBufferSize)
{
if(nullptr == newBuffer){
return false;
}
size_t Buffersize = my->CountNeedBuffer();
if(nBufferSize < Buffersize){
return false;
}
char* pBufferEnd = newBuffer;
//不去管内存大小够不够,这个问题留给外面去考虑,我只管复制
for (auto itIndex = my->listSection.begin(); itIndex != my->listSection.end(); itIndex++){
if(itIndex != my->listSection.begin() || "" != itIndex ->strSectionName){
*pBufferEnd++ = '[';
strcpy(pBufferEnd, itIndex->strSectionName.c_str());
pBufferEnd += strlen(pBufferEnd);
*pBufferEnd++ = ']';
*pBufferEnd++ = '\n';
}
//添加本段中的所有属性到配置文件中
for (auto itSubIndex = itIndex->listVarPair.begin(); itSubIndex != itIndex->listVarPair.end(); itSubIndex++){
//把变量名复制到相应位置
strcpy(pBufferEnd, itSubIndex->first.c_str());
pBufferEnd += strlen(pBufferEnd);
*pBufferEnd++ = '=';
strcpy(pBufferEnd, itSubIndex->second.c_str());
pBufferEnd += strlen(pBufferEnd);
*pBufferEnd++ = '\n';
}
}
*pBufferEnd = '\0';
return true;
}