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

Commit

Permalink
kdb-cli: rewrite get command
Browse files Browse the repository at this point in the history
... and remove cpp implementation
  • Loading branch information
hannes99 committed Sep 21, 2022
1 parent a210512 commit 55693e4
Show file tree
Hide file tree
Showing 6 changed files with 275 additions and 249 deletions.
2 changes: 0 additions & 2 deletions src/tools/kdb/factory.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
#include <file.hpp>
#include <find.hpp>
#include <gen.hpp>
#include <get.hpp>
#include <globalmount.hpp>
#include <globalumount.hpp>
#include <import.hpp>
Expand Down Expand Up @@ -89,7 +88,6 @@ class Factory
Factory () : m_factory ()
{
// TODO: to add a new command, 2.) add a line here -> and you are done
m_factory.insert (std::make_pair ("get", std::make_shared<Cnstancer<GetCommand>> ()));
m_factory.insert (std::make_pair ("set", std::make_shared<Cnstancer<SetCommand>> ()));
m_factory.insert (std::make_pair ("rm", std::make_shared<Cnstancer<RemoveCommand>> ()));
m_factory.insert (std::make_pair ("ls", std::make_shared<Cnstancer<LsCommand>> ()));
Expand Down
229 changes: 229 additions & 0 deletions src/tools/kdb/get.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
/**
* @file
*
* @brief KDB get subcommand
*
* @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
*/

#include <command.h>
#include <get.h>
#include <kdbassert.h>
#include <kdbease.h>
#include <kdberrors.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define COMMAND_NAME "get"

#define GET_OPTION_KEY(options, name) GET_OPT_KEY (options, COMMAND_BASE_KEY (COMMAND_NAME) "/" name)
#define GET_OPTION(options, name) GET_OPT (options, COMMAND_BASE_KEY (COMMAND_NAME) "/" name)

void addGetSpec (KeySet * spec)
{
ksAppendKey (spec, keyNew (COMMAND_SPEC_KEY (COMMAND_NAME), KEY_META, "description", "Get the value of an individual key.",
KEY_META, "command", COMMAND_NAME, KEY_END));
ksAppendKey (spec, keyNew (COMMAND_SPEC_KEY (COMMAND_NAME) "/all", KEY_META, "description", "Consider all of the keys", KEY_META,
"opt", "a", KEY_META, "opt/long", "all", KEY_META, "opt/arg", "none", KEY_END));
ksAppendKey (spec, keyNew (COMMAND_SPEC_KEY (COMMAND_NAME) "/name", KEY_META, "description", "The name of the key", KEY_META,
"args", "indexed", KEY_META, "args/index", "0", KEY_END));

ADD_BASIC_OPTIONS (spec, COMMAND_SPEC_KEY (COMMAND_NAME))
}

int execGet (KeySet * options, Key * errorKey)
{
int ret = 0;
bool verbose = false;
elektraKeyToBoolean (GET_OPTION_KEY (options, "verbose"), &verbose);

bool all = false;
elektraKeyToBoolean (GET_OPTION_KEY (options, "all"), &all);

const char * rawName = GET_OPTION (options, "name");
bool resolved = false;
char * name = expandKeyName (options, rawName, &resolved);
if (name == NULL)
{
ELEKTRA_SET_VALIDATION_SEMANTIC_ERRORF (errorKey, "could not resolve bookmark in '%s'", rawName);
return -1;
}
if (verbose && resolved)
{
printf ("resolved bookmark: \'%s\' -> \'%s\'\n", rawName, name);
}

KeySet * searchIn = ksNew (0, KS_END);
KDB * handle = kdbOpen (NULL, errorKey);
Key * toLookUp = keyNew (name, KEY_END);
Key * parentKey = toLookUp;
if (all)
{
parentKey = keyNew ("/", KEY_END);
}
if (kdbGet (handle, searchIn, parentKey) == -1)
{
ELEKTRA_SET_VALIDATION_SEMANTIC_ERRORF (errorKey, "could not load '%s': %s", name, GET_ERR (toLookUp));
kdbClose (handle, errorKey);
ksDel (searchIn);
keyDel (toLookUp);
keyDel (parentKey);
return -1;
}
kdbClose (handle, errorKey);
keyDel (parentKey);

setCallback (toLookUp, warnOnMeta);
if (verbose)
{
printf ("got %ld keys\n", ksGetSize (searchIn));
setCallback (toLookUp, printTrace);
}

Key * found = ksLookup (searchIn, toLookUp, KDB_O_CALLBACK);

if (keyCopyAllMeta (errorKey, toLookUp) == -1)
{
ELEKTRA_SET_INTERNAL_ERROR (errorKey, "could not copy key meta to errorKey");
ksDel (searchIn);
keyDel (toLookUp);
return -1;
}

if (found != NULL)
{
if (verbose)
{
if (keyGetNamespace (found) == KEY_NS_DEFAULT)
{
printf ("The key was not found in any other namespace, taking the default\n");
}
printf ("The resulting keyname is %s\n", keyName (found));
printf ("The resulting value size is %ld\n", keyGetValueSize (found));
}
if (keyIsBinary (found))
{
ssize_t binSize = keyGetValueSize (found);
if (verbose)
{
printf ("The key is %s.\n", binSize == 0 ? "null" : "binary");
}
char * buffer = elektraMalloc (binSize);
if (buffer == NULL)
{
ELEKTRA_SET_RESOURCE_ERROR (errorKey, "could not allocate memory for key bin value");
}
else
{
keyGetBinary (found, buffer, sizeof buffer);
for (ssize_t pos = 0; pos < binSize; pos++)
{
printf ("%x", buffer[pos]);
}
elektraFree (buffer);
}
}
else
{
printf ("%s", keyString (found));
}
}
else
{
printf ("Did not find key '%s'", name);
ret = 1;
}
printf ("\n");
ksDel (searchIn);
keyDel (toLookUp);
return ret;
}

void printOptions (elektraLookupFlags options)
{
// :'<,'>s/\(.*\)/^Iif(options \& \1) printf("\1 ");
if (options & KDB_O_SPEC) printf ("KDB_O_SPEC ");
if (options & KDB_O_CREATE) printf ("KDB_O_CREATE ");
if (options & KDB_O_NOCASCADING) printf ("KDB_O_NOCASCADING ");
if (options & KDB_O_NOSPEC) printf ("KDB_O_NOSPEC ");
if (options & KDB_O_NODEFAULT) printf ("KDB_O_NODEFAULT ");
if (options & KDB_O_CALLBACK) printf ("KDB_O_CALLBACK");
}

const char * getCascadingName (const char * str)
{
if (str == NULL) return "/";
const char * r = strchr (str, '/');
return r == NULL ? "/" : r;
}

Key * warnOnMeta (ELEKTRA_UNUSED KeySet * ks, ELEKTRA_UNUSED Key * key, Key * found, elektraLookupFlags options)
{
if (found != NULL && strncmp (keyName (found), "spec:/", 6) == 0 && options == KDB_O_CALLBACK)
{
const Key * meta = keyGetMeta (found, "context");
if (meta != NULL)
{
ELEKTRA_ADD_RESOURCE_WARNINGF (
key, "%s is context dependent, shown result might be wrong, -v shows you the trace to the key\n",
keyName (found));
}
}
return found;
}


Key * printTrace (ELEKTRA_UNUSED KeySet * ks, Key * key, Key * found, elektraLookupFlags options)
{
warnOnMeta (ks, key, found, options);
const char * lastKeyName = keyValue (keyGetMeta (key, "callback/print_trace/last_key_name"));
const char * name = keyName (key);
const char * rawDepth = keyValue (keyGetMeta (key, "callback/print_trace/depth"));

int depth = rawDepth == NULL ? 0 : atoi (rawDepth);
for (int i = 0; i < depth; ++i)
{
printf (" ");
}

printf ("searching %s%s", (name[0] == '/' ? "default of spec" : ""), name);
printf (", found: %s", (found != NULL ? keyName (found) : "<nothing>"));
if (options)
{
printf (", options: ");
printOptions (options);
}
printf ("\n");

int newDepth = depth;
if (elektraStrNCmp (name, "spec:/", 6) == 0 && (options & KDB_O_CALLBACK))
{
newDepth += 4;
}
else if (elektraStrCmp (getCascadingName (lastKeyName), getCascadingName (name)) != 0)
{
newDepth = depth != 0 ? depth - 2 : depth;
}
if (newDepth != depth)
{
char buff[11];
snprintf (buff, 11, "%d", newDepth);
keySetMeta (key, "callback/print_trace/depth", buff);
}
keySetMeta (key, "callback/print_trace/last_key_name", name);
return found;
}

void setCallback (Key * key, Key * (*f) (KeySet * ks, Key * key, Key * found, elektraLookupFlags flags))
{
union
{
Key * (*f) (KeySet * ks, Key * key, Key * found, elektraLookupFlags flags);
void * v;
} conversation;

conversation.f = f;
keySetBinary (key, &conversation.v, sizeof (conversation));
keySetMeta (key, "callback", "");
}
Loading

0 comments on commit 55693e4

Please sign in to comment.