#include "Rwconfig.h"
#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#define MAX_LINE_LEN 1024 /* 每行最大长度 */
typedef enum _ELineType_ {
LINE_IDLE, /* 未处理行 */
LINE_ERROR, /* 错误行 */
LINE_EMPTY, /* 空白行或注释行 */
LINE_SECTION, /* 节定义行 */
LINE_VALUE /* 值定义行 */
} ELineType ;
inline int get_min(int x, int y)
{
return (x <= y ? x : y);
}
inline int get_max(int x, int y)
{
return (x <= y ? y : x);
}
inline bool is_newline(char ch)
{
return (ch == '\r' || ch == '\n');
}
Rwini::Rwini()
{
m_bufflen = 0;
m_buff = NULL;
memset(m_filename, 0, 256);
}
Rwini::~Rwini()
{
if (m_buff) {
delete []m_buff;
}
}
/*
* 去除串首尾空格,原串被改写:
* 会将处理后的有效字符串覆盖到
* 原先的字符串中
*/
char * Rwini::strtrim(char *str)
{
assert(str);
size_t len = strlen(str);
char *ptr_left, *ptr_right;
if (len == 0) {
return str;
}
ptr_left = str;
ptr_right = str + len - 1;
while (*ptr_left && isspace(*ptr_left)) { /* 去除头部空格等,ptr_left指向第一个有效字段 */
ptr_left++;
}
while (ptr_right > ptr_left && isspace(*ptr_right)) { /* 去除尾部空格等,p2指向最后的有效字段 */
ptr_right--;
}
*(ptr_right + 1) = '\0';
if (ptr_left != str) { /* 移动有效字段到开头,ptr_right没有指向最后,要加上最后的'\0' */
memmove(str, ptr_left, ptr_right - ptr_left + 2);
}
return str;
}
/*
* 不区分大小写比较字符串
*/
int Rwini::strcmp_l(const char *s1, const char *s2)
{
assert(s1 && s2);
char ch1 = 0, ch2 = 0;
do {
ch1 = tolower(*s1++);
ch2 = tolower(*s2++);
} while (ch1 && (ch1 == ch2));
return (ch1 - ch2);
}
/*
* 取一行
* 输入:数据区(指针及长度)
* 输出:行类型、有效内容串(去首尾空格)、注释首、下一行首(行尾与下一行首间为换行符)
* 首先断行断注释,支持如下换行符:\r、\n、\r\n、\n\r
*/
int Rwini::get_line_info(char *buf, int buf_len, char *content, char *¬e, char *&next_line)
{
char *ptr = buf;
int i = 0, cont_len;
char single_quot = 0, double_quot = 0; /* 引号记录标志 */
int space_num = 0, CRLF_num = 0, cnt_LF = 0; /* 连续空格、换行符数量 */
char *cont_begin = NULL, *line_end = NULL; /* 记录有效数据开始,记录一行有效的末尾位置 */
note = NULL; /* 记录有效数据结束(注释开始) */
for (; i < buf_len; ++i, ++ptr) {
switch (*ptr) {
case '\0' :
++ptr;
break;
case '\r':
case '\n':
CRLF_num++;
break;
case '\'':
if (!double_quot) { /* 之前是双引号,单引号暂不再处理 */
single_quot = 1 - single_quot;
}
break;
case '\"':
if (!single_quot) { /* 如果之前是单引号,双引号不进行处理 */
double_quot = 1 - double_quot;
}
break;
case ';':
case '#':
if (!single_quot && !double_quot && !note) {
note = ptr - space_num; // 注释以有效内容结束开始
}
break;
default:
if (isspace(*ptr)) { /* 空白字符,记录数量 */
space_num++;
} else {
space_num = 0;
if (!note && !cont_begin) {
cont_begin = ptr;
}
}
break;
}
if (CRLF_num > 1) { /* CR或LF各1个之后任意字符,行结束 */
ptr++;
break;
}
if (CRLF_num && !is_newline(*ptr)) { /* CR或LF之后出现其它字符,行结束 */
break;
}
}
next_line = ptr;
if (cont_begin == NULL) {
return LINE_EMPTY;
}
line_end = ptr - CRLF_num; /* 去除换行符的行尾 */
if (note == NULL) { /* 没有注释 */
note = line_end - space_num;
}
if ((cont_len = note - cont_begin) >= MAX_LINE_LEN) {
return LINE_ERROR;
}
memcpy(content, cont_begin, cont_len); /* 内容头尾已无空格等(仅有效数据) */
content[cont_len] = 0;
// printf("line content: %s\n", content);
if (content[0] == '[' && content[cont_len - 1] == ']') { /* section头部分 */
return LINE_SECTION;
} else if (strchr(content, '=')) { /* section的行值内容部分 */
return LINE_VALUE;
}
return LINE_ERROR;
}
/*
* 取一节section
* 输入:节名称
* 输出:成功与否、节名称首、节名称尾、节内容首、节内容尾(含换行)、
* 下一节首(节尾与下一节首间为空行或注释行)
*/
int Rwini::find_section(const char *section, char *&cont_begin, char *&cont_end)
{
if (!m_buff || !section) {
return false;
}
int type = 0; /* 行内容的返回类型 */
int usedlen = 0; /* 记录已读过的长度 */
char found = 0; /* 是否找到section */
char content[MAX_LINE_LEN] = {0};
char *ptr = NULL, *nextline = NULL, *note = NULL; /* 记录内容 */
while (usedlen < m_bufflen) {
ptr = m_buff + usedlen;
type = get_line_info(ptr, m_bufflen - usedlen, content, note, nextline);
usedlen += nextline - ptr;
if (type == LINE_SECTION) {
if (found) { // 找到下一个section起始,为目标section结束
cont_end = ptr;
return true;
}
content[strlen(content) - 1] = 0; /* 去尾部] */
strtrim(content + 1); /* 去[]之中的内容的首尾空格 */
if (!strcmp_l(content + 1, section)) { /* 目标section */
// printf("*************find section: %s\n", section);
found = 1;
cont_begin = nextline; /* 指定section的下行开始 */
}
}
}
if (!found) {
return false;
}
cont_end = m_buff + m_bufflen - 1;
return true;
}
/* 从一行取键、值
* 输入:内容串(将被改写)
* 输出:键串、值串
*/
void Rwini::get_key_value(char *content, char *&key, char *&value)
{
char *ptr = strchr(content, '=');
*ptr = 0; /* 将key = value 从=位置分成两个字符串:content和p+1*/
strtrim(content); /* 去除空格 */
strtrim(ptr + 1);
key = content;
value = ptr + 1;
}
/*
* 未找到section,取最早出现的key的值
*/
bool Rwini::get_first_key_val(const char *key, char *value, int maxlen, const char *defval)
{
int type = 0, len = 0; /* 返回行内容的类型 */
char content[MAX_LINE_LEN] = {0};
char *key_pos = NULL, *val_pos = NULL; /* buff中此行内容中的key与key对应的内容 */
char *ptr = NULL, *nextline = NULL, *note = NULL;
while (len < m_bufflen) {
ptr = m_buff + len;
type = get_line_info(ptr, m_bufflen - len, content, note, nextline);
len += (int)(nextline - ptr);
if (type == LINE_VALUE) {
get_key_value(content, key_pos, val_pos);
if (strcmp_l(key_pos, key) == 0) {
len = get_min(strlen(val_pos), maxlen - 1);
if (len == 0) { /* 空值视为无效 */
break;
}
strncpy(value, val_pos, len);
value[len] = 0;
return 0;
}
}
}
if (defval) { /* 未发现键值取缺省 */
len = get_min(strlen(defval), maxlen - 1);
strncpy(value, defval, len);
value[0] = 0;
return true;
}
return false;
}
/*
* 查找到目标section节,取section内容中目标key值
*/
bool Rwini::get_value(const char
C++读写ini配置文件
5星 · 超过95%的资源 需积分: 29 102 浏览量
2019-01-22
17:58:41
上传
评论 2
收藏 6KB RAR 举报
Shunhwa
- 粉丝: 1
- 资源: 6
最新资源
- main.c
- Unity 创建快捷方式自动启动
- 一分钟一条原创视频,蹭热点撸收益,条条爆款,狂撸各大平台,轻松日入1000+-教程网盘链接提取码下载 .txt
- 51单片机实现万年历,包括闹钟的设置与秒表功能(汇编)
- STM32单片机FPGA毕设电路原理论文报告铁合金电炉单片机电力监控系统的研究
- STM32单片机FPGA毕设电路原理论文报告贴片元件封装机的智能控制系统设计
- STM32单片机FPGA毕设电路原理论文报告体育高考投篮自动测试系统的设计与实现
- STM32单片机FPGA毕设电路原理论文报告提高放疗精度的单片机控制方法
- C++ matplot学习及demo实操
- STM32单片机FPGA毕设电路原理论文报告提高单晶炉加热电源控制电路精度的研究
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