Skip to content
This repository has been archived by the owner on Oct 15, 2024. It is now read-only.

Commit

Permalink
Merge pull request #593 from tom-wa/rename_write
Browse files Browse the repository at this point in the history
rename updates
  • Loading branch information
markus2330 committed Apr 24, 2016
2 parents 314252a + a4a3791 commit 31d7a1e
Show file tree
Hide file tree
Showing 4 changed files with 193 additions and 19 deletions.
55 changes: 54 additions & 1 deletion src/plugins/rename/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,51 @@
- infos/metadata = rename/to rename/toupper rename/tolower rename/cut
- infos/description = renaming of keys

## INTRODUCTION ##
# INTRODUCTION #


This plugin can be used to perform rename operations on keys. This is useful if a backend does not provide keys
with the required names or case.

If keys are renamed, their original name is stored in the `origname` MetaKey.

There are 2 types of transformations:
* basic
* advanced


# BASIC TRANSFORMATIONS #

are applied before and after the advanced transformations.

## GET ##

first transformation to be applied to all keys on kdbGet.

`get/case`
* toupper
* tolower
* unchanged // this is the default value if no configuration is given

converts the whole keyname below the parentKey to upper- or lowercase. if no configuration or `unchanged` is used no transformation is done here.

## SET ##

last transformation to be applied to all keys on kdbSet.

`set/case`
* toupper
* tolower
* keyname
* unchanged // this is the default value if no configuration is given

`toupper` or `tolower` tells the rename plugin to convert the whole keyname below below the parentKey to lower or uppercase.

`unchanged` returnes the key to it's original name

`keyname` tells the plugin to keep the name of the advanced transformation

# ADVANCED TRANSFORMATIONS #

## CUT ##

