File:  [ELWIX - Embedded LightWeight unIX -] / libaitcfg / src / queue.c
Revision 1.18: download - view: text, annotated - select for diffs - revision graph
Thu Dec 5 14:33:35 2019 UTC (4 years, 5 months ago) by misho
Branches: MAIN
CVS tags: cfg8_2, HEAD, CFG8_1
ver 8.1

    1: /*************************************************************************
    2: * (C) 2008 AITNET ltd - Sofia/Bulgaria - <misho@aitbg.com>
    3: *  by Michael Pounov <misho@openbsd-bg.org>
    4: *
    5: * $Author: misho $
    6: * $Id: queue.c,v 1.18 2019/12/05 14:33:35 misho Exp $
    7: *
    8: **************************************************************************
    9: The ELWIX and AITNET software is distributed under the following
   10: terms:
   11: 
   12: All of the documentation and software included in the ELWIX and AITNET
   13: Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org>
   14: 
   15: Copyright 2004 - 2019
   16: 	by Michael Pounov <misho@elwix.org>.  All rights reserved.
   17: 
   18: Redistribution and use in source and binary forms, with or without
   19: modification, are permitted provided that the following conditions
   20: are met:
   21: 1. Redistributions of source code must retain the above copyright
   22:    notice, this list of conditions and the following disclaimer.
   23: 2. Redistributions in binary form must reproduce the above copyright
   24:    notice, this list of conditions and the following disclaimer in the
   25:    documentation and/or other materials provided with the distribution.
   26: 3. All advertising materials mentioning features or use of this software
   27:    must display the following acknowledgement:
   28: This product includes software developed by Michael Pounov <misho@elwix.org>
   29: ELWIX - Embedded LightWeight unIX and its contributors.
   30: 4. Neither the name of AITNET nor the names of its contributors
   31:    may be used to endorse or promote products derived from this software
   32:    without specific prior written permission.
   33: 
   34: THIS SOFTWARE IS PROVIDED BY AITNET AND CONTRIBUTORS ``AS IS'' AND
   35: ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   36: IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   37: ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   38: FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   39: DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   40: OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   41: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   42: LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   43: OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   44: SUCH DAMAGE.
   45: */
   46: #include "global.h"
   47: 
   48: 
   49: static inline struct tagCfg *
   50: _selectAttribute(cfg_root_t * __restrict cfg, const char *csSec, const char *csAttr)
   51: {
   52: 	struct tagCfg fav, *c;
   53: 
   54: 	if (!cfg)
   55: 		return NULL;
   56: 	else
   57: 		memset(&fav, 0, sizeof fav);
   58: 
   59: 	if (csSec && *csSec)
   60: 		AIT_KEY(&fav.cfg_sec) = crcFletcher16((u_short*) csSec, 
   61: 				E_ALIGN(strlen(csSec), 2) / 2);
   62: 	if (csAttr)
   63: 		AIT_KEY(&fav.cfg_attr) = crcFletcher16((u_short*) csAttr, 
   64: 				E_ALIGN(strlen(csAttr), 2) / 2);
   65: 
   66: 	if (!csAttr)
   67: 		return RB_NFIND(tagRC, cfg, &fav);
   68: 	else {
   69: 		c = RB_FIND(tagRC, cfg, &fav);
   70: 		if (!c)
   71: 			return NULL;	/* not found */
   72: 		do {
   73: 			if (!strcmp(AIT_GET_STR(&c->cfg_attr), csAttr))
   74: 				return c;	/* FOUND! */
   75: 		} while ((c = RB_NEXT(tagRC, cfg, c)) && c && !cfg_tree_cmp(c, &fav));
   76: 		return NULL;	/* not found */
   77: 	}
   78: }
   79: 
   80: /* --------------------------------------------------------------- */
   81: 
   82: /*
   83:  * cfg_dumpCfg() - dump config data
   84:  *
   85:  * @cfg = Config root
   86:  * return: none
   87:  */
   88: void
   89: cfg_dumpCfg(cfg_root_t * __restrict cfg)
   90: {
   91: 	struct tagCfg *r, *c, *ctmp, *q, *qtmp;
   92: 	int syn;
   93: 
   94: 	r = RB_ROOT(cfg);
   95: 	printf("ROOT:: KEY=%.8x [%s] %s=%s\n", ((AIT_KEY(&r->cfg_sec) << 15) | AIT_KEY(&r->cfg_attr)), 
   96: 			AIT_ADDR(&r->cfg_sec), AIT_ADDR(&r->cfg_attr), AIT_ADDR(&r->cfg_val));
   97: 
   98: 	RB_FOREACH_SAFE(c, tagRC, cfg, ctmp) {
   99: 		syn ^= syn;
  100: 		TAILQ_FOREACH_SAFE(q, cfg, cfg_next, qtmp) {
  101: 			if (c == q) {
  102: 				syn = 42;
  103: 				break;
  104: 			}
  105: 		}
  106: 
  107: 		printf("%s KEY=%.8x [%s] %s=%s sync=%d\n", c == r ? "*" : "", 
  108: 				((AIT_KEY(&c->cfg_sec) << 15) | AIT_KEY(&c->cfg_attr)), 
  109: 				AIT_ADDR(&c->cfg_sec), AIT_ADDR(&c->cfg_attr), AIT_ADDR(&c->cfg_val), syn);
  110: 	}
  111: }
  112: 
  113: /*
  114:  * cfg_getSection() - Get entire section attributes into array
  115:  *
  116:  * @cfg = Config root
  117:  * @csSec = Config section //[{csSec}]
  118:  * return: NULL not found or !=NULL allocated array, must free with array_Destroy() after use!
  119:  */
  120: array_t *
  121: cfg_getSection(cfg_root_t * __restrict cfg, const char *csSec)
  122: {
  123: 	array_t *arr = NULL;
  124: 	struct tagCfg *av, fav;
  125: 
  126: 	if (!cfg) {
  127: 		cfg_SetErr(EINVAL, "Invalid argument(s)");
  128: 		return NULL;
  129: 	} else
  130: 		memset(&fav, 0, sizeof fav);
  131: 	if (csSec && !*csSec)
  132: 		csSec = NULL;
  133: 
  134: 	if (csSec && *csSec)
  135: 		AIT_KEY(&fav.cfg_sec) = crcFletcher16((u_short*) csSec, 
  136: 				E_ALIGN(strlen(csSec), 2) / 2);
  137: 
  138: 	arr = array_Init(0);
  139: 	if (!arr) {
  140: 		cfg_SetErr(elwix_GetErrno(), "%s", elwix_GetError());
  141: 		return NULL;
  142: 	}
  143: 
  144: 	TAILQ_FOREACH(av, cfg, cfg_next)
  145: 		if (AIT_KEY(&av->cfg_sec) == AIT_KEY(&fav.cfg_sec)) {
  146: 			if (!csSec) {
  147: 				if (AIT_ISEMPTY(&av->cfg_sec))
  148: 					array_Push(arr, av, 0);
  149: 			} else {
  150: 				if (!AIT_ISEMPTY(&av->cfg_sec) && 
  151: 						!strcmp(AIT_GET_STR(&av->cfg_sec), csSec))
  152: 					array_Push(arr, av, 0);
  153: 			}
  154: 		}
  155: 
  156: 	if (!array_Size(arr))
  157: 		array_Destroy(&arr);
  158: 
  159: 	return arr;
  160: }
  161: 
  162: /*
  163:  * cfg_findAttribute() - Find attribute position in config file
  164:  *
  165:  * @cfg = Config root
  166:  * @csSec = Config section //[{csSec}]
  167:  * @csAttr = Config attribute //{csAttr} = ..., if NULL as *any* attribute
  168:  * return: 0 not found item, -1 error or >0 position in list
  169:  */
  170: int
  171: cfg_findAttribute(cfg_root_t * __restrict cfg, const char *csSec, const char *csAttr)
  172: {
  173: 	struct tagCfg *av, fav;
  174: 	register int cx = 0;
  175: 
  176: 	if (!cfg) {
  177: 		cfg_SetErr(EINVAL, "Invalid argument(s)");
  178: 		return -1;
  179: 	} else
  180: 		memset(&fav, 0, sizeof fav);
  181: 
  182: 	if (csSec && *csSec)
  183: 		AIT_KEY(&fav.cfg_sec) = crcFletcher16((u_short*) csSec, 
  184: 				E_ALIGN(strlen(csSec), 2) / 2);
  185: 	if (csAttr)
  186: 		AIT_KEY(&fav.cfg_attr) = crcFletcher16((u_short*) csAttr, 
  187: 				E_ALIGN(strlen(csAttr), 2) / 2);
  188: 
  189: 	TAILQ_FOREACH(av, cfg, cfg_next) {
  190: 		++cx;
  191: 		if (!cfg_tree_cmp(&fav, av))
  192: 			return cx;
  193: 	}
  194: 
  195: 	return 0;
  196: }
  197: 
  198: /*
  199:  * cfg_unsetAttribute() - Unset item from config and free resources
  200:  *
  201:  * @cfg = Config root
  202:  * @csSec = Config section //[{csSec}], if NULL unset in *default* section
  203:  * @csAttr = Config attribute //{csAttr} = ..., if NULL as *any* attribute
  204:  * return: 0 item not found, -1 error or 1 removed item
  205:  */
  206: int
  207: cfg_unsetAttribute(cfg_root_t * __restrict cfg, const char *csSec, const char *csAttr)
  208: {
  209: 	struct tagCfg *av;
  210: 
  211: 	if (!cfg)
  212: 		return -1;
  213: 
  214: 	av = _selectAttribute(cfg, csSec, csAttr);
  215: 	if (!av)
  216: 		return 0;
  217: 
  218: 	CFG_RC_LOCK(cfg);
  219: 	RB_REMOVE(tagRC, cfg, av);
  220: 	TAILQ_REMOVE(cfg, av, cfg_next);
  221: 	CFG_RC_UNLOCK(cfg);
  222: 
  223: 	AIT_FREE_VAL(&av->cfg_val);
  224: 	AIT_FREE_VAL(&av->cfg_attr);
  225: 	AIT_FREE_VAL(&av->cfg_sec);
  226: 	e_free(av);
  227: 	return 1;
  228: }
  229: 
  230: /*
  231:  * cfg_setAttribute() - Set item in config or adding new item if not exists
  232:  *
  233:  * @cfg = Config root
  234:  * @csSec = Config section //[{csSec}], if NULL set in *default* section
  235:  * @csAttr = Config attribute //{csAttr} = ...
  236:  * @csVal = Config value //... = {csVal} to setup
  237:  * return: 0 nothing changed, -1 error, 1 found and updated item or 2 added new item
  238:  */
  239: int
  240: cfg_setAttribute(cfg_root_t * __restrict cfg, const char *csSec, const char *csAttr, const char *csVal)
  241: {
  242: 	struct tagCfg *av, *section;
  243: 
  244: 	if (!cfg || !csAttr)
  245: 		return -1;
  246: 
  247: 	av = _selectAttribute(cfg, csSec, csAttr);
  248: 	if (!av) {
  249: 		/* adding new element */
  250: 		section = _selectAttribute(cfg, csSec, NULL);
  251: 
  252: 		av = e_malloc(sizeof(struct tagCfg));
  253: 		if (!av) {
  254: 			LOGERR;
  255: 			return -1;
  256: 		} else {
  257: 			memset(av, 0, sizeof(struct tagCfg));
  258: 
  259: 			CFG_RC_LOCK(cfg);
  260: 			if (!section)
  261: 				TAILQ_INSERT_TAIL(cfg, av, cfg_next);
  262: 			else
  263: 				TAILQ_INSERT_BEFORE(section, av, cfg_next);
  264: 			CFG_RC_UNLOCK(cfg);
  265: 		}
  266: 
  267: 		if (csSec && *csSec) {
  268: 			AIT_SET_STR(&av->cfg_sec, csSec);
  269: 			AIT_KEY(&av->cfg_sec) = crcFletcher16(AIT_GET_LIKE(&av->cfg_sec, u_short*), 
  270: 					E_ALIGN(AIT_LEN(&av->cfg_sec) - 1, 2) / 2);
  271: 		}
  272: 		AIT_SET_STR(&av->cfg_val, csVal ? csVal : "");
  273: 		AIT_SET_STR(&av->cfg_attr, csAttr);
  274: 		AIT_KEY(&av->cfg_attr) = crcFletcher16(AIT_GET_LIKE(&av->cfg_attr, u_short*), 
  275: 				E_ALIGN(AIT_LEN(&av->cfg_attr) - 1, 2) / 2);
  276: 
  277: 		CFG_RC_LOCK(cfg);
  278: 		RB_INSERT(tagRC, cfg, av);
  279: 		CFG_RC_UNLOCK(cfg);
  280: 		return 2;
  281: 	}
  282: 
  283: 	if (csVal && AIT_ADDR(&av->cfg_val) && 
  284: 			strcmp((char*) csVal, (char*) AIT_GET_STR(&av->cfg_val))) {
  285: 		/* Update element */
  286: 		AIT_FREE_VAL(&av->cfg_val);
  287: 		AIT_SET_STR(&av->cfg_val, csVal);
  288: 		return 1;
  289: 	}
  290: 
  291: 	/* Nothing happens ... found & values is equal! */
  292: 	return 0;
  293: }
  294: 
  295: /*
  296:  * cfg_getAttribute() - Get item from config and return value from it
  297:  *
  298:  * @cfg = Config root
  299:  * @csSec = Config section //[{csSec}], if NULL unset in *default* section
  300:  * @csAttr = Config attribute //{csAttr} = ..., if NULL as *any* attribute
  301:  * return: NULL item not found or null parameters, !=NULL value const string
  302:  */
  303: const char *
  304: cfg_getAttribute(cfg_root_t * __restrict cfg, const char *csSec, const char *csAttr)
  305: {
  306: 	struct tagCfg *av;
  307: 
  308: 	if (!cfg)
  309: 		return NULL;
  310: 
  311: 	av = _selectAttribute(cfg, csSec, csAttr);
  312: 	if (!av)
  313: 		return NULL;
  314: 
  315: 	return AIT_GET_STR(&av->cfg_val);
  316: }
  317: 
  318: /*
  319:  * cfg_getAttributeLong() - Get item as long from config and return value from it
  320:  *
  321:  * @cfg = Config root
  322:  * @csSec = Config section //[{csSec}], if NULL unset in *default* section
  323:  * @csAttr = Config attribute //{csAttr} = ..., if NULL as *any* attribute
  324:  * return: value
  325:  */
  326: long
  327: cfg_getAttributeLong(cfg_root_t * __restrict cfg, const char *csSec, const char *csAttr)
  328: {
  329: 	const char *str = NULL;
  330: 
  331: 	str = cfg_getAttribute(cfg, csSec, csAttr);
  332: 	return strtol(str ? str : "", NULL, 0);
  333: }
  334: 
  335: /*
  336:  * cfg_getAttributeLLong() - Get item as long long from config and return value from it
  337:  *
  338:  * @cfg = Config root
  339:  * @csSec = Config section //[{csSec}], if NULL unset in *default* section
  340:  * @csAttr = Config attribute //{csAttr} = ..., if NULL as *any* attribute
  341:  * return: value
  342:  */
  343: long long
  344: cfg_getAttributeLLong(cfg_root_t * __restrict cfg, const char *csSec, const char *csAttr)
  345: {
  346: 	const char *str = NULL;
  347: 
  348: 	str = cfg_getAttribute(cfg, csSec, csAttr);
  349: 	return strtoll(str ? str : "", NULL, 0);
  350: }
  351: 
  352: /*
  353:  * cfg_getAttributeDouble() - Get item as double from config and return value from it
  354:  *
  355:  * @cfg = Config root
  356:  * @csSec = Config section //[{csSec}], if NULL unset in *default* section
  357:  * @csAttr = Config attribute //{csAttr} = ..., if NULL as *any* attribute
  358:  * return: value
  359:  */
  360: double
  361: cfg_getAttributeDouble(cfg_root_t * __restrict cfg, const char *csSec, const char *csAttr)
  362: {
  363: 	const char *str = NULL;
  364: 
  365: 	str = cfg_getAttribute(cfg, csSec, csAttr);
  366: 	return strtod(str ? str : "", NULL);
  367: }
  368: 
  369: /*
  370:  * cfg_getAttributeLDouble() - Get item as long double from config and return value from it
  371:  *
  372:  * @cfg = Config root
  373:  * @csSec = Config section //[{csSec}], if NULL unset in *default* section
  374:  * @csAttr = Config attribute //{csAttr} = ..., if NULL as *any* attribute
  375:  * return: value
  376:  */
  377: long double
  378: cfg_getAttributeLDouble(cfg_root_t * __restrict cfg, const char *csSec, const char *csAttr)
  379: {
  380: 	const char *str = NULL;
  381: 
  382: 	str = cfg_getAttribute(cfg, csSec, csAttr);
  383: 	return strtold(str ? str : "", NULL);
  384: }
  385: 
  386: /*
  387:  * cfg_loadAttribute() - Get guarded attribute, if not found item return *default value*
  388:  *
  389:  * @cfg = Config root
  390:  * @csSec = Config section //[{csSec}], if NULL unset in *default* section
  391:  * @csAttr = Config attribute //{csAttr} = ..., if NULL as *any* attribute
  392:  * @val = Return buffer for item Value //... = {val}
  393:  * @csDefValue = *Default Value* for return in //{val}, if not found item in config
  394:  * return: 0 item not found, -1 error or >0 number of copied bytes in //{val}
  395:  */
  396: int
  397: cfg_loadAttribute(cfg_root_t * __restrict cfg, const char *csSec, const char *csAttr, 
  398: 		ait_val_t * __restrict val, const char *csDefValue)
  399: {
  400: 	struct tagCfg *av;
  401: 	int ret = 0;
  402: 
  403: 	if (!cfg || !val) {
  404: 		cfg_SetErr(EINVAL, "Invalid argument(s)");
  405: 		return -1;
  406: 	}
  407: 
  408: 	AIT_INIT_VAL(val);
  409: 	av = _selectAttribute(cfg, csSec, csAttr);
  410: 	if (!av) {
  411: 		/* not found item */
  412: 		if (csDefValue) {
  413: 			AIT_SET_STR(val, csDefValue);
  414: 			ret = AIT_LEN(val);
  415: 		} else
  416: 			AIT_INIT_VAL(val);
  417: 		return ret;
  418: 	}
  419: 
  420: 	if (AIT_ISEMPTY(&av->cfg_val) || !AIT_ADDR(&av->cfg_val) || 
  421: 			!*AIT_GET_LIKE(&av->cfg_val, char*)) {
  422: 		/* empty value */
  423: 		if (csDefValue) {
  424: 			AIT_SET_STR(val, csDefValue);
  425: 			ret = AIT_LEN(val);
  426: 		} else
  427: 			AIT_INIT_VAL(val);
  428: 	} else {
  429: 		/* copy value */
  430: 		AIT_SET_STR(val, AIT_GET_STR(&av->cfg_val));
  431: 		ret = AIT_LEN(val);
  432: 	}
  433: 
  434: 	return ret;
  435: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>