Overview
Comment: | Add smallxrm |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
f6f1c94d23363504afe56e64e72f7fd9 |
User & Date: | user on 2018-03-09 06:00:54 |
Other Links: | manifest | tags |
Context
2018-03-10
| ||
22:48 | RLE compression of levels check-in: 06cd05742f user: user tags: trunk | |
2018-03-09
| ||
06:00 | Add smallxrm check-in: f6f1c94d23 user: user tags: trunk | |
01:33 | Add key names to names.js and names.h check-in: ceadd9ba47 user: user tags: trunk | |
Changes
Added smallxrm.c version [4ef0f077c3].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 | #if 0 gcc -s -O2 -c smallxrm.c exit #endif /* Small XRM (X Resource Manager) in C. Public domain. */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include "smallxrm.h" typedef struct xrm_pair { xrm_quark k; xrm_db*x; } xrm_pair; typedef struct xrm_map { int n; xrm_pair*p; } xrm_map; typedef struct xrm_db { xrm_map l; xrm_map t; char*v; } xrm_db; #define BUFINC 1024 static char anyq_name[2]="?"; static void*(*my_realloc)(void*,size_t); static int nquarks; static xrm_quark*quarklook; static char**quarknames; static xrm_quark keyquark=0; static const char*keyname; static char*inbuf; static int inbufsize; static int staticquarks; static void*cb_get_resource(xrm_db*db,void*usr) { return db->v; } static int db_compar(const void*a,const void*b) { const xrm_pair*x=a; const xrm_pair*y=b; return x->k<y->k?-1:x->k==y->k?0:1; } static char*my_strdup(const char*p) { char*s=my_realloc(0,strlen(p)+1); if(!s) return 0; strcpy(s,p); return s; } static int quarklook_compar(const void*a,const void*b) { xrm_quark x=*(const xrm_quark*)a; xrm_quark y=*(const xrm_quark*)b; return strcmp(x?quarknames[x-1]?:"":keyname,y?quarknames[y-1]?:"":keyname); } void xrm_annihilate(void) { int i; if(!my_realloc) return; for(i=staticquarks;i<nquarks;i++) my_realloc(quarknames[i],0); my_realloc(quarknames,0); nquarks=0; quarklook=0; quarknames=0; my_realloc(inbuf,0); inbuf=0; inbufsize=0; my_realloc=0; } xrm_db*xrm_create(void) { xrm_db*db=my_realloc(0,sizeof(xrm_db)); if(!db) return 0; db->l.n=0; db->l.p=0; db->t.n=0; db->t.p=0; db->v=0; return db; } void xrm_destroy(xrm_db*db) { int i; if(!db) return; my_realloc(db->v,0); for(i=0;i<db->l.n;i++) xrm_destroy(db->l.p[i].x); my_realloc(db->l.p,0); for(i=0;i<db->t.n;i++) xrm_destroy(db->t.p[i].x); my_realloc(db->t.p,0); my_realloc(db,0); } void*xrm_enumerate(xrm_db*db,void*(*cb)(xrm_db*,void*,int,xrm_quark),void*usr) { int i; void*r; if(!db) return 0; for(i=0;i<db->l.n;i++) if(r=cb(db,usr,1,db->l.p[i].k)) return r; for(i=0;i<db->t.n;i++) if(r=cb(db,usr,0,db->t.p[i].k)) return r; return 0; } const char*xrm_get(xrm_db*db) { return db?db->v:0; } const char*xrm_get_resource(xrm_db*db,const xrm_quark*ns,const xrm_quark*cs,int len) { if(!db) return 0; return xrm_search(db,ns,cs,len,cb_get_resource,0); } int xrm_init(void*(*f)(void*,size_t)) { if(my_realloc || !f) return -1; my_realloc=f; nquarks=1; quarknames=my_realloc(0,sizeof(char*)); if(!quarknames) goto bad; quarklook=my_realloc(0,sizeof(xrm_quark)); if(!quarklook) { my_realloc(quarknames,0); quarknames=0; goto bad; } *quarklook=xrm_anyq; *quarknames=anyq_name; inbuf=0; inbufsize=0; staticquarks=1; return 0; bad: my_realloc=0; return -1; } int xrm_init_quarks(const char*const*list) { void*mem; int i=0; if(!my_realloc || !list || nquarks!=1 || staticquarks!=1) return -1; while(list[i]) i++; mem=my_realloc(quarknames,(i+1)*sizeof(char*)); if(!mem) return -1; quarknames=mem; mem=my_realloc(quarklook,(i+1)*sizeof(xrm_quark)); if(!mem) return -1; quarklook=mem; nquarks=staticquarks=i+1; for(i=0;list[i];i++) { quarknames[i+1]=(char*)(list[i]); quarklook[i+1]=i+2; } qsort(quarklook,nquarks,sizeof(xrm_quark),quarklook_compar); return 0; } int xrm_link(xrm_db*db,int loose,xrm_quark q,xrm_db*ins) { xrm_map*m; xrm_pair*p; xrm_pair k={q,ins}; if(!db || !q) return 0; m=loose?&db->l:&db->t; if(m->n) { p=bsearch(&k,m->p,m->n,sizeof(xrm_pair),db_compar); if(p) { *p=k; return 0; } } p=my_realloc(m->p,(m->n+1)*sizeof(xrm_pair)); if(!p) return -1; p[m->n]=k; qsort(p,++m->n,sizeof(xrm_pair),db_compar); m->p=p; return 0; } int xrm_load(xrm_db*db,FILE*fp,int o) { int bs,c,n,x; if(!inbuf) { inbuf=my_realloc(0,BUFINC+2); if(!inbuf) return -1; inbufsize=BUFINC; } if(!db || !fp) return -1; for(c=0;c!=EOF;) { for(x=bs=0;(c=fgetc(fp))!=EOF;) { if(c=='\r') continue; if(c=='\\') { bs^=1; } else if(c=='\n') { if(bs--) x--; else break; } else { bs=0; } inbuf[x++]=c; if(x>=inbufsize) { char*buf=my_realloc(inbuf,inbufsize+BUFINC+2); if(!buf) return -1; inbuf=buf; inbufsize+=BUFINC; } } inbuf[x]=0; xrm_load_line(db,inbuf,o); } return 0; } int xrm_load_line(xrm_db*db,const char*s,int o) { int c; int loose=0; char*p; char*q=0; char*r; if(!s) return -1; if(!*s || *s=='!') return 0; if(*s=='#') return -1; if(s!=inbuf) { int i=strlen(s)+1; if(i>=inbufsize) { char*buf=my_realloc(inbuf,i+2); if(!buf) return -1; inbuf=buf; inbufsize=i; } strcpy(inbuf,s); } p=inbuf; while(*p==' ' || *p=='\t') s++; if(!*p) return 0; while(c=*p++) { if(c=='.' || c=='*' || c==':') { if(q) { r=p-1; *r--=0; while(r>q && (*r==' ' || *r=='\t')) *r--=0; db=xrm_sub(db,loose,xrm_make_quark(q,1)); if(!db) return -1; loose=0; q=0; } if(c=='*') loose=1; if(c==':') break; } else if(c!=' ' && c!='\t' && !q) { q=p-1; } } if(!c) return -1; if(db->v && !o) return 0; while(*p==' ' || *p=='\t') p++; q=p; while(c=*p++) { if(c=='\\') { if(p[0]>='0' && p[0]<'8' && p[1]>='0' && p[1]<'8' && p[2]>='0' && p[2]<'8') { r=p+2; *r=((p[0]-'0')<<6)|((p[1]-'0')<<3)|(p[2]-'0'); while(*r) r[-3]=*r,++r; r[-3]=0; } else { if(*p=='n') *p='\n'; r=p; while(*r) r[-1]=*r,++r; r[-1]=0; } } else if(c=='\r' || c=='\n') { break; } } *p=0; return xrm_put(db,q,1); } xrm_quark xrm_make_quark(const char*name,int addnew) { xrm_quark*q; if(name && !*name) return 0; keyname=name; if(!name) { if(!addnew) return 0; q=0; } else { q=bsearch(&keyquark,quarklook,nquarks,sizeof(xrm_quark),quarklook_compar); } if(addnew && !q) { xrm_quark*ql=my_realloc(quarklook,(nquarks+1)*sizeof(xrm_quark)); char**qn=my_realloc(quarknames,(nquarks+1)*sizeof(char*)); if(ql) quarklook=ql; if(qn) quarknames=qn; if(!ql || !qn) return 0; if(name) { qn[nquarks]=my_strdup(name); if(!qn[nquarks]) return 0; } else { qn[nquarks]=0; } ql[nquarks]=++nquarks; qsort(quarklook,nquarks,sizeof(xrm_quark),quarklook_compar); return nquarks; } else { return q?*q:0; } } int xrm_merge(xrm_db*to,xrm_db*from,int o) { int i; if(!from) return 0; if(!to) return -1; if(xrm_put(to,from->v,o)) return -1; for(i=0;i<from->t.n;i++) if(xrm_merge(xrm_sub(to,0,from->t.p[i].k),from->t.p[i].x,o)) return -1; for(i=0;i<from->l.n;i++) if(xrm_merge(xrm_sub(to,1,from->l.p[i].k),from->l.p[i].x,o)) return -1; return 0; } const char*xrm_name(xrm_quark n) { if(!n || n>nquarks) return 0; return quarknames[n-1]; } int xrm_put(xrm_db*db,const char*v,int o) { char*s; if(!db) return -1; if(db->v && !o) return 0; if(v) { s=my_strdup(v); if(!s) return -1; my_realloc(db->v,0); db->v=s; } else { my_realloc(db->v,0); db->v=0; } return 0; } int xrm_put_resource(xrm_db*db,const xrm_quark*q,const char*b,const char*v,int o) { while(*b) { if(*b!='.' && *b!='*') return -1; db=xrm_sub(db,*b=='*',*q); q++; b++; } return xrm_put(db,v,o); } void*xrm_search(xrm_db*db,const xrm_quark*ns,const xrm_quark*cs,int len,void*(*cb)(xrm_db*,void*),void*usr) { xrm_db*p; void*r; if(!len) return cb(db,usr); if((p=xrm_sub(db,0,*ns)) && (r=xrm_search(p,ns+1,cs+1,len-1,cb,usr))) return r; if(ns!=cs && (p=xrm_sub(db,0,*cs)) && (r=xrm_search(p,ns+1,cs+1,len-1,cb,usr))) return r; if((p=xrm_sub(db,0,xrm_anyq)) && (r=xrm_search(p,ns+1,cs+1,len-1,cb,usr))) return r; again: if((p=xrm_sub(db,1,*ns)) && (r=xrm_search(p,ns+1,cs+1,len-1,cb,usr))) return r; if(ns!=cs && (p=xrm_sub(db,1,*cs)) && (r=xrm_search(p,ns+1,cs+1,len-1,cb,usr))) return r; if((p=xrm_sub(db,1,xrm_anyq)) && (r=xrm_search(p,ns+1,cs+1,len-1,cb,usr))) return r; ns++; cs++; if(--len) goto again; return 0; } xrm_db*xrm_sub(xrm_db*db,int loose,xrm_quark q) { xrm_map*m; xrm_pair*p; xrm_pair k={q,0}; if(!db || !q) return 0; m=loose?&db->l:&db->t; if(m->n) { p=bsearch(&k,m->p,m->n,sizeof(xrm_pair),db_compar); if(p) return p->x; } k.x=xrm_create(); if(!k.x) return 0; p=my_realloc(m->p,(m->n+1)*sizeof(xrm_pair)); if(!p) { my_realloc(k.x,0); return 0; } p[m->n]=k; qsort(p,++m->n,sizeof(xrm_pair),db_compar); m->p=p; return k.x; } |
Added smallxrm.h version [4b3decb0ca].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 | /* Small XRM (X Resource Manager) in C. Public domain. */ #ifndef SMALLXRM_H_INCLUDED #define SMALLXRM_H_INCLUDED typedef struct xrm_db xrm_db; // type of database nodes typedef unsigned int xrm_quark; // type of quarks #define xrm_nullq ((xrm_quark)0) // not a valid quark #define xrm_anyq ((xrm_quark)1) // the "?" quark // Memory handling: Any xrm_db* values returned by these functions are // invalid if xrm_destroy() is subsequently used on that node or on any of // its ancestor nodes. Any string pointers returned by these functions are // invalid if the node it belongs to is destroyed, if the resource value is // changed, or if xrm_annihilate() is called. Do not free them by yourself. void xrm_annihilate(void); // Releases all memory used by this library. Does nothing if not // initialized. You must first call xrm_destroy() on any existing resource // databases you may have allocated. After xrm_annihilate() is called, // nothing else should be called without calling xrm_init() first. You may // safely terminate the program without calling this function, since the // only thing it does is free memory, which is automatically done when the // program terminates anyways. xrm_db*xrm_create(void); // Creates a new empty resource database. void xrm_destroy(xrm_db*db); // Destroy an existing resource database. All sub-databases are also // destroyed. The memory is freed. void*xrm_enumerate(xrm_db*db,void*(*cb)(xrm_db*,void*,int,xrm_quark),void*usr); // Calls the given callback function for each child node of the resource // database; the first two arguments are the same as db and usr given to // this function, while the next is 1 if loose or 0 if tight, and the next // is the quark that is in use. You can then call xrm_sub() in order to // access the sub-database it contains. If the callback returns null, then // the enumeration continues, otherwise it returns with the same value. It // only goes one level deep; you can use it recursively to go more deep. const char*xrm_get(xrm_db*db); // Retrieves the value of the resource at the root of the given database. // If there is no value, the result is a null pointer. const char*xrm_get_resource(xrm_db*db,const xrm_quark*ns,const xrm_quark*cs,int len); // Retrieves the value of a given resource, given the root node, list of // quarks for the name of the query, list of quarks for the class of the // query, and the length of the name and class list. Both list pointers // must be non-null, but you may give the same pointers for each. If there // is no such resource, the result is a null pointer. int xrm_init(void*(*f)(void*,size_t)); // Initialize the library; must be called exactly once, before anything // else is called. The argument should be realloc, or your own function // that does the same thing; all dynamic memory allocation done by the // library will use the function you give for this purpose. Return value // is 0 if success or -1 if error. int xrm_init_quarks(const char*const*list); // Optional. If you call it, it must be called after xrm_init() is called // before any other library functions are called. The argument is a null // terminated list of strings, all of which must be unique, and none of // them may be "?". They are assigned constant quark numbers, where the // first string is the name of quark number 2, the next being quark number // 3, and so on. You can use this in order to make compile-time constants // for the quarks used in your program. The library does not make copies // of the strings; they must exist for the entire duration of the library. // The return value is 0 if OK or -1 if not OK. int xrm_link(xrm_db*db,int loose,xrm_quark q,xrm_db*ins); // Insert a node (the fourth argument) as child of the node given by the // first argument. The node is now "owned" by the parent; if you then call // xrm_destroy() without unlinking it, it will destroy that one too. You // normally do not need to use this function. Return value is 0 if it is // successful or -1 in case of error. int xrm_load(xrm_db*db,FILE*fp,int o); // Load a resource database from an open file handle. #include is not // currently implemented. It loads into the given database, and returns 0 // if successful or -1 if error. The third argument is nonzero if it // should override existing resources, or zero if it doesn't. int xrm_load_line(xrm_db*db,const char*s,int o); // Load a resource from a string, which must be a single line; in case of // any line breaks, they and anything after them are ignored. Line // continuation is not implemented by xrm_load_line() (but xrm_load() does // implement it). xrm_quark xrm_make_quark(const char*name,int addnew); // Make a new quark (or retrieves an existing quark by name) and returns // it. The return value is zero (xrm_nullq) if it does not exist. The // second argument is zero to retrieve only existing quarks, or nonzero if // it should make a new quark if there isn't an existing quark with the // given name. If the first argument is null and the second argument is // nonzero, then it makes a new unique quark. The library makes a copy of // the passed string if a new quark is made; you need not copy it yourself. int xrm_merge(xrm_db*to,xrm_db*from,int o); // Merge the second database into the first one. Returns 0 if success or // -1 if error. The third argument is zero if the existing resources have // priority or nonzero if the new ones do. const char*xrm_name(xrm_quark n); // Returns the name of the given quark. If there is no such quark, or if // it is xrm_nullq, or if it has no name, the result is null. int xrm_put(xrm_db*db,const char*v,int o); // Set the value of the node. First argument is the node, second argument // is the value (the library makes a copy of it) or null to delete the // value, and third argument is nonzero to override an existing value or // zero to not change an existing value. Returns 0 if successful. int xrm_put_resource(xrm_db*db,const xrm_quark*q,const char*b,const char*v,int o); // Set the value of a resource. The second argument is the quark list, the // third argument is the binding list, the fourth argument is the value, // and the fifth argument specifies to override or not. The binding list // is a string containing characters '*' and '.' and must have the same // length as the quark list. void*xrm_search(xrm_db*db,const xrm_quark*ns,const xrm_quark*cs,int len,void*(*cb)(xrm_db*,void*),void*usr); // Perform a search of the given resource database, given the list of // quarks for name of the query, quarks for class of the query, length of // the quark lists, a callback function, and the user value for the // callback function. Both the name and class list must be not null, but // they may be the same pointer. It calls the callback function for each // node in priority order, and stops once the callback function returns // not null, and then xrm_search() returns the same value. xrm_db*xrm_sub(xrm_db*db,int loose,xrm_quark q); // Access a child node of the given node. The second argument is zero for // a tight binding or nonzero for loose. The third is the quark. If no // such node exists, a new node with no value or children is created. #endif |