Expand Down Expand Up @@ -92,6 +129,22 @@ user/rename
user/rename/mixed/case/CONVERSION
```

```
% cat renameTest.ini
test/removed/key = test
% kdb mount renameTest.ini /rename ini rename get/case=toupper,set/case=keyname,/cut=REMOVED
% kdb ls /rename
user/rename/TEST/KEY
% kdb set /rename
Using name user/rename
Create a new key user/rename with null value
% cat renameTest.ini
TEST/KEY = test
```


## PLANNED OPERATIONS ##


Expand Down
105 changes: 93 additions & 12 deletions src/plugins/rename/rename.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,12 @@
#define ELEKTRA_ORIGINAL_NAME_META "origname"
#define TOLOWER (-1)
#define TOUPPER 1
#define UNCHNGD 0
#define KEYNAME 2
// TODO defined privately in keyhelpers.c, API break possible..
char * keyNameGetOneLevel (const char * name, size_t * size);

static void doConversion (char * newName, int levels, int toCase)
static void doConversion (char * newName, int levels, const int toCase)
{
int (*conversion) (int);

Expand Down Expand Up @@ -74,7 +76,7 @@ static void doConversion (char * newName, int levels, int toCase)
}

Key * elektraKeyCreateNewName (const Key * key, const Key * parentKey, const char * cutPath, const char * replaceWith,
const char * toUpperPath, const char * toLowerPath)
const char * toUpperPath, const char * toLowerPath, const int initialConversion)
{
size_t addToLen = 0;
if (replaceWith != NULL) addToLen = strlen (replaceWith);
Expand All @@ -89,9 +91,15 @@ Key * elektraKeyCreateNewName (const Key * key, const Key * parentKey, const cha
char * curKeyName = elektraMalloc (keyGetFullNameSize (key));
keyGetFullName (key, curKeyName, keyGetFullNameSize (key));

const char * afterParentString = curKeyName + (strlen (parentKeyName));
char * afterParentString = curKeyName + (strlen (parentKeyName));
char * ptr;

if (initialConversion != UNCHNGD)
{
doConversion (afterParentString, 0, initialConversion);
replace = 1;
}

if (cutPath && (cutPath[0] != '/') && ((ptr = strstr (afterParentString, cutPath)) != NULL))
{
strncpy (newName, afterParentString, (ptr - afterParentString));
Expand Down Expand Up @@ -165,7 +173,8 @@ static void keyAddUnescapedBasePath (Key * key, const char * path)
}
}

static Key * renameGet (Key * key, Key * parentKey, Key * cutConfig, Key * replaceWithConfig, Key * toUpperConfig, Key * toLowerConfig)
static Key * renameGet (Key * key, Key * parentKey, Key * cutConfig, Key * replaceWithConfig, Key * toUpperConfig, Key * toLowerConfig,
Key * getCase)
{
char * cutPath = 0;
char * replaceWith = 0;
Expand All @@ -175,6 +184,24 @@ static Key * renameGet (Key * key, Key * parentKey, Key * cutConfig, Key * repla
const Key * toMeta = keyGetMeta (key, "rename/to");
const Key * toUpperMeta = keyGetMeta (key, "rename/toupper");
const Key * toLowerMeta = keyGetMeta (key, "rename/tolower");

int initialConversion = 0;
if (getCase)
{
const char * str = keyString (getCase);
if (!strcmp (str, "toupper"))
{
initialConversion = TOUPPER;
}
else if (!strcmp (str, "tolower"))
{
initialConversion = TOLOWER;
}
else
{
initialConversion = UNCHNGD;
}
}
/* if the meta config exists, it takes precedence over the global config */
if (cutMeta)
cutPath = (char *)keyString (cutMeta);
Expand All @@ -193,7 +220,7 @@ static Key * renameGet (Key * key, Key * parentKey, Key * cutConfig, Key * repla
else if (toLowerConfig)
toLowerPath = (char *)keyString (toLowerConfig);

return elektraKeyCreateNewName (key, parentKey, cutPath, replaceWith, toUpperPath, toLowerPath);
return elektraKeyCreateNewName (key, parentKey, cutPath, replaceWith, toUpperPath, toLowerPath, initialConversion);
}

static Key * restoreKeyName (Key * key, const Key * parentKey, const Key * configKey)
Expand Down Expand Up @@ -265,10 +292,14 @@ int elektraRenameGet (Plugin * handle, KeySet * returned, Key * parentKey)
Key * toUpper = ksLookupByName (config, "/toupper", KDB_O_NONE);
Key * toLower = ksLookupByName (config, "/tolower", KDB_O_NONE);
Key * replaceWith = ksLookupByName (config, "/replacewith", KDB_O_NONE);
Key * getCase = ksLookupByName (config, "/get/case", KDB_O_NONE);


Key * key;
while ((key = ksNext (iterateKs)) != 0)
{
Key * renamedKey = renameGet (key, parentKey, cutConfig, replaceWith, toUpper, toLower);

Key * renamedKey = renameGet (key, parentKey, cutConfig, replaceWith, toUpper, toLower, getCase);

if (renamedKey)
{
Expand Down Expand Up @@ -315,29 +346,80 @@ int elektraRenameSet (Plugin * handle, KeySet * returned, Key * parentKey)
KeySet * config = elektraPluginGetConfig (handle);
Key * cutConfig = ksLookupByName (config, "/cut", KDB_O_NONE);

Key * setCase = ksLookupByName (config, "/set/case", KDB_O_NONE);

int writeConversion = 0;
if (setCase)
{
const char * str = keyString (setCase);
if (!strcmp (str, "toupper"))
{
writeConversion = TOUPPER;
}
else if (!strcmp (str, "tolower"))
{
writeConversion = TOLOWER;
}
else if (!strcmp (str, "keyname"))
{
writeConversion = KEYNAME;
}
else
{
writeConversion = UNCHNGD;
}
}
ksRewind (iterateKs);
Key * key;
char * parentKeyName = elektraMalloc (keyGetFullNameSize (parentKey));
keyGetFullName (parentKey, parentKeyName, keyGetFullNameSize (parentKey));
while ((key = ksNext (iterateKs)) != 0)
{
Key * renamedKey = restoreKeyName (key, parentKey, cutConfig);

if (renamedKey)
Key * renamedKey = NULL;
if (writeConversion != KEYNAME)
{
renamedKey = restoreKeyName (key, parentKey, cutConfig);

if (!renamedKey) renamedKey = keyDup (key);
if (writeConversion == TOUPPER || writeConversion == TOLOWER)
{
char * curKeyName = elektraMalloc (keyGetFullNameSize (renamedKey));
keyGetFullName (renamedKey, curKeyName, keyGetFullNameSize (renamedKey));

char * afterParentString = curKeyName + (strlen (parentKeyName));

doConversion (afterParentString, 0, writeConversion);

keySetName (renamedKey, curKeyName);
elektraFree (curKeyName);
}
/*
* if something is restored from the parentKey, do
* not delete the parentKey (might cause troubles)
*/
if (keyCmp (key, parentKey) != 0)
{
ksLookup (returned, key, KDB_O_POP);
keyDel (key);
keyDel (ksLookup (returned, key, KDB_O_POP));
}
ksAppendKey (returned, renamedKey);
keyDel (renamedKey);
}
else
{
if (keyCmp (key, parentKey) != 0)
{
keyDel (ksLookupByName (returned, keyString (keyGetMeta (key, ELEKTRA_ORIGINAL_NAME_META)), KDB_O_POP));
}
ksAppendKey (returned, key);
}
}

keyIncRef (parentKey);
ksDel (iterateKs);
keyDecRef (parentKey);

ksRewind (returned);
elektraFree (parentKeyName);
return 1; /* success */
}

Expand All @@ -349,4 +431,3 @@ Plugin * ELEKTRA_PLUGIN_EXPORT (rename)
ELEKTRA_PLUGIN_SET, &elektraRenameSet,
ELEKTRA_PLUGIN_END);
}

2 changes: 1 addition & 1 deletion src/plugins/rename/rename.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
int elektraRenameGet (Plugin * handle, KeySet * ks, Key * parentKey);
int elektraRenameSet (Plugin * handle, KeySet * ks, Key * parentKey);
Key * elektraKeyCreateNewName (const Key * key, const Key * parentKey, const char * cutPath, const char * replaceWith, const char * toUpper,
const char * toLower);
const char * toLower, const int initialConversion);

Plugin * ELEKTRA_PLUGIN_EXPORT (rename);

Expand Down
50 changes: 45 additions & 5 deletions src/plugins/rename/testmod_rename.c
Original file line number Diff line number Diff line change
Expand Up @@ -225,28 +225,28 @@ static void test_metaConfigTakesPrecedence ()
static void test_keyCutNamePart ()
{
Key * parentKey = keyNew ("user/tests/rename", KEY_END);
Key * result = elektraKeyCreateNewName (parentKey, parentKey, "wont/cut/this", NULL, NULL, NULL);
Key * result = elektraKeyCreateNewName (parentKey, parentKey, "wont/cut/this", NULL, NULL, NULL, 0);
succeed_if (!result, "parentKey was modified although it should have been ignored");

/* cutting works correctly without trailing slash */
Key * testKey = keyNew ("user/tests/rename/will/cut/this/key1", KEY_END);
result = elektraKeyCreateNewName (testKey, parentKey, "will/cut/this", NULL, NULL, NULL);
result = elektraKeyCreateNewName (testKey, parentKey, "will/cut/this", NULL, NULL, NULL, 0);
succeed_if (result, "key1 was not cut")
succeed_if (!strcmp (keyName (result), "user/tests/rename/key1"), "cutting key1 did not yield the expected result");
keyDel (testKey);
keyDel (result);

/* cutting works correctly with trailing slash */
testKey = keyNew ("user/tests/rename/will/cut/this/key1", KEY_END);
result = elektraKeyCreateNewName (testKey, parentKey, "will/cut/this/", NULL, NULL, NULL);
result = elektraKeyCreateNewName (testKey, parentKey, "will/cut/this/", NULL, NULL, NULL, 0);
succeed_if (result, "key1 was not cut")
succeed_if (!strcmp (keyName (result), "user/tests/rename/key1"), "cutting key1 did not yield the expected result");
keyDel (testKey);
keyDel (result);

/* disallow leading slashes */
testKey = keyNew ("user/tests/rename/wont/cut/this/key1", KEY_END);
result = elektraKeyCreateNewName (testKey, parentKey, "/wont/cut/this", NULL, NULL, NULL);
result = elektraKeyCreateNewName (testKey, parentKey, "/wont/cut/this", NULL, NULL, NULL, 0);
succeed_if (!result, "key was cut although it the cutpath contained a leading slash");
keyDel (testKey);
keyDel (parentKey);
Expand Down Expand Up @@ -395,6 +395,45 @@ static void test_mixCase ()
PLUGIN_CLOSE ();
}

static void test_write ()
{
Key * parentKey = keyNew ("user/tests/rename", KEY_END);
KeySet * conf =
ksNew (20, keyNew ("system/tolower", KEY_VALUE, "1", KEY_END), keyNew ("system/get/case", KEY_VALUE, "toupper", KEY_END),
keyNew ("system/set/case", KEY_VALUE, "keyname"), KS_END);
KeySet * ks = ksNew (20, keyNew ("user/tests/rename/uppercase/uppercase/uppercase/LOWERCASE", KEY_VALUE, "test", KEY_END), KS_END);
ksAppendKey (ks, parentKey);
PLUGIN_OPEN ("rename");
succeed_if (plugin->kdbGet (plugin, ks, parentKey) >= 1, "call to kdbGet was not successful");
Key * key = ksLookupByName (ks, "user/tests/rename/UPPERCASE/UPPERCASE/UPPERCASE/lowercase", KDB_O_NONE);
succeed_if (key, "key1 was not correctly rename");
succeed_if (plugin->kdbSet (plugin, ks, parentKey) == 1, "call to kdbSet was not successful");
key = ksLookupByName (ks, "user/tests/rename/UPPERCASE/UPPERCASE/UPPERCASE/lowercase", KDB_O_NONE);
succeed_if (key, "key1s name was not correctly saved");
keyDel (parentKey);
ksDel (ks);
PLUGIN_CLOSE ();
}

static void test_write2 ()
{
Key * parentKey = keyNew ("user/tests/rename", KEY_END);
KeySet * conf =
ksNew (20, keyNew ("system/tolower", KEY_VALUE, "1", KEY_END), keyNew ("system/get/case", KEY_VALUE, "tolower", KEY_END),
keyNew ("system/set/case", KEY_VALUE, "toupper"), KS_END);
KeySet * ks = ksNew (20, keyNew ("user/tests/rename/UPPERCASE/UPPERCASE/UPPERCASE/LOWERCASE", KEY_VALUE, "test", KEY_END), KS_END);
ksAppendKey (ks, parentKey);
PLUGIN_OPEN ("rename");
succeed_if (plugin->kdbGet (plugin, ks, parentKey) >= 1, "call to kdbGet was not successful");
Key * key = ksLookupByName (ks, "user/tests/rename/uppercase/uppercase/uppercase/lowercase", KDB_O_NONE);
succeed_if (key, "key1 was not correctly rename");
succeed_if (plugin->kdbSet (plugin, ks, parentKey) == 1, "call to kdbSet was not successful");
key = ksLookupByName (ks, "user/tests/rename/UPPERCASE/UPPERCASE/UPPERCASE/LOWERCASE", KDB_O_NONE);
succeed_if (key, "key1s name was not correctly saved");
keyDel (parentKey);
ksDel (ks);
PLUGIN_CLOSE ();
}
int main (int argc, char ** argv)
{
printf ("RENAME TESTS\n");
Expand All @@ -415,7 +454,8 @@ int main (int argc, char ** argv)
test_toLower ();
test_mixCase ();
test_replaceString ();

test_write ();
test_write2 ();
printf ("\ntest_rename RESULTS: %d test(s) done. %d error(s).\n", nbTest, nbError);

return nbError;
Expand Down

0 comments on commit 31d7a1e

Please sign in to comment.