www.gusucode.com > VC++游戏圣剑英雄传2双刃剑源程序+开发文档-源码程序 > VC++游戏圣剑英雄传2双刃剑源程序+开发文档-源码程序\code\source\GAMELIB\Gp_iniset.cpp

    //Download by http://www.NewXing.com
//********************************************
//	IniSet 相关函数
//  创建于2000年4月7日
//********************************************

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <io.h>
#include <fcntl.h>
#include "gp_init.h"
#include "gp_other.h"
#include "gp_iniset.h"

/////////////////////////////////////////////////////////////////////
//
/////////////////////////////////////////////////////////////////////

//初始化
CIniSet::CIniSet()
{
	DataLen=0;
	Data=NULL;
	IndexNum=0;
	IndexList=NULL;
}

//初始化
CIniSet::CIniSet(char *filename)
{
	DataLen=0;
	Data=NULL;
	IndexNum=0;
	IndexList=NULL;
	Open(filename);
}

//析构释放
CIniSet::~CIniSet()
{
	if( DataLen != 0 && Data != NULL )
	{
		_DELETE( Data );
	}

	if( IndexNum != 0 && IndexList != NULL )
	{
		_DELETE( IndexList );
	}
}

//读入文件
bool CIniSet::Open(char *filename)
{
	strcpy(FileName, filename);

	_DELETE( Data );

	DataLen=GetFileLength(filename);	//获取文件长度
	if( DataLen > 0 )		//文件存在
	{
		Data=new char[DataLen];

		FILE *fp;
		fp=fopen(filename, "rb");
		fread(Data, DataLen, 1, fp);		//读数据
		fclose(fp);

		//初始化索引
		InitIndex();
	}
	else
	{
		DataLen=1;
		Data=new char[DataLen];
		memset(Data, 0, 1);
		InitIndex();
	}

	return false;
}

//写入文件
bool CIniSet::Save(char *filename)
{
	if( filename==NULL )
		filename=FileName;

	FILE *fp;
	fp=fopen(filename, "wb");
	if( fp==NULL )
	{
		ShowMessage("Can't save %s ",filename);
		return false;
	}

	fwrite(Data, DataLen, 1, fp);
	fclose(fp);

	return true;
}

//计算出所有的索引位置
void CIniSet::InitIndex()
{
	IndexNum=0;

	for(int i=0; i<DataLen; i++)
	{
		//找到,要以[开头,而且段与段之间要用回车分开
		if( Data[i]=='[' && (i==0||(i>0&&Data[i-1]=='\n')  ) )
		{
			IndexNum++;
		}
	}

	//申请内存
	_DELETE( IndexList );
	if( IndexNum>0 )
		IndexList=new int[IndexNum];

	int n=0;
	//初始化
	for(i=0; i<DataLen; i++)
	{
		if( Data[i]=='[' && ((i>0&&Data[i-1]=='\n' )|| i==0) )
		{
			IndexList[n]=i+1;		//保存到索引表的位置是 [ 的下一个字符的位置
			n++;
		}
	}
}

/////////////////////////////////////////////////////////////////////
//
/////////////////////////////////////////////////////////////////////

//返回指定标题位置
int CIniSet::FindIndex(char *string)
{
	for(int i=0; i<IndexNum; i++)
	{
		char *str=ReadText( IndexList[i] );		//遍历索引表,读所以的索引
		if( strcmp(string, str) == 0 )			//比较,如果向同就返回标题的位置
		{
			_FREE( str );
			return IndexList[i];				//索引所在的位置,是 [ 的字符的下一个位置
		}
		_FREE( str );
	}
	return -1;
}

//返回指定数据的内容的位置
int CIniSet::FindData(int index, char *string)
{
	int p=index;	//指针

	while(1)
	{									//跳过标题(索引)所在的行
		p=GotoNextLine(p);				//下一行的位置
		char *name=ReadDataName(p);		//读一个名字,注意p是按地址的方式传参的
		if( strcmp(string, name)==0 )	//相同就返回位置,数据内容开始的位置
		{
			_FREE( name );
			return p;
		}

		_FREE( name );
		if( p>=DataLen ) return -1;		//没有找到
	}
	return -1;
}

//提行
int CIniSet::GotoNextLine(int p)
{
	for(int i=p; i<DataLen; i++)
	{
		if( Data[i]=='\n' )				//回车换行
			return i+1;

	}
	return i;
}

//在指定位置读一数据名称
char *CIniSet::ReadDataName(int &p)			//引用参数,将通过p返回,而其值是
{											//数据的内容的位置
	char chr;
	char *Ret;
	int m=0;

	Ret=(char *)malloc(256);
	memset(Ret, 0, 256);

	for(int i=p; i<DataLen; i++)
	{
		chr=Data[i];

		//结束
		if( chr == '\r' )
		{
			p=i+1;			
			return Ret;
		}
		
		//结束
		if( chr == '=' || chr == ';' )
		{
			p=i+1;						//指向数据的内容,跳过了分隔符
			return Ret;
		}
		
		Ret[m]=chr;
		m++;
	}
	return Ret;
}

