51testing 发表于 2007-11-23 14:48:15

游戏编程系统2----Configuration System

不多说了,看代码吧
头文件
/************************************************************************/
/*
Config System
*/
/************************************************************************/
// Default config file
#define DEF_CONFIG   _T("D:\\myc\\dllSystem\\debug\\Config.cfg")

enum ValType
{
TYPE_EMPTY,
TYPE_VARIABLE,
TYPE_KEYWORD,
TYPE_BLOCK
};

class Value
{
std::string value;
int type;
int block;

public:
Value* next;

Value();

void set(std::string str, int bl, int key = TYPE_VARIABLE);
std::string& get();
const TCHAR* sget();

int is_keyword();
int is_block();
int get_block_id();
int get_type();
};

class Config
{
std::ifstream file;
TCHAR delimiter;
int vcol;

Value* svalue, *vstart;

int open_config_file(const TCHAR* name);
int close_config_file();
int read_config_file();

void S_trunc(std::string& str);

int search_block(const TCHAR* block);
const TCHAR* search_value(int col);

public:
Config();
Config(const TCHAR* name, int col = 1);
Config(TCHAR delim, int col = 1);
Config(const TCHAR* name, TCHAR delim, int col = 1);
int init(const TCHAR* name, TCHAR delim, int col);

~Config();

const TCHAR* value(const TCHAR* name, int col = 1);
const TCHAR* value(const TCHAR* block, const TCHAR* name, int col = 1);
const TCHAR* operator()(const TCHAR* name, int col = 1);
const TCHAR* operator()(const TCHAR* block, const TCHAR* name, int col = 1);

const TCHAR* _ivalue(const TCHAR* block, const TCHAR* name, int index, int col);
const TCHAR* ivalue(int index, int col = 1);
const TCHAR* ivalue(const TCHAR* block, int index, int col = 1);
const TCHAR* ivalue(const TCHAR* block, const TCHAR* name, int index, int col = 1);

const TCHAR* keyword(int index);
};


cpp文件
//////////////////////////////////////////////////////////////////////////
//Config System
//////////////////////////////////////////////////////////////////////////
int S_count(const std::string& s, TCHAR c);

Value::Value(void)
{
next = 0;
type = TYPE_EMPTY;
}

void Value::set(std::string str, int bl, int key /* = TYPE_VARIABLE */)
{
value = str;
type = key;
block = bl;
}

std::string& Value::get()
{
return value;
}

const TCHAR* Value::sget()
{
return value.c_str();
}

int Value::is_keyword()
{
return (type == TYPE_KEYWORD) ? 1 : 0;
}

int Value::is_block()
{
return (type == TYPE_BLOCK) ? 1 : 0;
}

int Value::get_block_id()
{
return block;
}

int Value::get_type()
{
return type;
}

Config::Config()
{
init(DEF_CONFIG, '=', 1);
}

Config::Config(const TCHAR* name, int col /* = 1 */)
{
init(name, '=', col);
}

Config::Config(TCHAR delim, int col /* = 1 */)
{
init(DEF_CONFIG, delim, col);
}

Config::Config(const TCHAR* name, TCHAR delim, int col /* = 1 */)
{
init(name, delim, col);
}

int Config::init(const TCHAR* name, TCHAR delim, int col)
{
delimiter = delim;
vcol = col;
if (vcol < 1)
vcol = 1;

svalue = 0;

open_config_file(name);
read_config_file();
close_config_file();

return 0;
}

Config::~Config()
{
if (vstart != 0)
{
while (vstart->next)
{
   svalue = vstart->next;
   delete vstart;
   vstart = svalue;
}
}
}

int Config::open_config_file(const TCHAR* name)
{
file.open(name);
if (!file)
MessageBox(NULL, "File Open Error!", "Error", MB_OK | MB_ICONSTOP);

return 0;
}

int Config::close_config_file()
{
file.close();

return 0;
}

const TCHAR* Config::operator ()(const TCHAR *name, int col /* = 1 */)
{
return value(name, col);
}

const TCHAR* Config::operator ()(const TCHAR *block, const TCHAR *name, int col /* = 1 */)
{
return value(block, name, col);
}

const TCHAR* Config::value(const TCHAR* block, const TCHAR* name, int col /* = 1 */)
{
if (name == NULL || col < 1)
return NULL;

svalue = vstart;

int block_id = 0;
block_id = search_block(block);

while (svalue->next)
{
if (block_id != svalue->get_block_id())
   break;

if (!(svalue->get()).compare(name) && svalue->is_keyword())
   return search_value(col);

svalue = svalue->next;
}

return NULL;
}

const TCHAR* Config::value(const TCHAR* name, int col /* = 1 */)
{
if (name == NULL || col < 1)
return NULL;

svalue = vstart;

while (svalue->next)
{
if (!(svalue->get()).compare(name) && svalue->is_keyword())
   return search_value(col);

svalue = svalue->next;
}

return NULL;
}

