init_file.c

来自「OTP是开放电信平台的简称」· C语言 代码 · 共 548 行

C
548
字号
#include <windows.h>#include <stdio.h>#include <stdlib.h>#include "init_file.h"#define ALLOC malloc#define REALLOC realloc#define FREE free #define CONTEXT_BUFFER_SIZE 1024typedef struct {    HANDLE fd;    int eof;    int num;    int pos;    char buff[CONTEXT_BUFFER_SIZE];} FileContext;static char *read_one_line(FileContext *fc){    char *buff = ALLOC(10);    int size = 10;    int num = 0;    int skipping;    int escaped;#define PUSH(Char) 				\    do {					\	if (num == size) {			\	    size += 10;				\	    buff = REALLOC(buff,size);		\	}					\	buff[num++] = (Char);			\    } while(0)#define POP() (buff[--num])#define TOP() (buff[(num-1)])    skipping = 0;    escaped = 0;    for(;;) {	char current;	if (fc->eof) {	    break;	}	if (fc->pos == fc->num) {	    if (!ReadFile(fc->fd, fc->buff, CONTEXT_BUFFER_SIZE, 			  &(fc->num), NULL) || !(fc->num)) {		fc->eof = 1;		break;	    }	    fc->pos = 0;	}	current = fc->buff[fc->pos];	++(fc->pos);	switch (current) {	case ' ':	    if (!skipping && num) {		PUSH(current);	    }	    escaped = 0;	    break;	case ';':	    if (!skipping) {		if (!escaped) {		    skipping = 1;		} else {		    PUSH(current);		}	    }	    escaped = 0;	    break;	case '\\':	    if (!skipping) {		if (!escaped) {		    escaped = 1;		} else {		    PUSH(current);		    escaped = 0;		}	    }	    break;	case '\r':	    break;	case '\n':	    if (!escaped) {		while (num && TOP() == ' ') {			POP();		}		if (num) {		    goto done;		}	    } 	    skipping = 0;	    escaped = 0;	    break;	default:	    if (!skipping) {		PUSH(current);	    }	    escaped = 0;	    break;	}    }    /* EOF comes here */    while (num && TOP() == ' ') {	POP();    }    if (!num) {	FREE(buff);	return NULL;    } done:    PUSH('\0');    return buff;#undef PUSH#undef POP#undef TOP}static int is_section_header(char *line) {    int x = strlen(line);    return (x > 2 && *line == '[' && line[x-1] == ']');}static int is_key_value(char *line){    char *p = strchr(line,'=');    return (p != NULL && p > line);}static char *digout_section_name(char *line)     /* Moving it because it shall later be freed. */{    int x = strlen(line);    memmove(line,line+1,x-1);    line[x-2] = '\0';    return line;}static void digout_key_value(char *line, char **key, char **value){    char *e = strchr(line,'=');    *key = line;    *value = (e+1);    *e = '\0';    while (*(--e) == ' ') {	*e = '\0';    }    while (**value == ' ') {	++(*value);    }}InitFile *load_init_file(char *filename){    HANDLE infile;    InitFile *inif;    InitSection *inis;    InitEntry *inie;    FileContext fc;    char *line;    char **lines;    int size_lines;    int num_lines;    int i;    if ( (infile = CreateFile(filename, 			      GENERIC_READ,			      FILE_SHARE_READ,			      NULL,			      OPEN_EXISTING,			      FILE_ATTRIBUTE_NORMAL,			      NULL)) == INVALID_HANDLE_VALUE) {	return NULL;    }        size_lines = 10;    num_lines = 0;    lines = ALLOC(size_lines * sizeof(char *));    fc.fd = infile;    fc.eof = 0;    fc.num = 0;    fc.pos = 0;    while ((line = read_one_line(&fc)) != NULL) {	if (num_lines == size_lines) {	    size_lines += 10;	    lines = REALLOC(lines,size_lines * sizeof(char *));	}	lines[num_lines] = line;	++num_lines;    }    CloseHandle(infile);    /* Now check the lines before doing anything else, so that        we don't need any error handling while creating the data       structures */    /*        The file should contain:       [section]       Key=Value       ...       [section]       ...    */    i = 0;    while (i < num_lines && is_section_header(lines[i])) {	++i;	while (i < num_lines && is_key_value(lines[i])) {	    ++i;	}    }    if (i < num_lines) {	for (i = 0; i < num_lines; ++i) {	    FREE(lines[i]);	}	FREE(lines);	return NULL;    }        /* So, now we know it's consistent... */    i = 0;    inif = ALLOC(sizeof(InitFile));    inif->num_sections = 0;    inif->size_sections = 10;    inif->sections = ALLOC(sizeof(InitSection *) * 10);     while (i < num_lines) {	inis = ALLOC(sizeof(InitSection));	inis->num_entries = 0;	inis->size_entries = 10;	inis->section_name = digout_section_name(lines[i]);	inis->entries = ALLOC(sizeof(InitEntry *) * 10);	++i;	while (i < num_lines && is_key_value(lines[i])) {	    inie = ALLOC(sizeof(InitEntry));	    digout_key_value(lines[i], &(inie->key), &(inie->value));	    if (inis->num_entries == inis->size_entries) {		inis->size_entries += 10;		inis->entries = 		    REALLOC(inis->entries,			    sizeof(InitEntry *) * inis->size_entries);	    }	    inis->entries[inis->num_entries] = inie;	    ++(inis->num_entries);	    ++i;	}	if (inif->num_sections == inif->size_sections) {	    inif->size_sections += 10;	    inif->sections = 		REALLOC(inif->sections,			sizeof(InitSection *) * inif->size_sections);	}	inif->sections[inif->num_sections] = inis;	++(inif->num_sections);    }    FREE(lines); /* Only the array of strings, not the actual strings, they		    are kept in the data structures. */    return inif;}int store_init_file(InitFile *inif, char *filename){    char *buff;    int size = 10;    int num = 0;    int i,j;    HANDLE outfile;#define PUSH(Char) 				\    do {					\	if (num == size) {			\	    size += 10;				\	    buff = REALLOC(buff,size);		\	}					\	buff[num++] = (Char);			\    } while(0)    if ( (outfile = CreateFile(filename, 			      GENERIC_WRITE,			      FILE_SHARE_WRITE,			      NULL,			      CREATE_ALWAYS,			      FILE_ATTRIBUTE_NORMAL,			      NULL)) == INVALID_HANDLE_VALUE) {	return INIT_FILE_OPEN_ERROR;    }    buff = ALLOC(size);    for(i = 0; i < inif->num_sections; ++i) {	int len;	int written;	InitSection *inis = inif->sections[i];	if (!WriteFile(outfile,"[",1,&written,NULL) || written != 1) {	    goto write_error;	}	len = strlen(inis->section_name);	if (!WriteFile(outfile,inis->section_name,len,&written,NULL) ||	    written != len) {	    goto write_error;	}	if (!WriteFile(outfile,"]\n",2,&written,NULL) || written != 2) {	    goto write_error;	}	for (j = 0; j < inis->num_entries; ++j) {	    InitEntry *inie = inis->entries[j];	    char *p = inie->key;	    num = 0;	    for (;*p != '\0';++p) {		switch (*p) {		case '\\': 		case ';': 		    PUSH('\\');		default:		    PUSH(*p);		    break;		}	    }	    PUSH('=');	    p = inie->value;	    for (;*p != '\0';++p) {		switch (*p) {		case '\\': 		case ';': 		    PUSH('\\');		default:		    PUSH(*p);		    break;		}	    }	    PUSH('\n');	    if (!WriteFile(outfile,buff,num,&written,NULL) || written != num) {		goto write_error;	    }	}    }    FREE(buff);    CloseHandle(outfile);    return INIT_FILE_NO_ERROR; write_error:    FREE(buff);    CloseHandle(outfile);    return INIT_FILE_WRITE_ERROR;#undef PUSH}InitFile *create_init_file(void){    InitFile *inif = ALLOC(sizeof(InitFile));    inif->num_sections = 0;    inif->size_sections = 10;    inif->sections = ALLOC(sizeof(InitSection *) * 10);    return inif;}InitSection *create_init_section(char *section_name){    InitSection *inis = ALLOC(sizeof(InitSection));    inis->num_entries = 0;    inis->section_name = ALLOC(sizeof(char) * (strlen(section_name) + 1));    strcpy(inis->section_name, section_name);    inis->size_entries = 10;    inis->entries = ALLOC(sizeof(InitEntry *) * 10);    return inis;}static void free_init_entry(InitEntry *inie){    FREE(inie->key);    /* Value is part of the same buffer */    FREE(inie);}void free_init_section(InitSection *inis){    int i;    for (i = 0;i < inis->num_entries; ++i) {	free_init_entry(inis->entries[i]);    }    FREE(inis->entries);    FREE(inis->section_name);    FREE(inis);}void free_init_file(InitFile *inif){    int i;    for (i = 0; i < inif->num_sections; ++i) {	free_init_section(inif->sections[i]);    }    FREE(inif->sections);    FREE(inif);}static int find_init_section(InitFile *inif, char *section_name){    int i;    for (i = 0; i < inif->num_sections; ++i) {	if (!strcmp(inif->sections[i]->section_name, section_name)) {	    return i;	}    }    return -1;}int delete_init_section(InitFile *inif, char *section_name){    int i;    if ((i = find_init_section(inif, section_name)) < 0) {	return INIT_FILE_NOT_PRESENT;    }    free_init_section(inif->sections[i]);    --(inif->num_sections);    inif->sections[i] = inif->sections[inif->num_sections];    return INIT_FILE_PRESENT;}int add_init_section(InitFile *inif, InitSection *inis){    int i;    InitSection *oinis;    if ((i = find_init_section(inif, inis->section_name)) >= 0) {	oinis = inif->sections[i];	inif->sections[i] = inis;	free_init_section(oinis);	return INIT_FILE_PRESENT;    }     if (inif->num_sections == inif->size_sections) {	inif->size_sections += 10;	inif->sections = REALLOC(inif->sections, 				 sizeof(InitSection *) * inif->size_sections);    }    inif->sections[inif->num_sections] = inis;    ++(inif->num_sections);    return INIT_FILE_NOT_PRESENT;}InitSection *lookup_init_section(InitFile *inif, char *section_name){    int i;    if ((i = find_init_section(inif,section_name)) < 0) {	return NULL;    }    return inif->sections[i];}char *nth_init_section_name(InitFile *inif, int n){    if (n >= inif->num_sections) {	return NULL;    }    return inif->sections[n]->section_name;}/* Inefficient... */InitSection *copy_init_section(InitSection *inis, char *new_name) {    int i;    char *key;    InitSection *ninis = create_init_section(new_name);    i = 0;    while ((key = nth_init_entry_key(inis,i)) != NULL) {	add_init_entry(ninis, key, lookup_init_entry(inis, key));	++i;    }    return ninis;}static int find_init_entry(InitSection *inis, char *key){    int i;    for (i = 0; i < inis->num_entries; ++i) {	if (!strcmp(inis->entries[i]->key,key)) {	    return i;	}    }    return -1;}int add_init_entry(InitSection *inis, char *key, char *value){    int keylen = strlen(key);    char *buff = ALLOC(sizeof(char) * (keylen + strlen(value) + 2));    InitEntry *inie;    char *obuff;    int i;    strcpy(buff,key);    strcpy(buff+keylen+1,value);    if ((i = find_init_entry(inis,key)) >= 0) {	inie = inis->entries[i];	FREE(inie->key);	inie->key = buff;	inie->value = buff+keylen+1;	return INIT_FILE_PRESENT;    }    inie = ALLOC(sizeof(InitEntry));    inie->key = buff;    inie->value = buff+keylen+1;    if (inis->num_entries == inis->size_entries) {	inis->size_entries += 10;	inis->entries = REALLOC(inis->entries, 				sizeof(InitEntry *) * inis->size_entries);    }    inis->entries[inis->num_entries] = inie;    ++(inis->num_entries);    return INIT_FILE_NOT_PRESENT;}char *lookup_init_entry(InitSection *inis, char *key){    int i;    if ((i = find_init_entry(inis,key)) < 0) {	return NULL;    }    return inis->entries[i]->value;}char *nth_init_entry_key(InitSection *inis, int n){    if (n >= inis->num_entries) {	return NULL;    }    return inis->entries[n]->key;}int delete_init_entry(InitSection *inis, char *key){    int i;    InitEntry *inie;    if ((i = find_init_entry(inis, key)) < 0) {	return INIT_FILE_NOT_PRESENT;    }    free_init_entry(inis->entries[i]);    --(inis->num_entries);    inis->entries[i] = inis->entries[inis->num_entries];    return INIT_FILE_PRESENT;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?