//在指定位置读一字符串
char *CIniSet::ReadText(int p)
{
	char chr;
	char *Ret;
	int n=p, m=0;

	int EndLine=GotoNextLine(p);		//下一行的位置,只读一行的内容
	Ret=(char *)malloc(EndLine-p+1);	//分配内存
	memset(Ret, 0, EndLine-p+1);		//清0

	for(int i=0; i<DataLen-p; i++)
	{
		chr=Data[n];

		//结束			用分号,回车,TAB或者是]结束
		if( chr == ';' || chr == '\r' || chr == '\t' || chr == ']' )
		{
			return Ret;
		}
		
		Ret[m]=chr;		//读入到缓冲区
		m++;
		n++;
	}
	return Ret;
}

/////////////////////////////////////////////////////////////////////
//
/////////////////////////////////////////////////////////////////////

//以普通方式读一字符串数据
char *CIniSet::ReadText(char *index, char *name)
{
	int n=FindIndex(index);				//通过索引名字找到位置
	if( n == -1 )
	{
		ShowMessage("Can't find [%s] in file '%s'!", index, FileName);
		return "";
	}

	int m=FindData(n, name);			//通过索引的位置和数据名字找到数据内容的位置
	if( m==-1 )
	{
		ShowMessage("Can't find [%s]-'%s' in file '%s'!", index, name, FileName);
		return "";
	}

	return ReadText(m);					//读出该内容
}
	
//在指定的行读一字符串,设计这个函数是用于读出一批数据,
//而且可以不关心具体的名字,可以用循环的方式读
char *CIniSet::ReadText(char *index, int lines)
{
	int n=FindIndex(index);				//通过索引名字找到位置
	if( n == -1 )
	{
		ShowMessage("Can't find [%s] in file '%s'!", index, FileName);
		return "";
	}

	//跳到指定行数
	n=GotoNextLine(n);
	for(int i=0; i<lines; i++)
	{
		if( n<DataLen )
			n=GotoNextLine(n);
	}

	//读数据
	while( n<=DataLen )
	{
		if( Data[n] == '=' )		//找到分隔符 =
		{
			n++;					//移动到=的下一个字符
			return ReadText(n);		//读出内容
		}
		if( Data[n] == '\r' )
		{
			return "";				//没有找到
		}
		n++;
	}

	return "";
}

//以普通方式读一整数数据
int CIniSet::ReadInt(char *index, char *name)
{
	int n=FindIndex(index);			//…………
	if( n == -1 )
	{
		ShowMessage("Can't find [%s] in file <%s>",index, FileName);
		return ERROR_DATA;
	}

	int m=FindData(n, name);		//看看上面的注释
	if( m==-1 )
	{
		ShowMessage("Can't find [%s] '%s' in file <%s>",index, name, FileName);
		return ERROR_DATA;
	}

	char *str=ReadText(m);			//………………
	int ret=atoi(str);				//转化成整数
	_FREE(str);
	return ret;
}

//在指定的行读一整数,同样是为了成批的读取,而且可以不关心具体的名字
int CIniSet::ReadInt(char *index, int lines)
{
	int n=FindIndex(index);			//不想多说了
	if( n == -1 )
	{
		ShowMessage("Can't find [%s] in file <%s>",index, FileName);
		return ERROR_DATA;
	}

	//跳到指定行数
	n=GotoNextLine(n);
	for(int i=0; i<lines; i++)
	{
		if( n<DataLen )
			n=GotoNextLine(n);
	}

	//读数据
	while( n<DataLen )
	{
		if( Data[n] == '=' )		//应该是明白了吧,不明白就看看上面的注释
		{
			n++;
			char *str=ReadText(n);	//…………
			int ret=atoi(str);
			_FREE(str);
			return ret;
		}
		if( Data[n] == '\r' )
		{
			return ERROR_DATA;
		}
		n++;
	}

	return ERROR_DATA;
}

//在指定的行读一数据名称,目的…………
char *CIniSet::ReadData(char *index, int lines)
{
	int n=FindIndex(index);			//没有语言了
	if( n == -1 )
	{
		ShowMessage("Can't find [%s] in file <%s>",index, FileName);
		return NULL;
	}

	//跳到指定行数
	n=GotoNextLine(n);
	for(int i=0; i<lines; i++)
	{
		if( n<DataLen )
			n=GotoNextLine(n);
	}

	return ReadDataName(n);			//读出名字返回
}

