Initial commit
This commit is contained in:
223
entry.c
Normal file
223
entry.c
Normal file
@@ -0,0 +1,223 @@
|
||||
#include <stdio.h>
|
||||
#include "pine-ini.h"
|
||||
|
||||
void test_PineIni_StringTrim() {
|
||||
const char *origin;
|
||||
char buf[100];
|
||||
|
||||
// case 1
|
||||
origin = "123";
|
||||
strcpy(buf, origin);
|
||||
printf("<%s> : <%s>\n", origin, PineIni_StringTrim(buf));
|
||||
|
||||
// case 2
|
||||
origin = "\t 123";
|
||||
strcpy(buf, origin);
|
||||
printf("<%s> : <%s>\n", origin, PineIni_StringTrim(buf));
|
||||
|
||||
// case 3
|
||||
origin = "\t 1z2 3 \t";
|
||||
strcpy(buf, origin);
|
||||
printf("<%s> : <%s>\n", origin, PineIni_StringTrim(buf));
|
||||
|
||||
// case 4
|
||||
origin = "1asd 12edc 3\t";
|
||||
strcpy(buf, origin);
|
||||
printf("<%s> : <%s>\n", origin, PineIni_StringTrim(buf));
|
||||
|
||||
// case 5
|
||||
origin = "\t \t \t \t";
|
||||
strcpy(buf, origin);
|
||||
printf("<%s> : <%s>\n", origin, PineIni_StringTrim(buf));
|
||||
}
|
||||
|
||||
void test_PineIni_StringRemoveQuotes() {
|
||||
const char *origin;
|
||||
char buf[100];
|
||||
|
||||
// case 1
|
||||
origin = " \" ";
|
||||
strcpy(buf, origin);
|
||||
printf("<%s> : <%s>\n", origin, PineIni_StringRemoveQuotes(buf));
|
||||
|
||||
// case 1
|
||||
origin = "\"\" ";
|
||||
strcpy(buf, origin);
|
||||
printf("<%s> : <%s>\n", origin, PineIni_StringRemoveQuotes(buf));
|
||||
|
||||
// case 1
|
||||
origin = " \"123\" ";
|
||||
strcpy(buf, origin);
|
||||
printf("<%s> : <%s>\n", origin, PineIni_StringRemoveQuotes(buf));
|
||||
|
||||
// case 1
|
||||
origin = " \"1367' ";
|
||||
strcpy(buf, origin);
|
||||
printf("<%s> : <%s>\n", origin, PineIni_StringRemoveQuotes(buf));
|
||||
|
||||
// case 1
|
||||
origin = " 'asd' ";
|
||||
strcpy(buf, origin);
|
||||
printf("<%s> : <%s>\n", origin, PineIni_StringRemoveQuotes(buf));
|
||||
}
|
||||
|
||||
void test_Ini(const char * iniText) {
|
||||
PineIniError errorRet;
|
||||
PineIniFile* iniResult;
|
||||
int i, j;
|
||||
|
||||
printf("------------ Input INI text: ------------\n%s\n------------ INI Result ------------\n", iniText);
|
||||
|
||||
iniResult = PineIni_Parse(iniText, &errorRet);
|
||||
|
||||
// Error
|
||||
if (iniResult == NULL) {
|
||||
printf("!!! ERROR !!!\n");
|
||||
printf("errorMessage: %s\n", PINE_INI_ERRMSG[errorRet.errorCode]);
|
||||
printf("errorCode: %d\n", errorRet.errorCode);
|
||||
printf("lineNumber: %d\n", errorRet.lineNumber);
|
||||
printf("line: \"%s\"\n", errorRet.lineContent);
|
||||
return;
|
||||
}
|
||||
|
||||
printf("Total sections = %d\n", iniResult->numSection);
|
||||
|
||||
// Print all sections in iniResult
|
||||
for (i = 0; i < iniResult->numSection; ++i) {
|
||||
|
||||
PineIniSection* section = iniResult->sections[i];
|
||||
|
||||
printf("<%s> %d Parameters\n", section->name, section->numParam);
|
||||
|
||||
// Print all parameters in section
|
||||
for (j = 0; j < section->numParam; ++j) {
|
||||
PineIniParameter* param = section->params[j];
|
||||
printf(" %s: %s\n", param->key, param->value);
|
||||
}
|
||||
}
|
||||
|
||||
PineIni_Destory(iniResult);
|
||||
}
|
||||
|
||||
void test_Ini_Success() {
|
||||
const char * iniText =
|
||||
"hello=1\r\n"
|
||||
"; General setting\r\n"
|
||||
"[General]\r\n"
|
||||
"sLanguage=ENGLISH\r\n"
|
||||
"uGridsToLoad=7\r\n"
|
||||
"uExterior Cell Buffer=64\r\n"
|
||||
"iPreloadSizeLimit=262144000\r\n"
|
||||
"\r\n"
|
||||
"[Display]\r\n"
|
||||
"fShadowLODMaxStartFade=1000.0\r\n"
|
||||
"fSpecularLODMaxStartFade=2000.0\r\n"
|
||||
"fLightLODMaxStartFade=3500.0\r\n"
|
||||
"iShadowMapResolutionPrimary=4096\r\n"
|
||||
"bAllowScreenshot=1\r\n"
|
||||
"fDefaultWorldFOV=80\r\n"
|
||||
"fDefault1stPersonFOV=80.0000\r\n"
|
||||
"\r\n"
|
||||
"[Audio]\r\n"
|
||||
"fMusicDuckingSeconds=6.0\r\n"
|
||||
"fMusicUnDuckingSeconds=8.0\r\n"
|
||||
"fMenuModeFadeOutTime=3.0\r\n"
|
||||
"fMenuModeFadeInTime=1.0\r\n"
|
||||
"\r\n"
|
||||
"; Override previous general setting\r\n"
|
||||
"[General]\r\n"
|
||||
" sLanguage = \"CHINESE\"";
|
||||
|
||||
test_Ini(iniText);
|
||||
}
|
||||
|
||||
void test_Ini_IllegalPattern() {
|
||||
const char * iniText =
|
||||
"hello=1\r\n"
|
||||
"; General setting\r\n"
|
||||
"- [General]\r\n";
|
||||
|
||||
test_Ini(iniText);
|
||||
}
|
||||
|
||||
void test_Ini_EmptyKey() {
|
||||
const char * iniText =
|
||||
"hello=1\r\n"
|
||||
"; General setting\r\n"
|
||||
"=asd\r\n";
|
||||
|
||||
test_Ini(iniText);
|
||||
}
|
||||
|
||||
void test_Ini_SectionExceed() {
|
||||
const char * iniText =
|
||||
"[Section01]\na=1\n[Section02]\na=1\n[Section03]\na=1\n[Section04]\na=1\n[Section05]\na=1\n[Section06]\na=1\n"
|
||||
"[Section07]\na=1\n[Section08]\na=1\n[Section09]\na=1\n[Section10]\na=1\n[Section11]\na=1\n[Section12]\na=1\n"
|
||||
"[Section13]\na=1\n[Section14]\na=1\n[Section15]\na=1\n[Section16]\na=1\n[Section17]\na=1\n[Section18]\na=1\n"
|
||||
"[Section19]\na=1\n[Section20]\na=1\n[Section21]\na=1\n[Section22]\na=1\n[Section23]\na=1\n[Section24]\na=1\n"
|
||||
"[Section25]\na=1\n";
|
||||
|
||||
test_Ini(iniText);
|
||||
}
|
||||
|
||||
void test_Ini_Param_Exceed() {
|
||||
const char* iniText =
|
||||
"b0=0\n"
|
||||
"[variables]\n"
|
||||
"v01=01\nv02=02\nv03=03\nv04=04\nv05=05\nv06=06\n"
|
||||
"v07=07\nv08=08\nv09=09\nv10=10\nv11=11\nv12=12\n"
|
||||
"v13=13\nv14=14\nv15=15\nv16=16\nv17=17\nv18=18\n"
|
||||
"v19=19\nv20=20\nv21=21\nv22=22\nv23=23\nv24=24\n"
|
||||
"v25=25\nv26=26\n";
|
||||
|
||||
test_Ini(iniText);
|
||||
}
|
||||
|
||||
void PutsTitle(const char* title) {
|
||||
int padding = 6;
|
||||
int length = strlen(title) + padding * 2;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < length; ++i) {
|
||||
putchar('-');
|
||||
}
|
||||
putchar('\n');
|
||||
|
||||
for (i = 0; i < padding; ++i) {
|
||||
putchar(' ');
|
||||
}
|
||||
printf("%s\n", title);
|
||||
|
||||
for (i = 0; i < length; ++i) {
|
||||
putchar('-');
|
||||
}
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
int main(int argc, char* argv) {
|
||||
|
||||
PutsTitle("Test: StringTrim");
|
||||
test_PineIni_StringTrim();
|
||||
|
||||
PutsTitle("Test: StringRemoveQuotes");
|
||||
test_PineIni_StringRemoveQuotes();
|
||||
|
||||
PutsTitle("Test: Ini Illegal Pattern");
|
||||
test_Ini_IllegalPattern();
|
||||
|
||||
PutsTitle("Test: Ini Empty Key");
|
||||
test_Ini_EmptyKey();
|
||||
|
||||
PutsTitle("Test: Ini Section Exceed");
|
||||
test_Ini_SectionExceed();
|
||||
|
||||
PutsTitle("Test: Ini Param Exceed");
|
||||
test_Ini_Param_Exceed();
|
||||
|
||||
PutsTitle("Test: Ini Success");
|
||||
test_Ini_Success();
|
||||
|
||||
PutsTitle("Test completed!");
|
||||
|
||||
return 0;
|
||||
}
|
||||
441
pine-ini.c
Normal file
441
pine-ini.c
Normal file
@@ -0,0 +1,441 @@
|
||||
#include <stdlib.h>
|
||||
#include "pine-ini.h"
|
||||
|
||||
#define isWhitespace(c) ((c) == ' ' || c == '\r' || c == '\n' || c == '\t')
|
||||
|
||||
const char * PINE_INI_ERRMSG[] = {
|
||||
"No error",
|
||||
"Illegal pattern",
|
||||
"Empty key",
|
||||
"Sections exceed",
|
||||
"Parameters exceed"
|
||||
};
|
||||
|
||||
//
|
||||
// * Parser
|
||||
//
|
||||
|
||||
#define PARSER_ACTION_CONTINUE 1
|
||||
#define PARSER_ACTION_END 0
|
||||
|
||||
typedef struct tagPineIniParser {
|
||||
const char * textBuffer;
|
||||
const char * currentPointer;
|
||||
int lineNumber;
|
||||
} PineIniParser;
|
||||
|
||||
static PineIniParser* PineIni_Parser_New(const char* textBuffer) {
|
||||
PineIniParser* parser = (PineIniParser *)malloc(sizeof(PineIniParser));
|
||||
|
||||
parser->textBuffer = textBuffer;
|
||||
parser->currentPointer = parser->textBuffer;
|
||||
parser->lineNumber = 0;
|
||||
|
||||
return parser;
|
||||
}
|
||||
|
||||
static void PineIni_Parser_Destory(PineIniParser* parser) {
|
||||
if (parser) {
|
||||
free(parser);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Return
|
||||
// PARSER_ACTION_END -> buffer end
|
||||
// PARSER_ACTION_CONTINUE -> buffer has follow-up content
|
||||
//
|
||||
static int PineIni_Parser_Gets(PineIniParser* parser, char* buf) {
|
||||
char *pBuf = buf;
|
||||
|
||||
parser->lineNumber++;
|
||||
|
||||
while (*parser->currentPointer != '\n' && *parser->currentPointer != '\0') {
|
||||
*(pBuf++) = *(parser->currentPointer++);
|
||||
}
|
||||
|
||||
*pBuf = '\0';
|
||||
|
||||
if (*parser->currentPointer == '\0') {
|
||||
return PARSER_ACTION_END;
|
||||
}
|
||||
else {
|
||||
// Skip LF
|
||||
parser->currentPointer++;
|
||||
return PARSER_ACTION_CONTINUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static PINE_BOOL PineIni_Line_Empty(const char* line, const int length) {
|
||||
if (length <= 0 || PineIni_StringEquals("", line)) {
|
||||
return PINE_TRUE;
|
||||
}
|
||||
return PINE_FALSE;
|
||||
}
|
||||
|
||||
|
||||
static PINE_BOOL PineIni_Line_IsComment(const char* line, const int length) {
|
||||
if (length >= 1 && line[0] == ';') {
|
||||
return PINE_TRUE;
|
||||
}
|
||||
return PINE_FALSE;
|
||||
}
|
||||
|
||||
static PINE_BOOL PineIni_Line_IsSection(const char* line, const int length) {
|
||||
if (length >= 2 && line[0] == '[' && line[length - 1] == ']') {
|
||||
return PINE_TRUE;
|
||||
}
|
||||
return PINE_FALSE;
|
||||
}
|
||||
|
||||
static PINE_BOOL PineIni_Line_IsParameter(const char* line, const int length) {
|
||||
int i;
|
||||
for (i = 0; i < length; ++i) {
|
||||
if (line[i] == '=') {
|
||||
return PINE_TRUE;
|
||||
}
|
||||
}
|
||||
return PINE_FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// * Parse API
|
||||
//
|
||||
|
||||
#define PARSER_RETURN_ERROR(error_code) (void *) 0; \
|
||||
errorRet->lineNumber = parser->lineNumber; \
|
||||
errorRet->errorCode = (error_code); \
|
||||
strcpy(errorRet->lineContent, lineBuffer); \
|
||||
PineIni_Parser_Destory(parser); \
|
||||
PineIni_Destory(iniResult); \
|
||||
return NULL;
|
||||
|
||||
PineIniFile* PineIni_Parse(const char* iniText, PineIniError* errorRet) {
|
||||
char lineBuffer[PINE_INI_LINE_MAX_LEN];
|
||||
int lineLength;
|
||||
int getsRetCode;
|
||||
PineIniParser* parser;
|
||||
PineIniFile* iniResult;
|
||||
PineIniSection* currentSection;
|
||||
|
||||
parser = PineIni_Parser_New(iniText);
|
||||
|
||||
// Create iniResult
|
||||
iniResult = (PineIniFile *)malloc(sizeof(PineIniFile));
|
||||
iniResult->numSection = 0;
|
||||
|
||||
// Create a default section for file
|
||||
// and append to iniResult
|
||||
currentSection = PineIni_Section_New("_default");
|
||||
PineIni_Append(iniResult, currentSection);
|
||||
|
||||
// Clear error info
|
||||
errorRet->lineNumber = 0;
|
||||
errorRet->errorCode = PINE_INI_ERRCODE_NO;
|
||||
strcpy(errorRet->lineContent, "");
|
||||
|
||||
do {
|
||||
// Get line from parser
|
||||
getsRetCode = PineIni_Parser_Gets(parser, lineBuffer);
|
||||
|
||||
// Trim white spaces
|
||||
PineIni_StringTrim(lineBuffer);
|
||||
|
||||
// Check pattern
|
||||
lineLength = strlen(lineBuffer);
|
||||
|
||||
// Pattern : empty
|
||||
if (PineIni_Line_Empty(lineBuffer, lineLength)) {
|
||||
continue;
|
||||
}
|
||||
// Pattern : comment
|
||||
else if (PineIni_Line_IsComment(lineBuffer, lineLength)) {
|
||||
continue;
|
||||
}
|
||||
// Pattern : section
|
||||
else if (PineIni_Line_IsSection(lineBuffer, lineLength)) {
|
||||
char sectionName[PINE_INI_LINE_MAX_LEN];
|
||||
PineIniSection* section;
|
||||
|
||||
PineIni_Substring(sectionName, lineBuffer, 1, lineLength - 2);
|
||||
|
||||
section = PineIni_Find(iniResult, sectionName);
|
||||
|
||||
// Section name not exist in iniResult
|
||||
if (section == NULL) {
|
||||
// Check if exceed
|
||||
if (iniResult->numSection >= PINE_INI_MAX_NUM_SECTIONS) {
|
||||
PARSER_RETURN_ERROR(PINE_INI_ERRCODE_SECTION_EXCEED);
|
||||
}
|
||||
|
||||
// Create a new section and append in iniResult
|
||||
section = PineIni_Section_New(sectionName);
|
||||
PineIni_Append(iniResult, section);
|
||||
}
|
||||
|
||||
currentSection = section;
|
||||
|
||||
continue;
|
||||
}
|
||||
// Pattern : parameter
|
||||
else if (PineIni_Line_IsParameter(lineBuffer, lineLength)) {
|
||||
char key[PINE_INI_LINE_MAX_LEN];
|
||||
char value[PINE_INI_LINE_MAX_LEN];
|
||||
int equalPos;
|
||||
PineIniParameter* param;
|
||||
|
||||
// Get key and value
|
||||
equalPos = PineIni_FindChar(lineBuffer, '=');
|
||||
PineIni_Substring(key, lineBuffer, 0, equalPos - 1);
|
||||
PineIni_Substring(value, lineBuffer, equalPos + 1, lineLength - 1);
|
||||
PineIni_StringTrim(key);
|
||||
PineIni_StringRemoveQuotes(value);
|
||||
|
||||
// Error: empty key
|
||||
if (strlen(key) <= 0) {
|
||||
PARSER_RETURN_ERROR(PINE_INI_ERRCODE_EMPTY_KEY);
|
||||
}
|
||||
|
||||
// Check if key already exist
|
||||
param = PineIni_Section_Find(currentSection, key);
|
||||
|
||||
// Exist, update value
|
||||
if (param) {
|
||||
PineIni_Parameter_Assign(param, value);
|
||||
}
|
||||
// Not exist, append to current section
|
||||
else {
|
||||
// Check if exceed
|
||||
if (currentSection->numParam >= PINE_INI_MAX_NUM_PARAMETERS) {
|
||||
PARSER_RETURN_ERROR(PINE_INI_ERRCODE_PARAMS_EXCEED);
|
||||
}
|
||||
PineIni_Section_Append(currentSection, key, value);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
// Illegal Pattern!
|
||||
else {
|
||||
PARSER_RETURN_ERROR(PINE_INI_ERRCODE_ILLEGAL_PATTERN);
|
||||
}
|
||||
|
||||
} while(getsRetCode != PARSER_ACTION_END);
|
||||
|
||||
PineIni_Parser_Destory(parser);
|
||||
|
||||
return iniResult;
|
||||
}
|
||||
|
||||
PineIniSection* PineIni_Find(PineIniFile* file, const char* sectionName) {
|
||||
if (file) {
|
||||
int i;
|
||||
for (i = 0; i < file->numSection; ++i) {
|
||||
PineIniSection* section = file->sections[i];
|
||||
if (PineIni_StringEquals(sectionName, section->name)) {
|
||||
return section;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PineIniFile* PineIni_Append(PineIniFile* file, PineIniSection* section) {
|
||||
if (file) {
|
||||
file->sections[file->numSection++] = section;
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
void PineIni_Destory(PineIniFile* file) {
|
||||
if (file) {
|
||||
int i;
|
||||
|
||||
// destory sections in file
|
||||
for (i = 0; i < file->numSection; ++i) {
|
||||
PineIni_Section_Destory(file->sections[i]);
|
||||
}
|
||||
|
||||
// free file self
|
||||
free(file);
|
||||
}
|
||||
}
|
||||
|
||||
// Section
|
||||
|
||||
PineIniSection* PineIni_Section_New(const char* sectionName) {
|
||||
PineIniSection* section = (PineIniSection *)malloc(sizeof(PineIniSection));
|
||||
|
||||
section->name = PineIni_StringDump(sectionName);
|
||||
section->numParam = 0;
|
||||
|
||||
return section;
|
||||
}
|
||||
|
||||
PineIniParameter* PineIni_Section_Find(PineIniSection* section, const char* key) {
|
||||
if (section) {
|
||||
int i;
|
||||
for (i = 0; i < section->numParam; ++i) {
|
||||
PineIniParameter* param = section->params[i];
|
||||
if (PineIni_StringEquals(key, param->key)) {
|
||||
return param;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PineIniSection* PineIni_Section_Append(PineIniSection* section, const char* key, const char* value) {
|
||||
if (section) {
|
||||
section->params[section->numParam++] = PineIni_Parameter_New(key, value);
|
||||
}
|
||||
return section;
|
||||
}
|
||||
|
||||
void PineIni_Section_Destory(PineIniSection* section) {
|
||||
if (section) {
|
||||
int i;
|
||||
|
||||
// free section name
|
||||
if (section->name) {
|
||||
free(section->name);
|
||||
}
|
||||
// destory parameters in section
|
||||
for (i = 0; i < section->numParam; ++i) {
|
||||
PineIni_Parameter_Destory(section->params[i]);
|
||||
}
|
||||
// free section self
|
||||
free(section);
|
||||
}
|
||||
}
|
||||
|
||||
// Parameter
|
||||
|
||||
PineIniParameter* PineIni_Parameter_New(const char* key, const char* value) {
|
||||
PineIniParameter* param;
|
||||
|
||||
param = (PineIniParameter *)malloc(sizeof(PineIniParameter));
|
||||
param->key = PineIni_StringDump(key);
|
||||
param->value = PineIni_StringDump(value);
|
||||
|
||||
return param;
|
||||
}
|
||||
|
||||
PineIniParameter* PineIni_Parameter_Assign(PineIniParameter* param, const char* value) {
|
||||
if (param) {
|
||||
if (param->value) {
|
||||
free(param->value);
|
||||
}
|
||||
param->value = PineIni_StringDump(value);
|
||||
}
|
||||
return param;
|
||||
}
|
||||
|
||||
void PineIni_Parameter_Destory(PineIniParameter* param) {
|
||||
if (param) {
|
||||
if (param->key) {
|
||||
free(param->key);
|
||||
}
|
||||
if (param->value) {
|
||||
free(param->value);
|
||||
}
|
||||
free(param);
|
||||
}
|
||||
}
|
||||
|
||||
// Utils functions
|
||||
|
||||
int PineIni_FindChar(const char* src, const char find) {
|
||||
int i;
|
||||
for (i = 0; src[i]; ++i) {
|
||||
if (src[i] == find) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
char* PineIni_Substring(char* dest, const char* src, int left, int right) {
|
||||
char* buf = dest;
|
||||
int newLength = 0;
|
||||
int i;
|
||||
|
||||
for (i = left; i <= right; ++i) {
|
||||
buf[newLength++] = src[i];
|
||||
}
|
||||
|
||||
buf[newLength] = 0;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
char* PineIni_ToSubstring (char* src, int left, int right) {
|
||||
int length = strlen(src);
|
||||
char* buf = (char *)malloc(length + 1);
|
||||
int newLength = 0;
|
||||
int i;
|
||||
|
||||
for (i = left; i <= right; ++i) {
|
||||
buf[newLength++] = src[i];
|
||||
}
|
||||
|
||||
buf[newLength] = 0;
|
||||
|
||||
strcpy(src, buf);
|
||||
|
||||
free(buf);
|
||||
|
||||
return src;
|
||||
}
|
||||
|
||||
char* PineIni_StringDump (const char* src) {
|
||||
int length = strlen(src);
|
||||
char* dup = (char *)malloc(length + 1);
|
||||
strcpy(dup, src);
|
||||
return dup;
|
||||
}
|
||||
|
||||
|
||||
char* PineIni_StringTrim(char* src) {
|
||||
int length = strlen(src);
|
||||
int left;
|
||||
int right;
|
||||
int newLength = 0;
|
||||
|
||||
for (left = 0; left < length; ++left) {
|
||||
if (!isWhitespace(src[left])) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (right = length - 1; right >= 0; --right) {
|
||||
if (!isWhitespace(src[right])) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return PineIni_ToSubstring(src, left, right);
|
||||
}
|
||||
|
||||
char* PineIni_StringRemoveQuotes(char* src) {
|
||||
int length;
|
||||
int isSingleQuotesAround;
|
||||
int isDoubleQuotesAround;
|
||||
|
||||
|
||||
PineIni_StringTrim(src);
|
||||
|
||||
// Too short, no need to check
|
||||
if ((length = strlen(src)) < 2) {
|
||||
return src;
|
||||
}
|
||||
|
||||
isSingleQuotesAround = (src[0] == '"' && src[length - 1] == '"');
|
||||
isDoubleQuotesAround = (src[0] == '\'' && src[length - 1] == '\'');
|
||||
|
||||
if (!isSingleQuotesAround && !isDoubleQuotesAround) {
|
||||
return src;
|
||||
}
|
||||
|
||||
return PineIni_ToSubstring(src, 1, length - 2);
|
||||
}
|
||||
99
pine-ini.h
Normal file
99
pine-ini.h
Normal file
@@ -0,0 +1,99 @@
|
||||
#ifndef _PINE_INI_H_
|
||||
#define _PINE_INI_H_
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL ((void *) 0)
|
||||
#endif
|
||||
|
||||
typedef int PINE_BOOL;
|
||||
#define PINE_TRUE 1
|
||||
#define PINE_FALSE 0
|
||||
|
||||
//
|
||||
// * How many parameters in section
|
||||
//
|
||||
#define PINE_INI_MAX_NUM_PARAMETERS 25
|
||||
|
||||
//
|
||||
// * How many sections in ini file
|
||||
//
|
||||
#define PINE_INI_MAX_NUM_SECTIONS 25
|
||||
|
||||
//
|
||||
// * The maximum length of token in ini
|
||||
//
|
||||
#define PINE_INI_LINE_MAX_LEN 150
|
||||
|
||||
//
|
||||
// * A single parameter in section
|
||||
//
|
||||
typedef struct tagPineIniParameter {
|
||||
char * key;
|
||||
char * value;
|
||||
} PineIniParameter;
|
||||
//
|
||||
// * A single section in ini file
|
||||
//
|
||||
typedef struct tagPineIniSection {
|
||||
char * name;
|
||||
int numParam;
|
||||
PineIniParameter* params[PINE_INI_MAX_NUM_PARAMETERS];
|
||||
} PineIniSection;
|
||||
|
||||
//
|
||||
// * The analysis result of ini file
|
||||
//
|
||||
typedef struct tagPineIni {
|
||||
int numSection;
|
||||
PineIniSection* sections[PINE_INI_MAX_NUM_SECTIONS];
|
||||
} PineIniFile;
|
||||
|
||||
//
|
||||
// * Error Codes
|
||||
//
|
||||
#define PINE_INI_ERRCODE_NO 0
|
||||
#define PINE_INI_ERRCODE_ILLEGAL_PATTERN 1
|
||||
#define PINE_INI_ERRCODE_EMPTY_KEY 2
|
||||
#define PINE_INI_ERRCODE_SECTION_EXCEED 3
|
||||
#define PINE_INI_ERRCODE_PARAMS_EXCEED 4
|
||||
|
||||
extern const char * PINE_INI_ERRMSG[];
|
||||
|
||||
typedef struct tagPineIniError {
|
||||
int errorCode;
|
||||
int lineNumber;
|
||||
char lineContent[PINE_INI_LINE_MAX_LEN];
|
||||
} PineIniError;
|
||||
|
||||
//
|
||||
// Interfaces
|
||||
//
|
||||
|
||||
PineIniParameter* PineIni_Parameter_New (const char* key, const char* value);
|
||||
PineIniParameter* PineIni_Parameter_Assign (PineIniParameter* param, const char* value);
|
||||
void PineIni_Parameter_Destory (PineIniParameter* param);
|
||||
|
||||
PineIniSection* PineIni_Section_New (const char* sectionName);
|
||||
PineIniParameter* PineIni_Section_Find (PineIniSection* section, const char* key);
|
||||
PineIniSection* PineIni_Section_Append (PineIniSection* section, const char* key, const char* value);
|
||||
void PineIni_Section_Destory (PineIniSection* section);
|
||||
|
||||
PineIniFile* PineIni_Parse (const char * iniText, PineIniError* errorRet);
|
||||
PineIniSection* PineIni_Find (PineIniFile* file, const char* sectionName);
|
||||
PineIniFile* PineIni_Append (PineIniFile* file, PineIniSection* section);
|
||||
void PineIni_Destory (PineIniFile* file);
|
||||
|
||||
// Utils functions
|
||||
|
||||
char* PineIni_ToSubstring (char* src, int left, int right);
|
||||
int PineIni_FindChar (const char* src, const char find);
|
||||
char* PineIni_Substring (char* dest, const char* src, int left, int right);
|
||||
char* PineIni_StringDump (const char* src);
|
||||
char* PineIni_StringTrim (char* src);
|
||||
char* PineIni_StringRemoveQuotes (char* src);
|
||||
|
||||
#define PineIni_StringEquals(str1, str2) (strcmp((str1), (str2)) == 0)
|
||||
|
||||
#endif
|
||||
5
sln-win32/.gitignore
vendored
Normal file
5
sln-win32/.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
Debug/
|
||||
Release/
|
||||
*.ncb
|
||||
*.opt
|
||||
*.plg
|
||||
97
sln-win32/PineIniReader.dsp
Normal file
97
sln-win32/PineIniReader.dsp
Normal file
@@ -0,0 +1,97 @@
|
||||
# Microsoft Developer Studio Project File - Name="PineIniReader" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
CFG=PineIniReader - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "PineIniReader.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "PineIniReader.mak" CFG="PineIniReader - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "PineIniReader - Win32 Release" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE "PineIniReader - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath "Desktop"
|
||||
# PROP WCE_FormatVersion "6.0"
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "PineIniReader - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x804 /d "NDEBUG"
|
||||
# ADD RSC /l 0x804 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
|
||||
!ELSEIF "$(CFG)" == "PineIniReader - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
||||
# ADD BASE RSC /l 0x804 /d "_DEBUG"
|
||||
# ADD RSC /l 0x804 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "PineIniReader - Win32 Release"
|
||||
# Name "PineIniReader - Win32 Debug"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\entry.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE="..\pine-ini.c"
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE="..\pine-ini.h"
|
||||
# End Source File
|
||||
# End Target
|
||||
# End Project
|
||||
29
sln-win32/PineIniReader.dsw
Normal file
29
sln-win32/PineIniReader.dsw
Normal file
@@ -0,0 +1,29 @@
|
||||
Microsoft Developer Studio Workspace File, Format Version 6.00
|
||||
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "PineIniReader"=".\PineIniReader.dsp" - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Global:
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<3>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Reference in New Issue
Block a user