Beispiel #1
0
char * elektraMetaArrayToString (Key * key, const char * metaName, const char * delim)
{
	char * result = NULL;
	Key * lookupElem = keyDup (keyGetMeta (key, metaName));
	keyAddBaseName (lookupElem, "#0");
	Key * elem = (Key *)keyGetMeta (key, keyName (lookupElem));
	if (elem != NULL)
	{
		elektraRealloc ((void **)&result, keyGetValueSize (elem));
		snprintf (result, keyGetValueSize (elem), "%s", keyString (elem));
	}
	elektraArrayIncName (lookupElem);
	elem = (Key *)keyGetMeta (key, keyName (lookupElem));
	while (elem != NULL)
	{
		elektraRealloc ((void **)&result,
				elektraStrLen (result) + keyGetValueSize (elem) + 1); // String (incl. +2 times \0) + delimiter + whitespace
		strcat (result, delim);
		strcat (result, keyString (elem));
		elektraArrayIncName (lookupElem);
		elem = (Key *)keyGetMeta (key, keyName (lookupElem));
	}
	keyDel (lookupElem);
	return result;
}
Beispiel #2
0
KeySet * elektraMetaArrayToKS (Key * key, const char * metaName)
{
	const Key * meta = keyGetMeta (key, metaName);
	if (!meta) return NULL;

	KeySet * result = ksNew (0, KS_END);

	if (keyString (meta)[0] != '#')
	{
		ksAppendKey (result, (Key *)meta);
		ksRewind (result);
		return result;
	}
	ksAppendKey (result, keyDup (meta));
	Key * currentKey = keyDup (meta);
	keyAddName (currentKey, "#");
	elektraArrayIncName (currentKey);
	Key * curMeta = NULL;
	while ((curMeta = (Key *)keyGetMeta (key, keyName (currentKey))) != NULL)
	{
		ksAppendKey (result, keyDup (curMeta));
		elektraArrayIncName (currentKey);
	}
	keyDel (currentKey);
	ksRewind (result);
	return result;
}
Beispiel #3
0
static void test_noArray (void)
{
	printf ("Test no array\n");
	Key * k = keyNew ("user/noarray", KEY_END);

	succeed_if (elektraArrayIncName (0) == -1, "null pointer");
	succeed_if (elektraArrayIncName (k) == -1, "no array");

	keyDel (k);
}
Beispiel #4
0
static void test_startArray (void)
{
	printf ("Test start array\n");
	Key * k = keyNew ("user/startarray/#", KEY_END);

	succeed_if (elektraArrayIncName (k) == 0, "no array start");
	succeed_if_same_string (keyName (k), "user/startarray/#0");
	succeed_if (elektraArrayIncName (k) == 0, "no array inc");
	succeed_if_same_string (keyName (k), "user/startarray/#1");

	keyDel (k);
}
Beispiel #5
0
int elektraLineRead (FILE * fp, KeySet * returned)
{
    char * value = NULL;
    size_t len = 0;
    ssize_t n = 0;
    Key * read = NULL;

    // Read in each line
    while ((n = getline (&value, &len, fp)) != -1)
    {
        // Remove trailing newline
        if (value[n - 1] == '\n')
        {
            value[n - 1] = '\0';
        }
        read = keyDup (ksTail (returned));
        if (elektraArrayIncName (read) == -1)
        {
            elektraFree (value);
            keyDel (read);
            return -1;
        }
        keySetString (read, value);

        ksAppendKey (returned, read);
    }
    elektraFree (value);

    return 1;
}
Beispiel #6
0
/**
 @retval 0 if ksCurrent does not hold an array entry
 @retval 1 if the array entry will be used because its the first
 @retval 2 if a new array entry was created
 @retval -1 error in snprintf
 */
