Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Units plugin #2614

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions doc/news/_preparation_next_release.md
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,10 @@ The following section lists news about the [modules](https://www.libelektra.org/
- Fixed missing Metadata in README and METADATA.ini. _(Michael Zronek)_

### Specload
### units

- The [units](https://www.libelektra.org/plugins/units) plugin provides the capability to enter values with additional SI units. The unit will be checked if it as a valid SI base-unit, additional SI prefixes will be validated and the value re-calculated to it's base-unit in respect to the prefix. _(Josef Wechselauer)_
- Work in Progress _(Josef Wechselauer)_

- The [specload](https://www.libelektra.org/plugins/specload) plugin is a special storage plugin. Instead of using a storage file
it calls an external application to request its specification. For the transfer it relies on the
Expand Down Expand Up @@ -235,6 +239,11 @@ The following section lists news about the [modules](https://www.libelektra.org/

- [cache](https://www.libelektra.org/plugins/cache) is a new global caching plugin. It uses [mmapstorage](https://www.libelektra.org/plugins/mmapstorage) as its storage backend and lazily stores keysets from previous ´kdbGet()´ calls. We added initial support for the default resolver and multifile resolver. _(Mihael Pranjić)_

### units
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

twice?


- The [units](https://www.libelektra.org/plugins/units) plugin provides the capability to enter values with additional SI units. The unit will be checked if it as a valid SI base-unit, additional SI prefixes will be validated and the value re-calculated to it's base-unit in respect to the prefix. _(Josef Wechselauer)_
- Work in Progress _(Josef Wechselauer)_

## Libraries

The text below summarizes updates to the [C (and C++)-based libraries](https://www.libelektra.org/libraries/readme) of Elektra.
Expand Down
6 changes: 6 additions & 0 deletions src/error/specification
Original file line number Diff line number Diff line change
Expand Up @@ -1345,3 +1345,9 @@ description:the contract was malformed
severity:error
ingroup:kdb
macro:MALFORMED_CONTRACT

number:214
description:value of key is not a valid SI-unit
severity:error
ingroup:plugin
module:units
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add newline

6 changes: 6 additions & 0 deletions src/plugins/units/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
include (LibAddMacros)

add_plugin (units
SOURCES units.h
units.c
TEST_README)
56 changes: 56 additions & 0 deletions src/plugins/units/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
- infos = Information about the units plugin is in keys below
- infos/author = Josef Wechselauer <e1326671@student.tuwien.ac.at>
- infos/licence = BSD
- infos/needs =
- infos/provides = check/transformation
- infos/recommends =
- infos/placements = presetstorage
- infos/status = unfinished
- infos/metadata = check/units
- infos/description = validates and transforms values entered as units

## Introduction

This plugin provides the capability to enter values with additional SI units. The unit will be checked if it as a valid SI base-unit, additional SI prefixes will be validated and the value re-calculated to it's base-unit in respect to the prefix.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's -> its


E.g. If the value **1 km** is entered, it will be checked if **m** is a valid SI unit and **k** is a valid SI prefix. If both are valid, the prefix will be used to calculate the correct value with the base unit, which would be 1000 m in this example. The value is stored without the SI unit (in this case without the **m**).

This plugin is written in C.

## Usage

## Dependencies

None.

## Examples

```sh
sudo kdb mount /tests/units.ini /tests/units ini units
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is ini needed? Otherwise use the default (by not specifying "ini")

#> Mount a config file with the units plugin

sudo kdb setmeta /tests/units check/units any
#> Check the /tests/units key for validity

kdb set /tests/units "1m"
#> Suceeds, since the value is a valid decimal with SI-unit representation.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to match with the output.


Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does kdb get now return? (also for other examples...)

kdb set /tests/units "35453.327468 µH"
#> Suceeds, since the value is a valid decimal with SI-unit representation.

kdb set /tests/units "32"
#> Throws an error: value of key is not a representation for a value with a SI-unit
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which error? (See shell recorder tests/shell/shell_recorder/tutorial_wrapper/README.md for how to specify errors)


kdb set /tests/units "12 n"
#> Throws an error: value of key is not a representation for a value with a SI-unit
#> This could be changed in a further step (see issue #1398) to be valid, as for example the user wants to enter 1k to represent 1000 without an SI-Unit.
#> For now, this is ignored as the entered units should be checked for correctness

kdb set /tests/units 432 km
#> Throws an error: quotes are expected.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expected -> needed because of the shell

```


## Limitations

None.
88 changes: 88 additions & 0 deletions src/plugins/units/units.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/**
* @file
*
* @brief Source file for the units plugin
*
* @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
*
*/

#include <kdberrors.h>
#include "units.h"
#include <regex.h>
#include <kdbhelper.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int is_valid_key(Key * key, Key * parentKey)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can be static

{
const Key * meta = keyGetMeta(key, "check/units");
if (!meta) return 1;
const char* value = keyString(key);
const char * prefix = "(Y|Z|E|P|T|G|M|k|h|da|d|c|m|µ|n|p|f|a|z|y)";
const char * unit = "?(m|g|s|A|K|mol|cd|rad|sr|Hz|N|Pa|J|W|C|V|F|Ω|Ohm|S|Wb|T|H|C|lm|lx|Bq|Gy|Sv|kat|l|L)";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

formatting broken

char regexString[256];
snprintf(regexString, sizeof regexString, "%s%s%s%s%s", "^([0-9]+)\\.?([0-9]*)\\s*", prefix, "?", unit, "$");

regex_t regex;
regmatch_t offsets;
int compile_failure = regcomp (&regex, regexString, REG_NOSUB | REG_EXTENDED | REG_NEWLINE);
if (compile_failure) return -1;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No error set when the compilation fails.

// regexec returns 0 on a successful match
int match = !(regexec (&regex, value, 0, &offsets, 0));
regfree (&regex);

if(!match) {
ELEKTRA_SET_ERRORF (214, parentKey, "Validation of key %s with value %s failed.", keyName (key), keyString (key));
}

return match;

}

int elektraUnitsGet (Plugin * handle ELEKTRA_UNUSED, KeySet * returned, Key * parentKey)
{
if (!elektraStrCmp (keyName (parentKey), "system/elektra/modules/units"))
{
KeySet * contract =
ksNew (30, keyNew ("system/elektra/modules/units", KEY_VALUE, "units plugin waits for your orders", KEY_END),
keyNew ("system/elektra/modules/units/exports", KEY_END),
keyNew ("system/elektra/modules/units/exports/get", KEY_FUNC, elektraUnitsGet, KEY_END),
keyNew ("system/elektra/modules/units/exports/set", KEY_FUNC, elektraUnitsSet, KEY_END),
#include ELEKTRA_README
keyNew ("system/elektra/modules/units/infos/version", KEY_VALUE, PLUGINVERSION, KEY_END), KS_END);
ksAppend (returned, contract);
ksDel (contract);

return ELEKTRA_PLUGIN_STATUS_SUCCESS;
}
// get all keys

return ELEKTRA_PLUGIN_STATUS_NO_UPDATE;
}

int elektraUnitsSet (Plugin * handle ELEKTRA_UNUSED, KeySet * returned ELEKTRA_UNUSED, Key * parentKey ELEKTRA_UNUSED)
{
// set all keys
// this function is optional
Key * cur;
ksRewind (returned);
while ((cur = ksNext (returned)) != NULL)
{
const Key * meta = keyGetMeta (cur, "check/units");
if (!meta) continue;
int is_valid = is_valid_key (cur, parentKey);
if (!is_valid) return ELEKTRA_PLUGIN_STATUS_ERROR;
}
return ELEKTRA_PLUGIN_STATUS_SUCCESS;
}

Plugin * ELEKTRA_PLUGIN_EXPORT
{
// clang-format off
return elektraPluginExport ("units",
ELEKTRA_PLUGIN_GET, &elektraUnitsGet,
ELEKTRA_PLUGIN_SET, &elektraUnitsSet,
ELEKTRA_PLUGIN_END);
}
21 changes: 21 additions & 0 deletions src/plugins/units/units.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/**
* @file
*
* @brief Header file for the units plugin
*
* @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
*
*/

#ifndef ELEKTRA_PLUGIN_UNITS_H
#define ELEKTRA_PLUGIN_UNITS_H

#include <kdbplugin.h>


int elektraUnitsGet (Plugin * handle, KeySet * ks, Key * parentKey);
int elektraUnitsSet (Plugin * handle, KeySet * ks, Key * parentKey);

Plugin * ELEKTRA_PLUGIN_EXPORT;

#endif