很实用的C++ ini解析类
来源:互联网 发布:linux尝试其他镜像 编辑:程序博客网 时间:2024/06/17 23:01
头文件:
#pragma once#include <map>#include <string>class INIReader{public:INIReader(std::string filename);INIReader(const char* buf);intParseError();std::stringGet(std::string section, std::string name, std::string default_value);longGetInteger(std::string section, std::string name, long default_value);doubleGetReal(std::string section, std::string name, double default_value);boolGetBoolean(std::string section, std::string name, bool default_value);private:static std::string MakeKey(std::string section, std::string name);static int ValueHandler(void* user, const char* section, const char* name, const char* value);private:int_error;std::map<std::string, std::string> _values;};
cpp文件:
// Read an INI file into easy-to-access name/value pairs.#include "StdAfx.h"#include "INIReader.h"#include <algorithm>#include <cctype>#include <cstdlib>#include "ini.h"INIReader::INIReader(std::string filename){_error = ini_parse(filename.c_str(), ValueHandler, this);}INIReader::INIReader(const char* buf){_error = ini_parse_mem(buf, ValueHandler, this);}int INIReader::ParseError(){return _error;}std::string INIReader::Get(std::string section, std::string name, std::string default_value){std::string key = MakeKey(section, name);return _values.count(key) ? _values[key] : default_value;}long INIReader::GetInteger(std::string section, std::string name, long default_value){std::string valstr = Get(section, name, "");const char* value = valstr.c_str();char* end;// This parses "1234" (decimal) and also "0x4D2" (hex)long n = strtol(value, &end, 0);return end > value ? n : default_value;}double INIReader::GetReal(std::string section, std::string name, double default_value){std::string valstr = Get(section, name, "");const char* value = valstr.c_str();char* end;double n = strtod(value, &end);return end > value ? n : default_value;}bool INIReader::GetBoolean(std::string section, std::string name, bool default_value){std::string valstr = Get(section, name, "");// Convert to lower case to make string comparisons case-insensitivestd::transform(valstr.begin(), valstr.end(), valstr.begin(), ::tolower);if (valstr == "true" || valstr == "yes" || valstr == "on" || valstr == "1")return true;else if (valstr == "false" || valstr == "no" || valstr == "off" || valstr == "0")return false;elsereturn default_value;}std::string INIReader::MakeKey(std::string section, std::string name){std::string key = section + "." + name;// Convert to lower case to make section/name lookups case-insensitivestd::transform(key.begin(), key.end(), key.begin(), ::tolower);return key;}int INIReader::ValueHandler(void* user, const char* section, const char* name, const char* value){INIReader* reader = (INIReader*)user;std::string key = MakeKey(section, name);if (reader->_values[key].size() > 0)reader->_values[key] += "\n";reader->_values[key] += value;return 1;}
依赖于google上的开源项目:inih(http://code.google.com/p/inih/)
头文件:
/* inih -- simple .INI file parserinih is released under the New BSD license (see LICENSE.txt). Go to the projecthome page for more info:http://code.google.com/p/inih/*/#ifndef __INI_H__#define __INI_H__/* Make this header file easier to include in C++ code */#ifdef __cplusplusextern "C" {#endif#include <stdio.h>/* Parse given INI-style file. May have [section]s, name=value pairs (whitespace stripped), and comments starting with ';' (semicolon). Section is "" if name=value pair parsed before any section heading. name:value pairs are also supported as a concession to Python's ConfigParser. For each name=value pair parsed, call handler function with given user pointer as well as section, name, and value (data only valid for duration of handler call). Handler should return nonzero on success, zero on error. Returns 0 on success, line number of first error on parse error (doesn't stop on first error), -1 on file open error, or -2 on memory allocation error (only when INI_USE_STACK is zero).*/int ini_parse(const char* filename, int (*handler)(void* user, const char* section, const char* name, const char* value), void* user);/* Same as ini_parse(), but takes a FILE* instead of filename. This doesn't close the file when it's finished -- the caller must do that. */int ini_parse_file(FILE* file, int (*handler)(void* user, const char* section, const char* name, const char* value), void* user);int ini_parse_mem(const char* buf, int (*handler)(void* user, const char* section, const char* name, const char* value), void* user);/* Nonzero to allow multi-line value parsing, in the style of Python's ConfigParser. If allowed, ini_parse() will call the handler with the same name for each subsequent line parsed. */#ifndef INI_ALLOW_MULTILINE#define INI_ALLOW_MULTILINE 1#endif/* Nonzero to allow a UTF-8 BOM sequence (0xEF 0xBB 0xBF) at the start of the file. See http://code.google.com/p/inih/issues/detail?id=21 */#ifndef INI_ALLOW_BOM#define INI_ALLOW_BOM 1#endif/* Nonzero to use stack, zero to use heap (malloc/free). */#ifndef INI_USE_STACK#define INI_USE_STACK 1#endif/* Maximum line length for any line in INI file. */#ifndef INI_MAX_LINE#define INI_MAX_LINE 20000#endif#ifdef __cplusplus}#endif#endif /* __INI_H__ */
.c文件:
#define _CRT_SECURE_NO_WARNINGS#pragma warning (disable: 4127)#include <stdio.h>#include <ctype.h>#include <string.h>#include "ini.h"#if !INI_USE_STACK#include <stdlib.h>#endif#define MAX_SECTION 50#define MAX_NAME 50/* Strip whitespace chars off end of given string, in place. Return s. */static char* rstrip(char* s){ char* p = s + strlen(s); while (p > s && isspace((unsigned char)(*--p))) *p = '\0'; return s;}/* Return pointer to first non-whitespace char in given string. */static char* lskip(const char* s){ while (*s && isspace((unsigned char)(*s))) s++; return (char*)s;}/* Return pointer to first char c or ';' comment in given string, or pointer to null at end of string if neither found. ';' must be prefixed by a whitespace character to register as a comment. */static char* find_char_or_comment(const char* s, char c){ int was_whitespace = 0; while (*s && *s != c && !(was_whitespace && *s == ';')) { was_whitespace = isspace((unsigned char)(*s)); s++; } return (char*)s;}/* Version of strncpy that ensures dest (size bytes) is null-terminated. */static char* strncpy0(char* dest, const char* src, size_t size){ strncpy(dest, src, size); dest[size - 1] = '\0'; return dest;}/* See documentation in header file. */int ini_parse_file(FILE* file, int (*handler)(void*, const char*, const char*, const char*), void* user){ /* Uses a fair bit of stack (use heap instead if you need to) */#if INI_USE_STACK char line[INI_MAX_LINE];#else char* line;#endif char section[MAX_SECTION] = ""; char prev_name[MAX_NAME] = ""; char* start; char* end; char* name; char* value; int lineno = 0; int error = 0;#if !INI_USE_STACK line = (char*)malloc(INI_MAX_LINE); if (!line) { return -2; }#endif /* Scan through file line by line */ while (fgets(line, INI_MAX_LINE, file) != NULL) { lineno++; start = line;#if INI_ALLOW_BOM if (lineno == 1 && (unsigned char)start[0] == 0xEF && (unsigned char)start[1] == 0xBB && (unsigned char)start[2] == 0xBF) { start += 3; }#endif start = lskip(rstrip(start)); if (*start == ';' || *start == '#') { /* Per Python ConfigParser, allow '#' comments at start of line */ }#if INI_ALLOW_MULTILINE else if (*prev_name && *start && start > line) { /* Non-black line with leading whitespace, treat as continuation of previous name's value (as per Python ConfigParser). */ if (!handler(user, section, prev_name, start) && !error) error = lineno; }#endif else if (*start == '[') { /* A "[section]" line */ end = find_char_or_comment(start + 1, ']'); if (*end == ']') { *end = '\0'; strncpy0(section, start + 1, sizeof(section)); *prev_name = '\0'; } else if (!error) { /* No ']' found on section line */ error = lineno; } } else if (*start && *start != ';') { /* Not a comment, must be a name[=:]value pair */ end = find_char_or_comment(start, '='); if (*end != '=') { end = find_char_or_comment(start, ':'); } if (*end == '=' || *end == ':') { *end = '\0'; name = rstrip(start); value = lskip(end + 1); end = find_char_or_comment(value, '\0'); if (*end == ';') *end = '\0'; rstrip(value); /* Valid name[=:]value pair found, call handler */ strncpy0(prev_name, name, sizeof(prev_name)); if (!handler(user, section, name, value) && !error) error = lineno; } else if (!error) { /* No '=' or ':' found on name[=:]value line */ error = lineno; } } }#if !INI_USE_STACK free(line);#endif return error;}int ini_parse_mem(const char* buf, int (*handler)(void* user, const char* section, const char* name, const char* value), void* user){char* bufptr = (char*)buf; /* Uses a fair bit of stack (use heap instead if you need to) */#if INI_USE_STACK char line[INI_MAX_LINE];#else char* line;#endif char section[MAX_SECTION] = ""; char prev_name[MAX_NAME] = ""; char* start; char* end; char* name; char* value; int lineno = 0; int error = 0;#if !INI_USE_STACK line = (char*)malloc(INI_MAX_LINE); if (!line) { return -2; }#endifwhile (1){int ncount = 0;while (*bufptr != '\0'){if (*bufptr == '\r' || *bufptr == '\n')break;line[ncount] = *bufptr ++;ncount ++;}while (*bufptr == '\r' || *bufptr == '\n') bufptr ++;line[ncount] = 0;if (ncount == 0)break; /* Scan through file line by line */ //while (fgets(line, INI_MAX_LINE, file) != NULL) { lineno++; start = line;#if INI_ALLOW_BOM if (lineno == 1 && (unsigned char)start[0] == 0xEF && (unsigned char)start[1] == 0xBB && (unsigned char)start[2] == 0xBF) { start += 3; }#endif start = lskip(rstrip(start)); if (*start == ';' || *start == '#') { /* Per Python ConfigParser, allow '#' comments at start of line */ }#if INI_ALLOW_MULTILINE else if (*prev_name && *start && start > line) { /* Non-black line with leading whitespace, treat as continuation of previous name's value (as per Python ConfigParser). */ if (!handler(user, section, prev_name, start) && !error) error = lineno; }#endif else if (*start == '[') { /* A "[section]" line */ end = find_char_or_comment(start + 1, ']'); if (*end == ']') { *end = '\0'; strncpy0(section, start + 1, sizeof(section)); *prev_name = '\0'; } else if (!error) { /* No ']' found on section line */ error = lineno; } } else if (*start && *start != ';') { /* Not a comment, must be a name[=:]value pair */ end = find_char_or_comment(start, '='); if (*end != '=') { end = find_char_or_comment(start, ':'); } if (*end == '=' || *end == ':') { *end = '\0'; name = rstrip(start); value = lskip(end + 1); end = find_char_or_comment(value, '\0'); if (*end == ';') *end = '\0'; rstrip(value); /* Valid name[=:]value pair found, call handler */ strncpy0(prev_name, name, sizeof(prev_name)); if (!handler(user, section, name, value) && !error) error = lineno; } else if (!error) { /* No '=' or ':' found on name[=:]value line */ error = lineno; } } }#if !INI_USE_STACK free(line);#endif return error;}/* See documentation in header file. */int ini_parse(const char* filename, int (*handler)(void*, const char*, const char*, const char*), void* user){ FILE* file; int error; file = fopen(filename, "r"); if (!file) return -1; error = ini_parse_file(file, handler, user); fclose(file); return error;}
0 0
- 很实用的C++ ini解析类
- 一个简单实用的ini解析算法
- ini解析库 c语言
- C语言解析Ini格式文件
- c/c++ 简单的解析ini配置文件程序
- 一个C语言解析ini文件的测试
- INI文件解析类
- boot.ini的深度解析
- 简单的INI解析器
- C++: Ini操作类
- 使用C语言解析INI文件
- c 语言 解析ini文件为xml
- ini文件解析c库(iniparser)
- 纯C语言INI文件解析
- 纯C语言INI文件解析
- C语言实现ini解析函数 getPrivateProfileString
- 纯C语言INI文件解析
- c印记(七): ini file解析
- MySQL AB复制&mysql-proxy读写分离
- 内核编译图文教程,概述篇
- 小波变换和motion信号处理(二)
- extern详解
- XCode开发遇到的“Could not inspect the application package”解决方案
- 很实用的C++ ini解析类
- [转载]/etc/security/limits.conf解释及应用
- unity3d移动平台减小安装包专题(1):分析打包的日志文件删除无用文件
- 什么是微信公众号开发
- leetcode|81|Search in Rotated Sorted Array II
- 建模中常用的30各MATLAB程序和函数
- Java tips
- 单挑成为过去,你必须要学会打群架
- Eclipse乱码问题