static int elektraYajlIncrementArrayEntry (KeySet * ks)
{
	Key * current = ksCurrent (ks);
	const char * baseName = keyBaseName (current);

	if (baseName && *baseName == '#')
	{
		current = keyNew (keyName (current), KEY_END);
		if (!strcmp (baseName, "###empty_array"))
		{
			// get rid of previous key
			keyDel (ksLookup (ks, current, KDB_O_POP));
			// we have a new array entry
			keySetBaseName (current, 0);
			keyAddName (current, "#0");
			ksAppendKey (ks, current);
			return 1;
		}
		else
		{
			// we are in an array
			elektraArrayIncName (current);
			ksAppendKey (ks, current);
			return 2;
		}
	}
	else
	{
		// previous entry indicates this is not an array
		return 0;
	}
}
Beispiel #7
0
/**
 * @internal
 * Remove plugin at all placements from list plugin configuration and apply it.
 *
 * @param  list   List plugin
 * @param  plugin Plugin to remove
 * @retval 0 on error
 * @retval 1 on success
 */
static int listRemovePlugin (Plugin * list, Plugin * plugin)
{
	ELEKTRA_NOT_NULL (list);
	ELEKTRA_NOT_NULL (plugin);

	KeySet * newConfig = ksDup (list->config);

	Key * configBase = keyNew ("user/plugins", KEY_END);
	KeySet * array = elektraArrayGet (configBase, newConfig);

	// Find the plugin with our handle
	Key * current;
	ksRewind (array);
	while ((current = ksNext (array)) != NULL)
	{
		Key * handleLookup = keyDup (current);
		keyAddBaseName (handleLookup, "handle");
		Key * handle = ksLookup (newConfig, handleLookup, 0);
		keyDel (handleLookup);

		if (handle)
		{
			Plugin * handleValue = (*(Plugin **) keyValue (handle));
			if (handleValue == plugin)
			{
				// Remove plugin configuration
				KeySet * cut = ksCut (newConfig, current);
				ksDel (cut);
			}
		}
	}
	ksDel (array);

	// Renumber array items
	KeySet * sourceArray = elektraArrayGet (configBase, newConfig);
	Key * renumberBase = keyNew ("user/plugins/#", KEY_END);
	ksRewind (sourceArray);
	while ((current = ksNext (sourceArray)) != NULL)
	{
		// Create new array item base name e.g. "user/plugins/#0"
		elektraArrayIncName (renumberBase);
		moveKeysRecursive (keyName (current), keyName (renumberBase), newConfig);
	}

	keyDel (configBase);
	keyDel (renumberBase);
	ksDel (sourceArray);
	ksDel (list->config);

	// Apply new configuration
	list->config = newConfig;
	list->kdbOpen (list, NULL);

	return 1;
}
Beispiel #8
0
/**
 *
 * Return the next key in the given array.
 * The function will automatically allocate memory
 * for a new key and name it accordingly.
 *
 * @pre The supplied keyset must contain only valid array keys.
 *
 * The caller has to keyDel the resulting key.
 *
 * @param arraykeys the array where the new key will belong to
 *
 * @return the new array key on success
 * @retval NULL if the passed array is empty
 * @retval NULL on NULL pointers or if an error occurs
 */
Key *elektraArrayGetNextKey(KeySet *arrayKeys)
{
	if (!arrayKeys) return 0;

	Key *last = ksPop(arrayKeys);

	if (!last) return 0;

	ksAppendKey(arrayKeys, last);
	Key *newKey = keyDup(last);
	int ret = elektraArrayIncName(newKey);

	if (ret == -1)
	{
		keyDel(newKey);
		return 0;
	}

	return newKey;
}
Beispiel #9
0
void elektraMetaArrayAdd (Key * key, const char * metaName, const char * value)
{
	const Key * meta = keyGetMeta (key, metaName);
	Key * arrayKey;
	if (!meta)
	{
		keySetMeta (key, metaName, "#0");
		arrayKey = keyDup (keyGetMeta (key, metaName));
		keySetString (arrayKey, 0);
		keyAddBaseName (arrayKey, "#");
	}
	else
	{
		arrayKey = keyDup (meta);
		keyAddBaseName (arrayKey, keyString (meta));
	}
	elektraArrayIncName (arrayKey);
	keySetMeta (key, keyName (arrayKey), value);
	keySetMeta (key, metaName, keyBaseName (arrayKey));
	keyDel (arrayKey);
}
Beispiel #10
0
static void test_array (void)
{
	printf ("Test array\n");

	Key * k = keyNew ("user/array/#0", KEY_END);
	succeed_if (!elektraArrayIncName (k), "increment array entry name returned error");
	succeed_if_same_string (keyName (k), "user/array/#1");
	succeed_if (!elektraArrayIncName (k), "increment array entry name returned error");
	succeed_if_same_string (keyName (k), "user/array/#2");
	succeed_if (!elektraArrayIncName (k), "increment array entry name returned error");
	succeed_if_same_string (keyName (k), "user/array/#3");
	succeed_if (!elektraArrayIncName (k), "increment array entry name returned error");
	succeed_if_same_string (keyName (k), "user/array/#4");
	succeed_if (!elektraArrayIncName (k), "increment array entry name returned error");
	succeed_if_same_string (keyName (k), "user/array/#5");
	succeed_if (!elektraArrayIncName (k), "increment array entry name returned error");
	succeed_if_same_string (keyName (k), "user/array/#6");
	succeed_if (!elektraArrayIncName (k), "increment array entry name returned error");
	succeed_if_same_string (keyName (k), "user/array/#7");
	succeed_if (!elektraArrayIncName (k), "increment array entry name returned error");
	succeed_if_same_string (keyName (k), "user/array/#8");
	succeed_if (!elektraArrayIncName (k), "increment array entry name returned error");
	succeed_if_same_string (keyName (k), "user/array/#9");
	succeed_if (!elektraArrayIncName (k), "increment array entry name returned error");
	succeed_if_same_string (keyName (k), "user/array/#_10");
	succeed_if (!elektraArrayIncName (k), "increment array entry name returned error");
	succeed_if_same_string (keyName (k), "user/array/#_11");
	succeed_if (!elektraArrayIncName (k), "increment array entry name returned error");
	succeed_if_same_string (keyName (k), "user/array/#_12");
	succeed_if (!elektraArrayIncName (k), "increment array entry name returned error");
	succeed_if_same_string (keyName (k), "user/array/#_13");
	succeed_if (!elektraArrayIncName (k), "increment array entry name returned error");
	succeed_if_same_string (keyName (k), "user/array/#_14");
	succeed_if (!elektraArrayIncName (k), "increment array entry name returned error");
	succeed_if_same_string (keyName (k), "user/array/#_15");
	succeed_if (!elektraArrayIncName (k), "increment array entry name returned error");
	succeed_if_same_string (keyName (k), "user/array/#_16");
	succeed_if (!elektraArrayIncName (k), "increment array entry name returned error");
	succeed_if_same_string (keyName (k), "user/array/#_17");
	succeed_if (!elektraArrayIncName (k), "increment array entry name returned error");
	succeed_if_same_string (keyName (k), "user/array/#_18");
	succeed_if (!elektraArrayIncName (k), "increment array entry name returned error");
	succeed_if_same_string (keyName (k), "user/array/#_19");
	succeed_if (!elektraArrayIncName (k), "increment array entry name returned error");
	succeed_if_same_string (keyName (k), "user/array/#_20");
	succeed_if (!elektraArrayIncName (k), "increment array entry name returned error");
	succeed_if_same_string (keyName (k), "user/array/#_21");
	succeed_if (!elektraArrayIncName (k), "increment array entry name returned error");
	succeed_if_same_string (keyName (k), "user/array/#_22");
	succeed_if (!elektraArrayIncName (k), "increment array entry name returned error");
	succeed_if_same_string (keyName (k), "user/array/#_23");
	succeed_if (!elektraArrayIncName (k), "increment array entry name returned error");
	succeed_if_same_string (keyName (k), "user/array/#_24");
	succeed_if (!elektraArrayIncName (k), "increment array entry name returned error");
	succeed_if_same_string (keyName (k), "user/array/#_25");
	succeed_if (!elektraArrayIncName (k), "increment array entry name returned error");
	succeed_if_same_string (keyName (k), "user/array/#_26");
	succeed_if (!elektraArrayIncName (k), "increment array entry name returned error");
	succeed_if_same_string (keyName (k), "user/array/#_27");
	succeed_if (!elektraArrayIncName (k), "increment array entry name returned error");
	succeed_if_same_string (keyName (k), "user/array/#_28");
	succeed_if (!elektraArrayIncName (k), "increment array entry name returned error");
	succeed_if_same_string (keyName (k), "user/array/#_29");
	succeed_if (!elektraArrayIncName (k), "increment array entry name returned error");
	for (int i = 30; i < 99; ++i)
	{
		succeed_if (!elektraArrayIncName (k), "increment array entry in loop returned error");
	}
	succeed_if_same_string (keyName (k), "user/array/#_99");
	succeed_if (!elektraArrayIncName (k), "increment array entry name returned error");
	succeed_if_same_string (keyName (k), "user/array/#__100");
	for (int i = 101; i < 1000; ++i)
	{
		succeed_if (!elektraArrayIncName (k), "increment array entry in loop returned error");
	}
	succeed_if_same_string (keyName (k), "user/array/#__999");
	succeed_if (!elektraArrayIncName (k), "increment array entry name returned error");
	succeed_if_same_string (keyName (k), "user/array/#___1000");
	keySetBaseName (k, "#_________4000000000");
	succeed_if (!elektraArrayIncName (k), "increment array entry name returned error");
	succeed_if_same_string (keyName (k), "user/array/#_________4000000001");
	keyDel (k);
}
static int csvRead(KeySet *returned, Key *parentKey, char delim, short useHeader, unsigned long fixColumnCount, const char **colNames)
{
    const char *fileName;
    fileName = keyString(parentKey);
    FILE *fp = NULL;
    fp = fopen(fileName, "rb");
    if(!fp)
    {
        ELEKTRA_SET_ERRORF(116, parentKey, "couldn't open file %s\n", fileName);
        return -1;
    }

    unsigned long length = 0;
    length = getLineLength(fp);
    if(length == 0)
    {
        ELEKTRA_ADD_WARNING(118, parentKey, "Empty file");
        fclose(fp);
        return -2;
    }

    char *lineBuffer;
    lineBuffer = elektraMalloc((length * sizeof(char))+1);
    if(!lineBuffer)
    {
        ELEKTRA_SET_ERROR(87, parentKey, "Out of memory");
        return -1;
    }
    if(!fgets(lineBuffer, length, fp))
    {
        ELEKTRA_SET_ERROR(116, parentKey, "Cant read from file");
        return -1;
    }

    unsigned long columns = 0;
    columns = getColumnCount(lineBuffer, delim);
    if(fixColumnCount)
    {
        if(columns != fixColumnCount)
        {
            ELEKTRA_SET_ERROR(117, parentKey, "illegal number of columns in Header line");
            elektraFree(lineBuffer);
            fclose(fp);
            return -1;
        }
    }
    unsigned long colCounter = 0;
    unsigned long lineCounter = 0;
    unsigned long offset = 0;
    char *col;
    char buf[INTSTR_MAX];
    int nr_keys = 1;
    KeySet *header = ksNew(0, KS_END);
    Key *key;

    if(useHeader == 1)
    {
        colCounter = 0;
        offset = 0;
        while((col = parseLine(lineBuffer, delim, offset, parentKey, lineCounter)) != NULL)
        {
            offset += elektraStrLen(col);
            key = keyDup(parentKey);
            if(colNames && (colNames+colCounter))
            {
                keyAddBaseName(key, colNames[colCounter]);
            }
            else
            {
                keyAddBaseName(key, col);
            }
            keySetMeta(key, "csv/order", itostr(buf, colCounter, sizeof(buf)-1));
            ksAppendKey(header, key);
            ++colCounter;
        }
        fseek(fp, 0, SEEK_SET);
    }
    else
    {
        colCounter = 0;
        //if no headerline exists name the columns 0..N where N is the number of columns
        key = keyDup(parentKey);
        keyAddName(key, "#");
        while(colCounter < columns)
        {
            if(elektraArrayIncName(key) == -1)
            {
                elektraFree(lineBuffer);
                keyDel(key);
                ksDel(header);
                fclose(fp);
                return -1;
            }
            keySetMeta(key, "csv/order", itostr(buf, colCounter, sizeof(buf)-1));
            if(colNames && (colNames+colCounter))
                keySetBaseName(key, colNames[colCounter]);
            ksAppendKey(header, keyDup(key));
            ++colCounter;
        }
        keyDel(key);
        if(useHeader == 0)
            fseek(fp, 0, SEEK_SET);
    }
    Key *dirKey;
    Key *cur;
    dirKey = keyDup(parentKey);
    keyAddName(dirKey, "#");
    while(!feof(fp))
    {
        length = getLineLength(fp);
        if(length == 0)
            break;
        if(elektraRealloc((void **)&lineBuffer, (length * sizeof(char))+1) < 0)
        {
            fclose(fp);
            elektraFree(lineBuffer);
            ksDel(header);
            keyDel(dirKey);
            ELEKTRA_SET_ERROR(87, parentKey, "Out of memory");
            return -1;
        }
        fgets(lineBuffer, length, fp);
        if(elektraArrayIncName(dirKey) == -1)
        {
            elektraFree(lineBuffer);
            keyDel(dirKey);
            ksDel(header);
            fclose(fp);
            return -1;
        }
        ++nr_keys;
        offset = 0;
        colCounter = 0;
        char *lastIndex = "#0";
        while((col = parseLine(lineBuffer, delim, offset, parentKey, lineCounter)) != NULL)
        {
            cur = getKeyByOrderNr(header, colCounter);
            offset += elektraStrLen(col);
            key = keyDup(dirKey);
            keyAddBaseName(key, keyBaseName(cur));
            keySetString(key, col);
            keySetMeta(key, "csv/order", itostr(buf, colCounter, sizeof(buf)-1));
            ksAppendKey(returned, key);
            lastIndex = (char *)keyBaseName(key);
            ++nr_keys;
            ++colCounter;
        }
        keySetString(dirKey, lastIndex);
        ksAppendKey(returned, keyDup(dirKey));
        if(colCounter != columns)
        {
            if(fixColumnCount)
            {
                ELEKTRA_SET_ERRORF(117, parentKey, "illegal number of columns in line %lu", lineCounter);
                elektraFree(lineBuffer);
                fclose(fp);
                keyDel(dirKey);
                ksDel(header);
                return -1;
            }
            ELEKTRA_ADD_WARNINGF(118, parentKey, "illegal number of columns in line %lu", lineCounter);
        }
        ++lineCounter;
    }
    key = keyDup(parentKey);
    keySetString(key, keyBaseName(dirKey));
    ksAppendKey(returned, key);
    keyDel(dirKey);
    fclose(fp);
    elektraFree(lineBuffer);
    ksDel(header);
    return 1;
}
Beispiel #12
0
int elektraSortTopology (KeySet * ks, Key ** array)
{
	if (ks == NULL || array == NULL) return -1;
	KeySet * done = ksNew (0, KS_END);
	ksRewind (ks);
	Key * cur;
	ssize_t size = ksGetSize (ks);
	Key * orderCounter = keyNew ("/#", KEY_CASCADING_NAME, KEY_END);
	elektraArrayIncName (orderCounter);
	_adjMatrix adjMatrix[size];
	int i = 0;
	int retVal = 1;
	int depCount = 0;
	Key ** localArray = elektraMalloc (size * sizeof (Key *));
	elektraKsToMemArray (ks, localArray);
	qsort (localArray, size, sizeof (Key *), topCmpOrder);
	for (long j = 0; j < size; ++j)
	{
		adjMatrix[j].key = localArray[j];
		adjMatrix[j].isResolved = 0;
		adjMatrix[j].deps = elektraCalloc (sizeof (unsigned long) * size);
	}
	kdb_octet_t hasOrder = 0;
	if (keyGetMeta (localArray[0], "order")) hasOrder = 1;
	unsigned int unresolved = 0;
	for (int j = 0; j < size; ++j)
	{
		cur = localArray[j];
		KeySet * deps = elektraMetaArrayToKS (cur, "dep");
		keyDel (ksLookupByName (deps, "dep", KDB_O_POP));
		Key * tmpDep;
		switch (ksGetSize (deps))
		{
		case -1:
		{
			// key has no dependencies, give it an order number and add it to list of resolved dependencies
			keySetMeta (cur, "order", keyBaseName (orderCounter));
			elektraArrayIncName (orderCounter);
			ksAppendKey (done, keyDup (cur));
			adjMatrix[j].isResolved = 1;
			ksDel (deps);
			break;
		}
		case 1:
		{
			// only 1 dependency:
			// test if it's reflexive
			tmpDep = ksHead (deps);
			if (!strcmp (keyName (cur), keyString (tmpDep)))
			{
				keySetMeta (cur, "order", keyBaseName (orderCounter));
				elektraArrayIncName (orderCounter);
				ksAppendKey (done, keyDup (cur));
				adjMatrix[j].isResolved = 1;
				ksDel (deps);
				break;
			}
			// if not, fallthrough to normal dependency handling
		}
		default:
		{
			int gotUnresolved = 0;
			while ((tmpDep = ksNext (deps)) != NULL)
			{
				if (!isValidKeyName (keyString (tmpDep)))
				{
					// invalid keyname -> ERROR
					retVal = -1;
					break;
				}
				i = getArrayIndex (tmpDep, adjMatrix, size);
				if (i == -1)
				{
					// key doesn't exist yet but has valid name, ignore it.
					continue;
				}
				else if (i == j)
				{
					// reflexiv depencency, do nothing
				}
				else
				{
					if (!adjMatrix[i].isResolved)
					{
						// unresolved dependency
						adjMatrix[j].deps[i] = 1;
						++gotUnresolved;
						// simple cycle detection
						if (adjMatrix[i].deps[j])
						{
							retVal = 0;
							break;
						}
					}
				}
			}
			if (gotUnresolved)
			{
				adjMatrix[j].isResolved = 0;
				++unresolved;
				// cound unresolved dependencies
				depCount += gotUnresolved;
			}
			ksDel (deps);
			break;
		}
		}
		if (retVal <= 0) break;
	}
	if (retVal <= 0)
	{
		// error or cycle: goto cleanup
		goto TopSortCleanup;
	}

	// resolve all dependencies that can be resolved immediately
	for (int j = 0; j < size; ++j)
	{
		if (adjMatrix[j].isResolved) depCount -= resolveDep (j, adjMatrix, size);
	}

	ssize_t resolved = ksGetSize (done);
	if (((depCount + resolved) >= size) && (unresolved))
	{
		// more dependencies dependencies than keys:
		//  cycle found !
		retVal = 0;
		goto TopSortCleanup;
	}

	if (unresolved)
	{
		int found = 1;
		// we have unresolved dependencies
		for (int j = 0; j < size + 1; ++j)
		{
			// loop until no dependency can be resolved anymore
			if (j == size)
			{
				if (found)
				{
					found = 0;
					j = -1;
					unresolved = 0;
					continue;
				}
				else
					break;
			}
			if (adjMatrix[j].isResolved) continue;
			++unresolved;
			if (hasOrder)
			{
				// resolve by order
				int ret = resolveDeps (j, adjMatrix, size, done, orderCounter);
				if (ret == -1) break;
				j = -1;
				found = 1;
				continue;
			}
			else
			{
				// resolve next possible dependency in keyset
				if (!hasUnresolvedDependencies (j, adjMatrix, size))
				{
					adjMatrix[j].isResolved = 1;
					resolveDep (j, adjMatrix, size);
					keySetMeta (localArray[j], "order", keyBaseName (orderCounter));
					elektraArrayIncName (orderCounter);
					ksAppendKey (done, keyDup (localArray[j]));
					found = 1;
				}
			}
		}
	}
	if (unresolved == 0)
	{
		// everything resolved
		// add dependencies in topological order to array
		elektraKsToMemArray (ks, array);
		qsort (array, size, sizeof (Key *), topCmpOrder);
		retVal = 1;
	}
	else
	{
		// still unresolved dependencies left:
		// there must be a cycle somewhere
		retVal = 0;
	}
TopSortCleanup:
	ksDel (done);
	keyDel (orderCounter);
	elektraFree (localArray);
	for (ssize_t j = 0; j < size; ++j)
	{
		elektraFree (adjMatrix[j].deps);
	}
	return retVal;
}
Beispiel #13
0
/**
 * @internal
 *
 * elektraSortTopology helper
 * resolve all dependencies of the key with the index j in our matrix.
 */
static int resolveDeps (unsigned int j, _adjMatrix * adjMatrix, size_t size, KeySet * done, Key * orderCounter)
{
	unsigned int loops = 0;
	unsigned int frontier[size];
	unsigned int todo = 0;
	for (unsigned int i = 0; i < size; ++i)
	{
		if (adjMatrix[j].deps[i])
		{
			frontier[i] = 1;
			++todo;
		}
		else
		{
			frontier[i] = 0;
		}
	}
	int found = 1;

	// loop until all dependencies are added to frontier
	while (found)
	{
		found = 0;
		for (unsigned int i = 0; i < size; ++i)
		{
			if (!frontier[i]) continue;
			if (hasUnresolvedDependencies (i, adjMatrix, size))
			{
				for (unsigned int k = 0; k < size; ++k)
				{
					if (adjMatrix[i].deps[k])
					{
						if (!frontier[k])
						{
							found = 1;
							++todo;
							frontier[k] = 1;
						}
					}
				}
			}
		}
	}
	if (todo == 0)
	{
		// all dependencies are already resolved, give key an order number and add it to
		// the our list of resolved keys (done)
		adjMatrix[j].isResolved = 1;
		resolveDep (j, adjMatrix, size);
		keySetMeta (adjMatrix[j].key, "order", keyBaseName (orderCounter));
		elektraArrayIncName (orderCounter);
		ksAppendKey (done, keyDup (adjMatrix[j].key));
		return 1;
	}
	unsigned int max_loops = todo;
	for (unsigned int i = 0; todo; ++i)
	{
		if (i == size)
		{
			++loops;
			i = 0;
		}
		if (loops > max_loops) return -1; // more loops than we had unresolved keys -> cycle
		if (!frontier[i]) continue;
		if (!hasUnresolvedDependencies (i, adjMatrix, size))
		{
			resolveDep (i, adjMatrix, size);
			frontier[i] = 0;
			--todo;
			adjMatrix[i].isResolved = 1;
			resolveDep (i, adjMatrix, size);
			keySetMeta (adjMatrix[i].key, "order", keyBaseName (orderCounter));
			elektraArrayIncName (orderCounter);
			ksAppendKey (done, keyDup (adjMatrix[i].key));
		}
	}
	return 1;
}
Beispiel #14
0
static int iniKeyToElektraKey (void *vhandle, const char *section, const char *name, const char *value, unsigned short lineContinuation)
{
	CallbackHandle *handle = (CallbackHandle *)vhandle;
	Key *appendKey = keyDup (handle->parentKey);
	keySetMeta(appendKey, "ini/lastSection", 0);
	if (!section || *section == '\0')
	{
		section = INTERNAL_ROOT_SECTION;
	}
	appendKey = createUnescapedKey(appendKey, section);
	short mergeSections = 0;
	Key *existingKey = NULL;
	if ((existingKey = ksLookup(handle->result, appendKey, KDB_O_NONE)))
	{
		if (keyGetMeta(existingKey, "ini/duplicate"))
		{
			mergeSections = 1;
		}
	}
	setSectionNumber(handle->parentKey, appendKey, handle->result);
	appendKey = createUnescapedKey(appendKey, name);
	existingKey = ksLookup(handle->result, appendKey, KDB_O_NONE);

	if (existingKey)
	{
		//a key with the same name already exists
		if (handle->array)
		{
			//array support is turned on 
			keySetMeta(appendKey, "ini/section", 0);
			if (keyGetMeta(existingKey, "ini/array"))
			{
				//array already exists, appending new key
				const char *lastIndex = keyString(keyGetMeta(existingKey, "ini/array"));
				keyAddBaseName(appendKey, lastIndex);
				keySetMeta(appendKey, "order/parent", 0);
				keySetMeta(appendKey, "ini/array", 0);
				keySetMeta(appendKey, "order", 0);
				if (elektraArrayIncName(appendKey) == 1)
				{
					return -1;
				}
				keySetString(appendKey, value);
				keySetMeta(appendKey, "ini/key", 0);
				ksAppendKey(handle->result, appendKey);
				keySetMeta(existingKey, "ini/array", keyBaseName(appendKey));
				ksAppendKey(handle->result, existingKey);
			}
			else
			{
				//creating a new array
				Key *sectionKey = keyDup(appendKey);
				keyAddName(sectionKey, "..");
				char *origVal = strdup(keyString(existingKey));
				keySetString(appendKey, "");
				keySetMeta(appendKey, "ini/array", "#1");
				keySetMeta(appendKey, "order/parent", keyName(sectionKey));
				setSectionNumber(handle->parentKey, appendKey, handle->result);
				setOrderNumber(handle->parentKey, appendKey);
				keySetMeta(appendKey, "ini/key", "");
				ksAppendKey(handle->result, keyDup(appendKey));
				keySetMeta(appendKey, "ini/key", 0);
				keySetMeta(appendKey, "ini/array", 0);
				keySetMeta(appendKey, "parent", 0);
				keyAddName(appendKey, "#");
				keySetMeta(appendKey, "order", 0);
				if (elektraArrayIncName(appendKey) == -1)
				{
					free(origVal);
					return -1;
				}
				keySetString(appendKey, origVal);
				ksAppendKey(handle->result, keyDup(appendKey));
				free(origVal);
				if (elektraArrayIncName(appendKey) == -1)
				{
					return -1;
				}
				keySetMeta(appendKey, "parent", 0);
				keySetString(appendKey, value);
				ksAppendKey(handle->result, keyDup(appendKey));
				keyDel(appendKey);
				keyDel(sectionKey);
			}
			return 1;
		}
		else if(!lineContinuation)
		{
			ELEKTRA_SET_ERRORF(141, handle->parentKey, "Key: %s\n", name);
			return -1;
		}
	}

	setSectionNumber(handle->parentKey, appendKey, handle->result);
	if (value == NULL)
		keySetMeta(appendKey, "ini/empty", "");
	if (!lineContinuation)
	{
		flushCollectedComment (handle, appendKey);
		keySetString (appendKey, value);
		keySetMeta(appendKey, "ini/key", "");
		ksAppendKey (handle->result, appendKey);
		if (mergeSections)
		{
			keySetMeta(appendKey, "order", 0);
			insertNewKeyIntoExistendOrder(appendKey, handle->result);
		}
		else
		{
			setOrderNumber(handle->parentKey, appendKey);
		}
	}
	else
	{
		existingKey = ksLookup (handle->result, appendKey, KDB_O_NONE);
		keyDel (appendKey);
		/* something went wrong before because this key should exist */
		if (!existingKey) return -1;

		elektraKeyAppendLine(existingKey, value);
	}


	return 1;
}