📄 gbx_c_settings.c
字号:
/*************************************************************************** gbx_c_settings.c (c) 2000-2004 Beno顃 Minisini <gambas@users.sourceforge.net> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.***************************************************************************/#define __GBX_C_SETTINGS_C#include "gb_common.h"#include <pwd.h>#include <sys/types.h>#include <unistd.h>#include <fcntl.h>#include <sys/stat.h>#include "gb_common_case.h"#include "gb_error.h"#include "gb_buffer.h"#include "gb_file.h"#include "gbx_api.h"#include "gbx_project.h"#include "gbx_local.h"#include "gbx_number.h"#include "gbx_exec.h"#include "gbx_c_collection.h"#include "gbx_c_settings.h"/*#define DEBUG*/static char *_data;static long _ptr;static long _len;static char get_next_char(void){ if (_ptr >= _len) return 0; else return _data[_ptr++];}static void next_line(void){ char c; for(;;) { c = get_next_char(); if (c == '\n' || c == 0) break; }}static void unquote_string(VALUE *result, char *str, long len){ int i, j; char c; j = 0; for (i = 0; i < len; i++) { c = str[i]; if (c == '\\') { i++; c = str[i]; if (c == 'n') c = '\n'; } str[j++] = c; } if (len > 0) { result->type = T_STRING; STRING_new_temp(&result->_string.addr, str, j); result->_string.start = 0; result->_string.len = j; } else { result->type = T_NULL; }}static void from_string(VALUE *value, const char *addr, long len){ if (!DATE_from_string(addr, len, value, FALSE)) return; if (!NUMBER_from_string(NB_READ_BOTH | NB_READ_HEX_BIN, addr, len, value)) return; if (len == 0) { value->type = T_NULL; return; } value->type = T_BOOLEAN; value->_boolean.value = strchr("0FfNn", *addr) == NULL;}static bool check_key(const char *key, long len){ int i; char c; for (i = 0; i < len; i++) { c = key[i]; if (c <= ' ' || c == '=') { GB_Error("Bad key"); return TRUE; } } return FALSE;}static void read_line(CSETTINGS *_object){ long p; char c; char *key; long key_len; char *val; long val_len; VALUE result; p = _ptr; for(;;) { c = get_next_char(); if (c < ' ' || c == '=') break; } key = &_data[p]; key_len = _ptr - p - 1; for(;;) { c = get_next_char(); if ((c > ' ' && c != '=') || c == 0 || c == '\n') break; } p = _ptr - 1; next_line(); val = &_data[p]; val_len = _ptr - p - 1; #ifdef DEBUG fprintf(stderr, "%.*s = %.*s\n", (int)key_len, key, (int)val_len, val); #endif result.type = T_NULL; if (*val == '"') { val++; val_len--; if (val[val_len - 1] == '"') val_len--; unquote_string(&result, val, val_len); } else { result.type = T_CSTRING; result._string.addr = val; result._string.start = 0; result._string.len = val_len; from_string(&result, val, val_len); } if (result.type != T_NULL) { VALUE_conv(&result, T_VARIANT); GB_CollectionSet(THIS->table, key, key_len, (GB_VARIANT *)&result); }}static void load_config(CSETTINGS *_object){ char c; #ifdef DEBUG fprintf(stderr, "load_config: %s\n", THIS->path); #endif BUFFER_load_file(&_data, THIS->path); if (!_data) return; _ptr = 0; _len = BUFFER_length(_data); for(;;) { c = get_next_char(); if (c == 0) break; if (c <= ' ') continue; if (c == '#') { next_line(); continue; } _ptr--; read_line(THIS); } BUFFER_delete(&_data);}static void save_config(CSETTINGS *_object){ FILE *f; HASH_ENUM iter; HASH_TABLE *hash; void *value; char *str; long len; VALUE res; int i; char c; if (!THIS->modified) return; #ifdef DEBUG fprintf(stderr, "save_config: %s\n", THIS->path); #endif f = fopen(THIS->path, "w"); if (!f) { GB_Error((char *)E_OPEN, THIS->path, strerror(errno)); return; } fprintf(f, "# Gambas configuration file 1.0\n"); fprintf(f, "# for %s\n", PROJECT_name); hash = ((CCOLLECTION *)THIS->table)->hash_table; CLEAR(&iter); for(;;) { value = HASH_TABLE_next(hash, &iter); if (!value) break; HASH_TABLE_get_last_key(hash, &str, &len); /*for (i = 0; i < len; i++) fputc(tolower(str[i]), f);*/ fprintf(f, "%.*s=", (int)len, str); #ifdef DEBUG fprintf(stderr, "%.*s\n", (int)len, str); #endif VALUE_read(&res, value, T_VARIANT); VARIANT_undo(&res); if (TYPE_is_string(res.type)) { VALUE_get_string(&res, &str, &len); fputc('"', f); for (i = 0; i < len; i++) { c = str[i]; if (c == '\n') fprintf(f, "\\n"); else if (c == '\\' || c == '"') { fputc('\\', f); fputc(c, f); } else fputc(c, f); } fputc('"', f); } else if (res.type == T_BOOLEAN) { fputc(res._boolean.value ? '1' : '0', f); } else { VALUE_conv(&res, T_STRING); VALUE_get_string(&res, &str, &len); fprintf(f, "%.*s", (int)len, str); RELEASE(&res); } fputc('\n', f); } fclose(f); THIS->modified = FALSE;}BEGIN_METHOD(CSETTINGS_new, GB_STRING path) char *path; struct passwd *info; if (MISSING(path)) { info = getpwuid(getuid()); if (!info) { GB_Error((char *)E_MEMORY); return; } mkdir(FILE_cat(info->pw_dir, ".gambas", NULL), S_IRWXU); STRING_new(&path, FILE_cat(info->pw_dir, ".gambas", PROJECT_name, NULL), 0); STRING_add(&path, ".conf", 0); } else { STRING_new(&path, STRING(path), LENGTH(path)); } THIS->path = path; /*HASH_TABLE_create(&THIS->table, TYPE_sizeof(T_VARIANT), GB_COMP_TEXT);*/ GB_CollectionNew(&THIS->table, GB_COMP_TEXT); GB_Ref(THIS->table); load_config(THIS);END_METHODBEGIN_METHOD_VOID(CSETTINGS_free) save_config(THIS); STRING_free(&THIS->path); GB_Unref((void **)&THIS->table);END_METHODBEGIN_METHOD_VOID(CSETTINGS_save) save_config(THIS);END_METHODBEGIN_METHOD(CSETTINGS_get, GB_STRING key; GB_VALUE def) GB_VARIANT value; if (GB_CollectionGet(THIS->table, STRING(key), LENGTH(key), &value)) { if (MISSING(def)) GB_ReturnNull(); else TEMP = *((VALUE *)ARG(def)); } else GB_ReturnPtr(T_VARIANT, &value.value); END_METHODBEGIN_METHOD(CSETTINGS_put, GB_VARIANT value; GB_STRING key) VALUE *val; if (check_key(STRING(key), LENGTH(key))) return; val = (VALUE *)ARG(value); if (TYPE_is_object(val->type) || (TYPE_is_variant(val->type) && TYPE_is_object(val->_variant.vtype))) { GB_Error("Bad setting"); return; } GB_CollectionSet(THIS->table, STRING(key), LENGTH(key), ARG(value)); THIS->modified = TRUE;END_METHODPUBLIC GB_DESC NATIVE_Settings[] ={ GB_DECLARE("Settings", sizeof(CSETTINGS)), GB_AUTO_CREATABLE(), GB_METHOD("_new", NULL, CSETTINGS_new, "[(Path)s]"), GB_METHOD("_free", NULL, CSETTINGS_free, NULL), GB_METHOD("Save", NULL, CSETTINGS_save, NULL), GB_METHOD("_get", "v", CSETTINGS_get, "(Key)s[(Default)v]"), GB_METHOD("_put", NULL, CSETTINGS_put, "(Value)v(Key)s"), GB_END_DECLARE};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -