/**
 * @file:    $RCSfile: initools.h,v $
 * @brief:   $parsing ini files
 *
 * @version: $Revision: 1.1 $
 * @date:    $Date: 2018/11/24 06:54:49 $
 * @author:  $Author: lizhongming $
 * @state:   $State: Exp $
 *
 * @latest:  $Id: initools.h,v 1.1 2018/11/24 06:54:49 lizhongming Exp $
 */

/****	
Examples 1:

inifile_t	   *Hp;	
char		   values[15];
ini_section_t	*sec;

ini_Parser_Create("c:\\1.ini",&Hp);
printf("---MAPI=%d--\n",ini_GetKeyIntValueWithDefault(Hp,"Mail","MAPI",999));
printf("---CMCDLLNAME32=%d--\n",ini_GetKeyIntValueWithDefault(Hp,"Mail","CMCDLLNAME32",999));
ini_GetKeyValue(Hp,"Mail","CMCDLLNAME32",values,15);
printf("---CMCDLLNAME32=%s--\n",values);
sec=ini_GetSection(Hp,"Mail");
printf("---MAPIX=%d--\n",ini_GetKeyIntValueByHandleWithDefault(sec,"MAPIX",999));
sec=ini_GetSection(Hp,"MCI Extensions.BAK");
ini_GetKeyValueByHandle(sec,"wm",values,15);
printf("---MAPIX=%s--\n",values);
ini_Parser_Destory(Hp);

Example 2: 在内存中生成INI文件
int ini_test()
{
	inifile_t		*Parser;
	apr_status_t	rv;
	char			contents[10240];
	strcpy(contents,"");

	rv = ini_Parser_Create_By_Memory_file(contents,sizeof(contents),&Parser);
	if (rv) return rv;

	rv  = ini_AppendSectionM(Parser,"SectionA");
	if (rv) return rv;

	rv  = ini_AppendKeyM(Parser,"SectionA","Item1","1");
	if (rv) return rv;
	rv  = ini_AppendKeyM(Parser,"SectionA","Item2","2");
	if (rv) return rv;
	rv  = ini_AppendKeyM(Parser,"SectionA","Item3","3");
	if (rv) return rv;

	rv = ini_Dump(Parser);
	printf ("%s",contents);
	return rv;

}

****/
#ifndef INITOOLS_H_HBJYUGGVYUGYGU
#define INITOOLS_H_HBJYUGGVYUGYGU

#include "apr.h"
#include "apr_errno.h"
#include "apr_pools.h"

#define INI_MAX_CHARS_A_LINE (1024)
typedef struct inifile_t		 inifile_t;
typedef struct ini_section_t	 ini_section_t;
typedef struct ini_item_t		 ini_item_t;
typedef enum token_name	token_name;
typedef enum parse_token parse_token;
typedef	enum char_event char_event;

#define INI_COMMON_FILE		(0)		/**< INI文件来自于文件  */
#define INI_MEMORY_FILE		(1)     /**< INI文件来自于内存  */


//更新指定文件
typedef int(* CALLBACK_CONTENT_FILTER)   (const char* content,int line_no,void *user_data);
typedef int(* CALLBACK_CONTENT_OPERATION)(const char* org_content,char *changed_content,size_t buffer_len,void * user_data);

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */


//建立一个空白INI文件
APR_DECLARE(apr_status_t) ini_Create_BlankFile (const char *path,const char *filename);

/**
 * @brief INI文件解析器建立
 * @param filename 要解析的文件名
 * @param parse_handle传出的解析器句柄
 * @return 成功返回APR_SUCCESS
 */
APR_DECLARE(apr_status_t) ini_Parser_Create (const char *filename,inifile_t **parse_handle);

/**
 * @brief INI内存文件解析器建立
 * @param str_buffer 要解析的内存
 * @param parse_handle传出的解析器句柄
 * @return 成功返回APR_SUCCESS
 */
APR_DECLARE(apr_status_t) ini_Parser_Create_By_Memory_file (char * str_buffer ,size_t len , inifile_t **parse_handle);


/**
 * @brief INI文件解析器销毁
 */
APR_DECLARE(void) ini_Parser_Destory (inifile_t *parse_handle);


