📄 keydata.c
字号:
/*** Copyright (C) 1999-2000 Open Source Telecom Corporation.** ** 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 2 of the License, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.**** As a special exception to the GNU General Public License, permission is** granted for additional uses of the text contained in its release** of ACS as noted here.**** This exception is that permission is hereby granted to link ACS with** the Pika MonteCarlo static libraries to produce a executable image** without requiring MonteCarlo itself to be supplied in source form so** long as each source file so linked contains this exclusion.**** This exception does not however invalidate any other reasons why** the resulting executable file might be covered by the GNU General** public license or invalidate the licensing requirements of any** other component or library.**** This exception applies only to the code released by OST under the** name ACS. If you copy code from other releases into a copy of** ACS, as the General Public License permits, the exception does not** apply to the code that you add in this way. To avoid misleading** anyone as to the status of such modified files, you must delete** this exception notice from them.**** If you write modifications of your own to ACS, it is your choice** whether to permit this exception to apply to your modifications.** If you do not wish that, delete this exception notice, at which** point the terms of your modification would be covered under the GPL** as explicitly stated in "COPYING".*/#include <string.h>#include <unistd.h>#include <stdlib.h>#include <fcntl.h>#include <stdio.h>#include "keydata.h"#ifndef KEY_INDEXSIZE#define KEY_INDEXSIZE 97#endif#ifdef HAVE_CONFIG_H#include "config.h"#endiftypedef struct _keyval{ struct _keyval *next; char val[1];} keyval_t;typedef struct _keysym{ struct _keysym *next; struct _keyval *data; char **list; short count; char sym[1];} keysym_t;typedef struct{ keysym_t *hash[KEY_INDEXSIZE];} keyidx_t;static FILE *fp = NULL;static char lastpath[257] = "";keydata_t *newkeydata(void){ keydata_t *root = (keydata_t *)malloc(sizeof(keydata_t)); if(!root) return NULL; root->next = NULL; root->used = sizeof(keyidx_t); memset(root->page, 0, sizeof(keyidx_t)); return root;}static void *getkeymem(keydata_t *root, size_t len){ void *p; keydata_t *last = root; while(last->next) last = last->next; if(!last) { last = root = (keydata_t *)malloc(sizeof(keydata_t)); root->next = NULL; root->used = 0; } else if((last->used + len) > (sizeof(keydata_t) - sizeof(keydata_t *) - sizeof(size_t))) { last->next = (keydata_t *)malloc(sizeof(keydata_t)); last = last->next; last->next = NULL; last->used = 0; } p = &last->page[last->used]; last->used += len; return p;} static void endkeymem(keydata_t *root){ keydata_t *next; while(root) { next = root->next; free(root); root = next; }}static unsigned getkeypath(char *str){ unsigned key = 0; while(*str) key = (key << 1) ^ *(str++); return key % KEY_INDEXSIZE;}int getkeyindex(keydata_t *root, char **data, int max){ int idx; keyidx_t *keys = (keyidx_t *)root->page; keysym_t *key; int count = 0; for(idx = 0; idx < KEY_INDEXSIZE; ++idx) { if(count >= max) break; key = keys->hash[idx]; while(key && count < max) { *(data++) = key->sym; ++count; } } *data = NULL; return count;}static keysym_t *getkeysym(keydata_t *root, char *sym, int create){ unsigned path = getkeypath(sym); keyidx_t *keys = (keyidx_t *)root->page; keysym_t *key = keys->hash[path]; while(key) { if(!stricmp(sym, key->sym)) return key; key = key->next; } if(!create) return key; key = (keysym_t *)getkeymem(root, sizeof(keysym_t) + strlen(sym)); strcpy(key->sym, sym); key->count = 0; key->next = keys->hash[path]; keys->hash[path] = key; key->data = NULL; key->list = NULL; return key;}void endkeydata(keydata_t *root){ if(fp) { fclose(fp); fp = NULL; lastpath[0] = 0; } if(root) endkeymem(root);}void setkeyvalue(keydata_t *root, char *sym, char *data){ keysym_t *key = getkeysym(root, sym, 1); keyval_t *val; if(!data) data = ""; val = getkeymem(root, sizeof(keyval_t) + strlen(data)); ++key->count; key->list = NULL; val->next = key->data; key->data = val; strcpy(val->val, data); }char *getkeylast(keydata_t *root, char *sym){ keysym_t *key = getkeysym(root, sym, 0); if(!key) return NULL; if(!key->data) return NULL; return key->data->val;} char *getkeyfirst(keydata_t *root, char *sym){ keysym_t *key = getkeysym(root, sym, 0); keyval_t *val; if(!key) return NULL; val = key->data; if(!val) return NULL; while(val->next) val = val->next; return val->val;}int getkeycount(keydata_t *root, char *sym){ keysym_t *key = getkeysym(root, sym, 0); if(!key) return 0; return key->count;}char **getkeylist(keydata_t *root, char *sym){ int count; keysym_t *key = getkeysym(root, sym, 0); keyval_t *data; if(!key) return NULL; count = key->count; if(!count) return NULL; ++count; if(!key->list) { key->list = (char **)getkeymem(root, sizeof(char **) * count); key->list[--count] = NULL; data=key->data; while(count && data) { key->list[--count] = data->val; data=data->next; } while(count) key->list[--count] = ""; } return key->list;}void clrkeyvalue(keydata_t *root, char *sym){ keysym_t *key = getkeysym(root, sym, 0); if(!key) return; key->count = 0; key->list = NULL; key->data = NULL;}keydata_t *addkeydata(keydata_t *root, char *keypath){ char path[512]; char seek[17]; char find[17]; char *prefix = NULL; char *cp, *ep; int fpos; keysym_t *sym; keyval_t *val; if(*keypath == '~') { prefix = getenv("HOME"); strcpy(path, prefix); strcat(path, "/."); ++keypath; } if(!prefix) { prefix = getenv("CONFIG_KEYDATA"); if(!prefix) prefix = "/etc/"; strcpy(path, prefix); prefix = NULL; } if(*keypath == '/') ++keypath; strcat(path, keypath); cp = strrchr(path, '/'); strncpy(seek, cp + 1, 16); seek[16] = 0; *cp = 0; if(!prefix) strcat(path, ".conf"); if(strcmp(path, lastpath)) { endkeydata(NULL); if(fp) fclose(fp); fp = fopen(path, "r"); if(!fp && !prefix) fp = fopen(path + 5, "r"); if(!fp) return NULL; strcpy(lastpath, path); } find[0] = 0; fseek(fp, 0l, SEEK_SET); while(stricmp(seek, find)) { fgets(path, sizeof(path) - 1, fp); if(feof(fp)) return NULL; cp = path; while(*cp == ' ' || *cp == '\n' || *cp == '\t') ++cp; if(*cp != '[') continue; ep = strchr(cp, ']'); if(ep) *ep = 0; else continue; strncpy(find, ++cp, 16); find[16] = 0; } for(;;) { fgets(path, sizeof(path) - 1, fp); if(feof(fp)) return root; cp = path; while(*cp == ' ' || *cp == '\t' || *cp == '\n') ++cp; if(!*cp || *cp == '#' || *cp == ';' || *cp == '!') continue; if(*cp == '[') return root; fpos = 0; while(*cp && *cp != '=') { if(*cp == ' ' || *cp == '\t') { ++cp; continue; } find[fpos] = *(cp++); if(fpos < 16) ++fpos; } find[fpos] = 0; if(*cp != '=') continue; ++cp; while(*cp == ' ' || *cp == '\t' || *cp == '\n') ++cp; ep = cp + strlen(cp); while((--ep) > cp) { if(*ep == ' ' || *ep == '\t' || *ep == '\n') *ep = 0; else break; } setkeyvalue(root, find, cp); } }keydata_t *getkeydata(char *path){ keydata_t *root = newkeydata(); keydata_t *p; if(root) p = addkeydata(root, path); if(!p) endkeymem(root); return p;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -