profile.h File Reference

a key-value store for loading configuration information More...

#include <stdlib.h>
#include <stddef.h>
#include "obj.h"

Go to the source code of this file.

Classes

struct  co_cbptr_t
 
struct  co_profile_t
 

Macros

#define SCHEMA(N)   static int schema_##N(co_obj_t *self, co_obj_t **output, co_obj_t *params)
 
#define SCHEMA_ADD(K, V)
 
#define SCHEMA_REGISTER(N)   co_schema_register(schema_##N)
 
#define SCHEMA_GLOBAL(N)   co_schema_register_global(schema_##N)
 

Typedefs

typedef struct co_cbptr_t co_cbptr_t
 
typedef struct co_profile_t co_profile_t
 

Functions

struct co_cbptr_t __attribute__ ((packed))
 
int co_schema_register (co_cb_t cb)
 register a callback for populating a profile schema More...
 
int co_schema_register_global (co_cb_t cb)
 register a callback for populating global profile More...
 
int co_schemas_load (co_obj_t *profile)
 load schemas for specified profile More...
 
int co_profiles_create (const size_t index_size)
 create global profiles list More...
 
int co_profiles_init (const size_t index_size)
 creates a list of available profiles
 
void co_profiles_shutdown (void)
 removes the list of available profiles
 
int co_profile_import_files (const char *path)
 imports available profiles from profiles directory More...
 
int co_profile_import_global (const char *path)
 imports global profile More...
 
co_obj_tco_profile_find (co_obj_t *name)
 searches the profile list for a specified profile More...
 
co_obj_tco_profile_global (void)
 returns the global profile
 
void co_profile_delete_global (void)
 deletes the global profile
 
int co_profile_add (const char *name, const size_t nlen)
 adds a new profile More...
 
int co_profile_remove (const char *name, const size_t nlen)
 removes profile with given name More...
 
void co_profile_dump (co_obj_t *profile)
 dumps profile data More...
 
co_obj_tco_profile_get (co_obj_t *profile, const co_obj_t *key)
 returns the key value (if an int) from the profile. If no value set, returns the default value More...
 
int co_profile_set_str (co_obj_t *profile, const char *key, const size_t klen, const char *value, const size_t vlen)
 sets a specified profile value (if a string) More...
 
size_t co_profile_get_str (co_obj_t *profile, char **output, const char *key, const size_t klen)
 returns the key value (if a string) from the profile. If no value set, returns the default value More...
 
int co_profile_set_int (co_obj_t *profile, const char *key, const size_t klen, const signed long value)
 sets a specified profile value (if an int) More...
 
signed long co_profile_get_int (co_obj_t *profile, const char *key, const size_t klen)
 returns the key value (if an int) from the profile. If no value set, returns the default value More...
 
int co_profile_set_uint (co_obj_t *profile, const char *key, const size_t klen, const unsigned long value)
 sets a specified profile value (if an unsigned int) More...
 
unsigned long co_profile_get_uint (co_obj_t *profile, const char *key, const size_t klen)
 returns the key value (if an unsigned int) from the profile. If no value set, returns the default value More...
 
int co_profile_set_float (co_obj_t *profile, const char *key, const size_t klen, const double value)
 sets a specified profile value (if a float) More...
 
double co_profile_get_float (co_obj_t *profile, const char *key, const size_t klen)
 returns the key value (if a float) from the profile. If no value set, returns the default value More...
 
int co_profile_export_file (co_obj_t *profile, const char *path)
 exports a profile in memory to a file More...
 
co_obj_tco_profiles_process (co_iter_t iter, void *context)
 processes all loaded profiles with specified iterator function More...
 

Variables

co_obj_t _header
 
uint8_t _exttype
 
uint8_t _len
 
co_cb_t cb
 
co_obj_tname
 
co_obj_tdata
 

Detailed Description

a key-value store for loading configuration information

Author
Josh King (jheretic), jking.nosp@m.@cha.nosp@m.mbana.nosp@m..net

Macro Definition Documentation

#define SCHEMA_ADD (   K,
 
)
Value:
({ \
co_obj_t *val = co_str8_create(V, sizeof(V), 0); \
if (!co_tree_insert(self, K, sizeof(K), val)) \
co_obj_free(val); \
})
int co_tree_insert(co_obj_t *root, const char *key, const size_t klen, co_obj_t *value)
insert object into given tree and associate with key
Definition: tree.c:332

Function Documentation

int co_profile_add ( const char *  name,
const size_t  nlen 
)

adds a new profile

Parameters
nameprofile name
nlenlength of profile name

References co_list_append().

158 {
159  co_obj_t *new_profile = _co_profile_create(name, nlen);
160  CHECK(_co_schemas_load(new_profile, _schemas), "Failed to initialize profile with schema.");
161  CHECK(co_list_append(_profiles, new_profile), "Failed to add profile to list.");
162 
163  return 1;
164 error:
165  co_obj_free(new_profile);
166  return 0;
167 }
int co_list_append(co_obj_t *list, co_obj_t *new_obj)
insert new item at end of list
Definition: list.c:425
Definition: obj.h:131
co_obj_t * name
Definition: cmd.h:60
void co_profile_dump ( co_obj_t profile)

dumps profile data

Parameters
profileprofile struct
int co_profile_export_file ( co_obj_t profile,
const char *  path 
)

exports a profile in memory to a file

Parameters
profileprofile struct
pathexport path

References co_tree_root().

679 {
680  CHECK(IS_PROFILE(profile),"Not a profile.");
681  int count = 0;
682  FILE *config_file = fopen(path, "wb");
683  CHECK(config_file != NULL, "Config file %s could not be opened", path);
684 
685  fprintf(config_file, "{\n");
686 
687  _co_profile_export_file_r(((co_profile_t*)profile)->data, co_tree_root(((co_profile_t*)profile)->data), &count, config_file);
688 
689  fprintf(config_file, "}");
690  fclose (config_file);
691  return 1;
692 error:
693  return 0;
694 }
_treenode_t * co_tree_root(const co_obj_t *tree)
return root node of tree object
Definition: tree.c:69
Definition: profile.h:69
co_obj_t* co_profile_find ( co_obj_t name)

searches the profile list for a specified profile

Parameters
nameprofile name (search key)

References co_list_parse().

Referenced by co_profile_remove().

625 {
626  CHECK(IS_STR(name), "Not a valid search index.");
627  co_obj_t *result = NULL;
628  CHECK((result = co_list_parse(_profiles, _co_profile_find_i, name)) != NULL, "Failed to find profile.");
629  return result;
630 error:
631  return NULL;
632 }
Definition: obj.h:131
co_obj_t * co_list_parse(co_obj_t *list, co_iter_t iter, void *context)
process list with given iterator function
Definition: list.c:233
co_obj_t* co_profile_get ( co_obj_t profile,
const co_obj_t key 
)

returns the key value (if an int) from the profile. If no value set, returns the default value

Parameters
profileprofile struct
keykey in profile
klenkey length

References co_tree_find().

467 {
468  CHECK(IS_PROFILE(profile),"Not a profile.");
469  CHECK_MEM(((co_profile_t*)profile)->data);
470  CHECK_MEM(key);
471  char *kstr = NULL;
472  size_t klen = co_obj_data(&kstr, key);
473  co_obj_t *obj = NULL;
474  CHECK((obj = co_tree_find(((co_profile_t*)profile)->data, kstr, klen)) != NULL, "Failed to find key %s.", kstr);
475  return obj;
476 
477 error:
478  return NULL;
479 }
Definition: obj.h:131
co_obj_t * co_tree_find(const co_obj_t *root, const char *key, const size_t klen)
return value from given tree that corresponds to key
Definition: tree.c:173
Definition: profile.h:69
double co_profile_get_float ( co_obj_t profile,
const char *  key,
const size_t  klen 
)

returns the key value (if a float) from the profile. If no value set, returns the default value

Parameters
profileprofile struct
keykey in profile
klenkey length

References co_tree_find().

584 {
585  CHECK(IS_PROFILE(profile),"Not a profile.");
586  CHECK_MEM(((co_profile_t*)profile)->data);
587  CHECK_MEM(key);
588  co_obj_t *obj = NULL;
589  CHECK((obj = co_tree_find(((co_profile_t*)profile)->data, key, klen)) != NULL, "Failed to find key %s.", key);
590  CHECK(IS_FLOAT(obj), "Object is not a floating point value.");
591  double *output;
592  CHECK(co_obj_data((char **)&output, obj) >= 0, "Failed to read data from %s.", key);
593  return *output;
594 
595 error:
596  return -1;
597 }
Definition: obj.h:131
co_obj_t * co_tree_find(const co_obj_t *root, const char *key, const size_t klen)
return value from given tree that corresponds to key
Definition: tree.c:173
Definition: profile.h:69
signed long co_profile_get_int ( co_obj_t profile,
const char *  key,
const size_t  klen 
)

returns the key value (if an int) from the profile. If no value set, returns the default value

Parameters
profileprofile struct
keykey in profile
klenkey length

References co_tree_find().

524 {
525  CHECK(IS_PROFILE(profile),"Not a profile.");
526  CHECK_MEM(((co_profile_t*)profile)->data);
527  CHECK_MEM(key);
528  co_obj_t *obj = NULL;
529  CHECK((obj = co_tree_find(((co_profile_t*)profile)->data, key, klen)) != NULL, "Failed to find key %s.", key);
530  CHECK(IS_INT(obj), "Object is not a signed integer.");
531  signed long *output;
532  CHECK(co_obj_data((char **)&output, obj) >= 0, "Failed to read data from %s.", key);
533  return *output;
534 
535 error:
536  return -1;
537 }
Definition: obj.h:131
co_obj_t * co_tree_find(const co_obj_t *root, const char *key, const size_t klen)
return value from given tree that corresponds to key
Definition: tree.c:173
Definition: profile.h:69
size_t co_profile_get_str ( co_obj_t profile,
char **  output,
const char *  key,
const size_t  klen 
)

returns the key value (if a string) from the profile. If no value set, returns the default value

Parameters
profileprofile struct
outputoutput buffer
keykey in profile
klenkey length

References co_tree_find().

Referenced by main().

496 {
497  CHECK(IS_PROFILE(profile),"Not a profile.");
498  CHECK_MEM(((co_profile_t*)profile)->data);
499  CHECK_MEM(key);
500  co_obj_t *obj = NULL;
501  CHECK((obj = co_tree_find(((co_profile_t*)profile)->data, key, klen)) != NULL, "Failed to find key %s.", key);
502  CHECK(IS_STR(obj), "Object is not a string.");
503  return co_obj_data((char **)output, obj);
504 
505 error:
506  return -1;
507 }
Definition: obj.h:131
co_obj_t * co_tree_find(const co_obj_t *root, const char *key, const size_t klen)
return value from given tree that corresponds to key
Definition: tree.c:173
Definition: profile.h:69
unsigned long co_profile_get_uint ( co_obj_t profile,
const char *  key,
const size_t  klen 
)

returns the key value (if an unsigned int) from the profile. If no value set, returns the default value

Parameters
profileprofile struct
keykey in profile
klenkey length

References co_tree_find().

554 {
555  CHECK(IS_PROFILE(profile),"Not a profile.");
556  CHECK_MEM(((co_profile_t*)profile)->data);
557  CHECK_MEM(key);
558  co_obj_t *obj = NULL;
559  CHECK((obj = co_tree_find(((co_profile_t*)profile)->data, key, klen)) != NULL, "Failed to find key %s.", key);
560  CHECK(IS_UINT(obj), "Object is not an unsigned integer.");
561  unsigned long *output;
562  CHECK(co_obj_data((char **)&output, obj) >= 0, "Failed to read data from %s.", key);
563  return *output;
564 
565 error:
566  return -1;
567 }
Definition: obj.h:131
co_obj_t * co_tree_find(const co_obj_t *root, const char *key, const size_t klen)
return value from given tree that corresponds to key
Definition: tree.c:173
Definition: profile.h:69
int co_profile_import_files ( const char *  path)

imports available profiles from profiles directory

Parameters
pathfile path to the profiles directory

References process_files().

Referenced by main().

348  {
349  DEBUG("Importing files from %s", path);
350  CHECK(process_files(path, _co_profile_import_files_i), "Failed to load all profiles.");
351 
352  return 1;
353 
354 error:
355  return 0;
356 }
int process_files(const char *dir_path, file_iter loader)
processes file paths
Definition: util.c:145
int co_profile_import_global ( const char *  path)

imports global profile

Parameters
pathfile path to the global profile

References co_profile_set_str().

Referenced by main().

358  {
359  int ret = 0;
360  FILE *config_file = NULL;
361  jsmntok_t *tokens = NULL;
362 
363  if(_profile_global == NULL)
364  {
365  _profile_global = _co_profile_create("global", sizeof("global"));
366  }
367  _co_schemas_load(_profile_global, _schemas_global);
368 
369  DEBUG("Importing file at path %s", path);
370 
371  config_file = fopen(path, "rb");
372  CHECK(config_file != NULL, "File %s could not be opened", path);
373  fseek(config_file, 0, SEEK_END);
374  long fsize = ftell(config_file);
375  rewind(config_file);
376  char *buffer = h_calloc(1, fsize + 1);
377  CHECK(fread(buffer, fsize, 1, config_file) != 0, "Failed to read from file.");
378  fclose(config_file);
379  config_file = NULL;
380 
381  buffer[fsize] = '\0';
382  tokens = _co_json_string_tokenize(buffer);
383 
384  typedef enum { START, KEY, VALUE, STOP } parse_state;
385  parse_state state = START;
386 
387  size_t object_tokens = 0;
388  char *key = NULL;
389  size_t klen = 0;
390 
391  for (size_t i = 0, j = 1; j > 0; i++, j--)
392  {
393  jsmntok_t *t = &tokens[i];
394 
395  // Should never reach uninitialized tokens
396  CHECK(t->start != -1 && t->end != -1, "Tokens uninitialized.");
397 
398  if (t->type == JSMN_ARRAY || t->type == JSMN_OBJECT)
399  j += t->size;
400 
401  switch (state)
402  {
403  case START:
404  CHECK(t->type == JSMN_OBJECT, "Invalid root element.");
405 
406  state = KEY;
407  object_tokens = t->size;
408 
409  if (object_tokens == 0)
410  state = STOP;
411 
412  CHECK(object_tokens % 2 == 0, "Object must have even number of children.");
413  break;
414 
415  case KEY:
416  object_tokens--;
417 
418  CHECK(t->type == JSMN_STRING, "Keys must be strings.");
419  state = VALUE;
420  key = _co_json_token_stringify(buffer, t);
421  klen = t->end - t->start;
422 
423  break;
424 
425  case VALUE:
426  CHECK(t->type == JSMN_STRING, "Values must be strings.");
427 
428  if(key != NULL && klen > 0)
429  {
430  if(!co_profile_set_str(_profile_global, key, klen + 1, _co_json_token_stringify(buffer, t), t->end - t->start + 1))
431  {
432  INFO("Value not in schema.");
433  }
434 
435  }
436 
437  key = NULL;
438  klen = 0;
439  object_tokens--;
440  state = KEY;
441 
442  if (object_tokens == 0)
443  state = STOP;
444 
445  break;
446 
447  case STOP:
448  // Just consume the tokens
449  break;
450 
451  default:
452  SENTINEL("Invalid state %u", state);
453  }
454  }
455 
456  ret = 1;
457 
458 error:
459  if(config_file != NULL) fclose(config_file);
460  if (buffer) h_free(buffer);
461  if (tokens) h_free(tokens);
462  return ret;
463 }
Definition: jsmn.h:35
int co_profile_set_str(co_obj_t *profile, const char *key, const size_t klen, const char *value, const size_t vlen)
sets a specified profile value (if a string)
Definition: profile.c:482
int co_profile_remove ( const char *  name,
const size_t  nlen 
)

removes profile with given name

Parameters
nameprofile name
nlenlength of profile name

References co_list_delete(), and co_profile_find().

143 {
144  co_obj_t *n = co_str8_create(name, nlen, 0);
145  co_obj_t *prof = co_profile_find(n);
146  prof = co_list_delete(_profiles, prof);
147  CHECK(prof != NULL, "Failed to remove profile.");
148 
149  co_obj_free(n);
150  return 1;
151 error:
152  co_obj_free(n);
153  return 0;
154 }
co_obj_t * co_profile_find(co_obj_t *name)
searches the profile list for a specified profile
Definition: profile.c:624
co_obj_t * co_list_delete(co_obj_t *list, co_obj_t *item)
delete specified item from list
Definition: list.c:457
Definition: obj.h:131
co_obj_t * name
Definition: cmd.h:60
int co_profile_set_float ( co_obj_t profile,
const char *  key,
const size_t  klen,
const double  value 
)

sets a specified profile value (if a float)

Parameters
profileprofile struct
keykey in profile
klenkey length
valuekey's value

References co_tree_set_float().

571 {
572  CHECK(IS_PROFILE(profile),"Not a profile.");
573  CHECK(co_tree_set_float(((co_profile_t*)profile)->data, key, klen, value),
574  "No corresponding key %s in schema, can't set %s:%lf",
575  key, key, value);
576  return 1;
577 
578 error:
579  return 0;
580 }
int co_tree_set_float(co_obj_t *root, const char *key, const size_t klen, const double value)
set value contained in an object in the tree with a specified key (if a float)
Definition: tree.c:524
Definition: profile.h:69
int co_profile_set_int ( co_obj_t profile,
const char *  key,
const size_t  klen,
const signed long  value 
)

sets a specified profile value (if an int)

Parameters
profileprofile struct
keykey in profile
klenkey length
valuekey's value

References co_tree_set_int().

511 {
512  CHECK(IS_PROFILE(profile),"Not a profile.");
513  CHECK(co_tree_set_int(((co_profile_t*)profile)->data, key, klen, value),
514  "No corresponding key %s in schema, can't set %s:%ld",
515  key, key, value);
516  return 1;
517 
518 error:
519  return 0;
520 }
int co_tree_set_int(co_obj_t *root, const char *key, const size_t klen, const signed long value)
set value contained in an object in the tree with a specified key (if an int)
Definition: tree.c:449
Definition: profile.h:69
int co_profile_set_str ( co_obj_t profile,
const char *  key,
const size_t  klen,
const char *  value,
const size_t  vlen 
)

sets a specified profile value (if a string)

Parameters
profileprofile struct
keykey in profile
klenkey length
valuekey's value
vlenvalue length

References co_tree_set_str().

Referenced by co_profile_import_global().

483 {
484  CHECK(IS_PROFILE(profile),"Not a profile.");
485  CHECK(co_tree_set_str(((co_profile_t*)profile)->data, key, klen, value, vlen),
486  "No corresponding key %s in schema, can't set %s:%s",
487  key, key, value);
488  return 1;
489 
490 error:
491  return 0;
492 }
int co_tree_set_str(co_obj_t *root, const char *key, const size_t klen, const char *value, const size_t vlen)
set value contained in an object in the tree with a specified key (if a string)
Definition: tree.c:408
Definition: profile.h:69
int co_profile_set_uint ( co_obj_t profile,
const char *  key,
const size_t  klen,
const unsigned long  value 
)

sets a specified profile value (if an unsigned int)

Parameters
profileprofile struct
keykey in profile
klenkey length
valuekey's value

References co_tree_set_uint().

541 {
542  CHECK(IS_PROFILE(profile),"Not a profile.");
543  CHECK(co_tree_set_uint(((co_profile_t*)profile)->data, key, klen, value),
544  "No corresponding key %s in schema, can't set %s:%lu",
545  key, key, value);
546  return 1;
547 
548 error:
549  return 0;
550 }
int co_tree_set_uint(co_obj_t *root, const char *key, const size_t klen, const unsigned long value)
set value contained in an object in the tree with a specified key (if an unsigned int) ...
Definition: tree.c:490
Definition: profile.h:69
int co_profiles_create ( const size_t  index_size)

create global profiles list

Parameters
index_sizesize of index for profiles list (16 or 32 bits)
co_obj_t* co_profiles_process ( co_iter_t  iter,
void *  context 
)

processes all loaded profiles with specified iterator function

Parameters
iteriterator function callback
contextadditional parameters for iterator

References co_list_parse().

698 {
699  return co_list_parse(_profiles, iter, context);
700 }
co_obj_t * co_list_parse(co_obj_t *list, co_iter_t iter, void *context)
process list with given iterator function
Definition: list.c:233
int co_schema_register ( co_cb_t  cb)

register a callback for populating a profile schema

Parameters
cbschema callback

References co_list_append().

71 {
72  DEBUG("Registering schema.");
73  CHECK(co_list_append(_schemas, _co_schema_create(cb)), "Failed to register schema.");
74  return 1;
75 error:
76  return 0;
77 }
int co_list_append(co_obj_t *list, co_obj_t *new_obj)
insert new item at end of list
Definition: list.c:425
int co_schema_register_global ( co_cb_t  cb)

register a callback for populating global profile

Parameters
cbschema callback

References co_list_append().

81 {
82  DEBUG("Registering global schema.");
83  CHECK(co_list_append(_schemas_global, _co_schema_create(cb)), "Failed to register schema.");
84  return 1;
85 error:
86  return 0;
87 }
int co_list_append(co_obj_t *list, co_obj_t *new_obj)
insert new item at end of list
Definition: list.c:425
int co_schemas_load ( co_obj_t profile)

load schemas for specified profile

Parameters
profileprofile to load schemas for

Variable Documentation

co_obj_t* name

command name