/**
 * @brief 读取一个ini 文件中的所有段
 * @param ini_parse_handle 解析器句柄
 * @param szBuffer 返回格式 'AAA\0BBB\0...\0\0'
 * @return 成功返回APR_SUCCESSszBuffer is not large enough to hold whole sections return APR_ENOMEM .
 * @note szBuffer should be large enough
 */
APR_DECLARE(apr_status_t) ini_GetSectionNames(inifile_t *ini_parse_handle ,char* szBuffer, int nlen);


//
//szBuffer 大小  'AAA\0BBB\0...\0\0'
//return APR_ENOMEM .

/**
 * @brief 读取一个ini 文件中的指定节中所有字段,szBuffer should be large enough
 * @param ini_parse_handle 解析器句柄
 * @param szBuffer 返回格式 'AAA\0BBB\0...\0\0'
 * @return 成功返回APR_SUCCESS, return APR_ENOMEM if szBuffer is not large enough to hold whole item lists 
 * @note szBuffer should be large enough
 */
APR_DECLARE(apr_status_t) ini_GetItemNames(ini_section_t *sec,char* szBuffer, int nlen);


/**
 * @brief 读取指定段句柄
 * @param ini_parse_handle 解析器句柄
 * @param Section 指定段名
 * @return 返回定段句柄,找不到指定段返回NULL
 */
APR_DECLARE(ini_section_t*) ini_GetSection (const inifile_t *ini_parse_handle , const char*  Section);


/**
 * @brief 读取指定section中的 键的整形值,效率较高建议采用
 * @param sec 段句柄
 * @param Key 指定变量名
 * @param nDefault 当解析错误或值为空时返回的缺省值
 * @return 返回变量的整形值
 */
APR_DECLARE(int) ini_GetKeyIntValueByHandleWithDefault(ini_section_t *sec ,const char* Key,int nDefault);


/**
 * @brief 读取指定section中的 键的整形值,效率较高建议采用
 * @param sec 段句柄
 * @param Key 指定变量名
 * @param Value 用于传出整形值
 * @return 成功返回APR_SUCCESS
 */
APR_DECLARE(apr_status_t) ini_GetKeyIntValueByHandle(ini_section_t *sec ,const char* Key, int *Value);



/**
 * @brief 读取指定section中的 键的字符串值,效率较高建议采用
 * @param sec 段句柄
 * @param Key 指定变量名
 * @param szValue 用于传出我字符串缓冲区
 * @param nlen 用于传出我字符串缓冲区大小
 * @return 返回变量的字符串值
 */
APR_DECLARE(apr_status_t) ini_GetKeyValueByHandle(ini_section_t *sec ,const char* Key,
												  char* szValue, int nlen);


/**
 * @brief 读取指定section中的 键的字符串值,效率较高建议采用
 * @param ini_parse_handle 解析器句柄
 * @param Section 指定段名
 * @param Key 指定变量名
 * @param nDefault 当解析错误或值为空时返回的缺省值
 * @return 返回变量的整形值
 */
APR_DECLARE(int) ini_GetKeyIntValueWithDefault(inifile_t *ini_parse_handle ,const char* Section,
											   const char* Key,int nDefault);


/**
 * @brief 读取指定section中的 键的整形值
 * @param ini_parse_handle 解析器句柄
 * @param Section 指定段名
 * @param Key 指定变量名
 * @param szValue 用于传出我字符串缓冲区
 * @param nlen 用于传出我字符串缓冲区大小
 * @return 成功返回APR_SUCCESS
 */
APR_DECLARE(apr_status_t) ini_GetKeyIntValue(inifile_t *ini_parse_handle ,const char* Section,
											 const char* Key,int *value);
/**
 * @brief 读取指定section中的 键的字符串值
 * @param ini_parse_handle 解析器句柄
 * @param Section 指定段名
 * @param Key 指定变量名
 * @param szValue 用于传出我字符串缓冲区
 * @param nlen 用于传出我字符串缓冲区大小
 * @return 成功返回APR_SUCCESS
 */
APR_DECLARE(apr_status_t) ini_GetKeyValue(inifile_t *ini_parse_handle ,
										  const char* Section,const char* Key,
										  char* szValue, int nlen);