//以普通方式写一字符串数据。索引,名字,内容
bool CIniSet::WriteText(char *index, char *name, char *string)
{
	int n=FindIndex(index);			//我真的不想说了
	if( n == -1 )	//新建索引
	{
		AddIndex(index);			//加入一个一个索引
		n=FindIndex(index);			//找到其位置
		AddData(n, name, string);	//在当前位置n加一个数据
		return true;
	}

	//存在索引
	int m=FindData(n, name);
	if( m==-1 )		//新建数据
	{
		AddData(n, name, string);	//在当前位置n加一个数据
		return true;
	}

	//存在数据
	ModityData(n, name, string);	//修改一个数据

	return true;
}

//以普通方式写一整数
bool CIniSet::WriteInt(char *index, char *name, int num)
{
	char string[32];
	sprintf(string, "%d", num);

	int n=FindIndex(index);			//……
	if( n == -1 )	//新建索引
	{
		AddIndex(index);			//看上面的注释
		n=FindIndex(index);
		AddData(n, name, string);	//在当前位置n加一个数据
		return true;
	}

	//存在索引
	int m=FindData(n, name);
	if( m==-1 )		//新建数据
	{
		AddData(n, name, string);	//在当前位置n加一个数据
		return true;
	}

	//存在数据
	ModityData(n, name, string);	//修改一个数据

	return true;
}

/////////////////////////////////////////////////////////////////////
//
/////////////////////////////////////////////////////////////////////

//加入一个索引
bool CIniSet::AddIndex(char *index)
{
	char str[256];
	memset(str, 0, 256);
	int n=FindIndex(index);			//找找看有没有一样的

	if( n == -1 )	//新建索引
	{
		sprintf(str,"\r\n[%s]\r\n",index);		//注意格式,索引要分开
		Data=(char *)realloc(Data, DataLen+strlen(str));	//重新分配内存
		sprintf(&Data[DataLen], "%s", str);		//接在后面
		DataLen+=strlen(str);					//更新长度

		InitIndex();							//重新建立索引表
		return true;
	}
	
	return false;	//已经存在
}

//在当前位置加入一个数据
bool CIniSet::AddData(int p, char *name, char *string)
{
	char *str;
	int len=strlen(string);
	str=new char[len+256];						//留出空间
	memset(str, 0, len+256);
	sprintf(str,"%s=%s\r\n",name,string);		//化成tiamo=1的格式
	len=strlen(str);							//重新算长度

	p=GotoNextLine(p);	//提行
	Data=(char *)realloc(Data, DataLen+len);	//重新分配内存

	char *temp=new char[DataLen-p];				//后面的内容放到temp里面
	memcpy(temp, &Data[p], DataLen-p);
	memcpy(&Data[p+len], temp, DataLen-p);		//把后面的搬到末尾
	memcpy(&Data[p], str, len);					//插入新加的内容
	DataLen+=len;								//更新数据长度

	_DELETE( temp );
	_DELETE( str );
	return true;
}

//在当前位置修改一个数据的值
bool CIniSet::ModityData(int p, char *name, char *string)
{
	int n=FindData(p, name);					//找到数据。注意:返回的n是内容的位置

	char *t=ReadText(n);						//读出数据的内容
	p=n+strlen(t);								//移动到数据的末尾的下一个位置
	_FREE(t);

	int newlen=strlen(string);					//新的数据长度
	int oldlen=p-n;								//t的长度,也就是原来的数据长度

	Data=(char *)realloc(Data, DataLen+newlen-oldlen);	//重新分配内存

	char *temp=new char[DataLen-p];						//相同的方法
	memcpy(temp, &Data[p], DataLen-p);
	memcpy(&Data[n+newlen], temp, DataLen-p);			//把后面的搬到末尾
	memcpy(&Data[n], string, newlen);
	DataLen+=newlen-oldlen;								//更新数据长度

	_DELETE( temp );
	return true;
}

//返回文件内容
char *CIniSet::GetData()
{
	return Data;
}

//获得文件的行数
int CIniSet::GetLines(int cur)
{
	int n=1;
	for(int i=0; i<cur; i++)
	{
		if( Data[i]=='\n' )					//找到\n,就是新的一行
			n++;
	}
	return n;
}

//返回连续的行数,就是标题(索引)这个段共有多少行,一般是用来循环记数的
int CIniSet::GetContinueDataNum(char *index)
{
	int num=0;
	int n=FindIndex(index);				//恩…………
	n=GotoNextLine(n);					//跳过标题(索引)
	while(1)
	{									//要是一行的开头就是下面的字符的话,就结束
		if( Data[n] == '\r' || Data[n] == -3 || Data[n] == EOF 
			|| Data[n] == ' ' || Data[n] == '/' || Data[n] == '\t' || Data[n] == '\n' )
		{
			return num;
		}
		else
		{
			num++;						//加一
			n=GotoNextLine(n);			//到下一行的开头
			if( n >= DataLen )	
				return num;			//文件结束
		}
	}
}