const TCHAR* Config::search_value(int col)
{
for (int i = 0; i < col; i++)
{
svalue = svalue->next;
if (svalue->next == NULL || svalue->is_keyword())
   return NULL;
}

return svalue->sget();
}

const TCHAR* Config::_ivalue(const TCHAR* block, const TCHAR* name, int index, int col)
{
if (index < 1 || col < 1)
return NULL;

svalue = vstart;

int block_id = 0;
if (block)
block_id = search_block(block);

int count = 0;
while (svalue->next)
{
if (block)
   if (block_id != svalue->get_block_id())
    break;

if (name)
{
   if (svalue->is_keyword() && !(svalue->get()).compare(name))
    count++;
}
else
{
   if (svalue->is_keyword())
    count++;
}

if (count == index)
   return search_value(col);

svalue = svalue->next;
}

return NULL;
}

int Config::search_block(const TCHAR* block)
{
int block_id = 0;

while (svalue->next)
{
if (!(svalue->get()).compare(block) && svalue->is_block())
{
   block_id = svalue->get_block_id();
   break;
}
svalue = svalue->next;
}

return block_id;
}

const TCHAR* Config::ivalue(int index, int col /* = 1 */)
{
return _ivalue(NULL, NULL, index, col);
}

const TCHAR* Config::ivalue(const TCHAR* block, int index, int col /* = 1 */)
{
return _ivalue(block, NULL, index, col);
}

const TCHAR* Config::ivalue(const TCHAR* block, const TCHAR* name, int index, int col /* = 1 */)
{
return _ivalue(block, name, index, col);
}

const TCHAR* Config::keyword(int index)
{
if (index < 1)
return NULL;

svalue = vstart;

int count = 0;
while (svalue->next)
{
if (svalue->is_keyword())
   count++;

if (count == index)
   return svalue->sget();

svalue = svalue->next;
}

return NULL;
}

int Config::read_config_file()
{
//std::string temp_buf;
std::string str, str_buf;
int block_no = 0;

int append = 0;
while (true)
{
if (svalue == 0)
{
   svalue = new Value;
   vstart = svalue;
}
else if (svalue->get_type() != TYPE_EMPTY)
{
   svalue->next = new Value;
   svalue = svalue->next;
}

if (getline(file, str_buf) == 0)
   break;

//str_buf = CA2W(temp_buf.c_str());

str_buf += '#';
str_buf = str_buf.substr(0, str_buf.find('#'));
S_trunc(str_buf);

if (append)
   str += str_buf;
else
   str = str_buf;

append = 0;

size_t pos = str.length();
if (pos <= 2)
   continue;
S_trunc(str);

if (str == '\\')
{
   size_t last = str.length() - 1;
   str.replace(last, 1, "");
   append = 1;
   continue;
}

if (str.length() <= 2 || str == '\r')
   continue;

if (str == '[' && str == ']')
{
   pos = str.length() - 1;
   str.replace(pos, 1, "");
   str.replace(0, 1, "");

   block_no++;
   svalue->set(str, block_no, TYPE_BLOCK);
   continue;
}

size_t is_delim = str.find(delimiter);
if (is_delim == -1)
   continue;

if (str == delimiter)
   continue;

str_buf = str.substr(0, str.find(delimiter));

S_trunc(str_buf);
svalue->set(str_buf, block_no, TYPE_KEYWORD);

int col = S_count(str, delimiter);

if (col > vcol)
   col = vcol;

pos = 0;
for (int i = 0; i < col; i++)
{
   svalue->next = new Value;
   svalue = svalue->next;

   pos = str.find(delimiter, pos + 1);
   str_buf = str.substr(pos + 1);

   if (i < col - 1)
   {
    str_buf += ':';
    str_buf = str_buf.substr(0, str_buf.find(delimiter));
   }

   S_trunc(str_buf);
   svalue->set(str_buf, block_no);
}
}

return 0;
}

int S_count(const std::string& s, TCHAR c)
{
int n = 0;
std::string::const_iterator i = find(s.begin(), s.end(), c);

while (i != s.end())
{
++n;
i = find(i + 1, s.end(), c);
}

return n;
}

void Config::S_trunc(std::string& str)
{
size_t pos = str.length();
if (pos <= 0)
return;

int count = 0;
while (iswspace(str))
{
pos--;
count++;
}
str.replace(pos, count, "");

count = 0;
pos = 0;
while (iswspace(str))
{
pos++;
count++;
}
str.replace(0, count, "");

if (str == '"' && str == '"')
{
pos = str.length() - 1;
str.replace(pos, 1, "");
str.replace(0, 1, "");
}
}


用的时候这样
Config g_Config;
g_Config.value(........);

比较郁闷的是在UNICODE里面,你处理的都是UNICODE的字符,但是读入和写入的时候必须要转换成ASCII,因为你在windows下面新建个文本文件默认存储格式还是ANSI...

UNICODE是趋势啊...vs.net 2005 默认工程全是 UNICODE了,strcpy也不让用了,不过strcpy_s也没什么区别的哈.
页: [1]
查看完整版本: 游戏编程系统2----Configuration System