/**
 * @brief 设定指定section中的某一键的字符串值
 * @param ini_parse_handle 解析器句柄
 * @param Section 指定段名
 * @param Key 指定变量名
 * @param szValue 新值的字符串缓冲区
 * @return 成功返回APR_SUCCESS
 * @mark   如需要求对INI文件进行写操作，那么在写完之前应用程序不应释放句柄，本函数立刻更改内存区中的值，然后再重写相应文件。
 */
APR_DECLARE(apr_status_t) ini_SetKeyValue(inifile_t *ini_parse_handle ,const char* Section,const char* Key,
										  char* szValue);
/**
 * @brief 设定指定section中的某一键的整数值
 * @param ini_parse_handle 解析器句柄
 * @param Section 指定段名
 * @param Key 指定变量名
 * @param szValue 新值的字符串缓冲区
 * @return 成功返回APR_SUCCESS
 * @mark   如需要求对INI文件进行写操作，那么在写完之前应用程序不应释放句柄，本函数立刻更改内存区中的值，然后再重写相应文件。
 */
APR_DECLARE(apr_status_t) ini_SetKeyIntValue(inifile_t *ini_parse_handle ,const char* Section_Name,const char* Key,int value);

/**
 * @brief 指定文件增加一个 Section域(仅仅在内存生成,用ini_Dump生成至文件)
 * @param ini_parse_handle 解析器句柄
 * @return 成功返回APR_SUCCESS
 */
APR_DECLARE(apr_status_t) ini_AppendSectionM(inifile_t *ini_parse_handle,const char* Section_Name);

/**
 * @brief 删除一个Section域
 * @param ini_parse_handle 解析器句柄
 * @param Section 指定段名
 * @return 当原INI文件指定的域不存在 或 成功删除指定的域 返回APR_SUCCESS
 * @mark   不允许删除全局域（没有以[Section Name]指明的那些域）
 */
APR_DECLARE(apr_status_t) ini_DeleteSection(inifile_t *ini_parse_handle,const char* Section);

/**
 * @brief 在一个已经存在的Section域下添加KEY(仅仅更新内存操作)
 * @param ini_parse_handle 解析器句柄
 * @param Section 指定段名(为""表示 根SECTION,也就是那些不包含在[XX]下的部分,不推荐)
 * @return 当原INI文件指定的域不存在 或 成功删除指定的域 返回APR_SUCCESS
 * @mark   不允许删除全局域（没有以[Section Name]指明的那些域）
 */
APR_DECLARE(apr_status_t) ini_AppendKeyM (inifile_t *ini_parse_handle ,const char* Section,const char* Key,const char * value);

/**
 * @brief 删除一个Section域(仅仅更新内存操作)
 * @param ini_parse_handle 解析器句柄
 * @param Section 指定段名
 * @return 当原INI文件指定的域不存在 或 成功删除指定的域 返回APR_SUCCESS
 * @mark   不允许删除全局域（没有以[Section Name]指明的那些域）
 */
APR_DECLARE(apr_status_t) ini_DeleteSectionM(inifile_t *ini_parse_handle,const char* Section_Name);

/**
 * @brief 在一个已经存在的Section域下添加KEY(仅仅更新内存操作)
 * @param ini_parse_handle 解析器句柄
 * @param sec 段句柄
 * @return 当原INI文件指定的域不存在 或 成功删除指定的域 返回APR_SUCCESS
 * @mark   不允许删除全局域（没有以[Section Name]指明的那些域）
 */
APR_DECLARE(apr_status_t) ini_AppendKeyMByHandle (inifile_t *ini_parse_handle ,ini_section_t *sec,const char* Key,const char * value);

/**
 * @brief 在一个已经存在的Section域下更新键值(仅仅更新内存操作)
 * @param ini_parse_handle 解析器句柄
 * @param sec 段句柄
 * @return 当原INI文件指定的域不存在 或 成功删除指定的域 返回APR_SUCCESS
 * @mark   不允许删除全局域（没有以[Section Name]指明的那些域）
 */
APR_DECLARE(apr_status_t) ini_UpdateKeyMByHandle (inifile_t *ini_parse_handle ,ini_section_t *sec,const char* Key,const char * value);

/**
 * @brief 将当前的INI内存镜像至文件
*/
APR_DECLARE(apr_status_t) ini_Dump(inifile_t *ini_parse_handle);
#ifdef __cplusplus
}
#endif

#endif /* GENERAL_DEQUE_H */
