The libparamset is a software development kit, written in plain C, for handling command-line parameters and program tasks. Parameters can be read from command line and a task can be extracted that matches with the given input. Process is covered with error detection and functions that generate helpful feedback messages to the user.
The libparamset provides the following functionality:
- Parameters can be parsed from command line, read from configuration file, or inserted from the code.
- Short and long parameters are recognised (
-aand--long). - Concatenating of flags with length 1 (
-abinstead of-a -b). - One alias for the parameter name (e.g.
--loadand-lor--versionand--VERSION). - Individual parsing options for parameters:
- Parameter with multiple coexisting values (
-a v1 -a v2 ... -a vn, where-a = {v1, v2, ..., vn}). - Parameter that never takes a value (
-a v1 -a -a, where-a = {NULL, NULL, NULL}andv1is unknown token). - Parameter that always takes a value (
-a -a, where-a = {-a}). - Existing parameter break that takes next token as it's value only if it's not an existing parameter.
- Possible parameter break that takes next token as it's value only if it does not look like possible parameter (
-a v1 -a -b, where-a = {v1, NULL}). - Parameter value sequence with (existing or possible) parameter break (
-a v1 v2 ... vn -b, where-a = {v1, v2, ..., vn}). - Parameter that is hidden from the command line but can be inserted from the code or configuration file.
- Parameter that does not generate any typo errors (useful when hiding a parameter from command line).
- Value collectors:
- Parameter
--, that will redirect every next token to a specified parameter(s). - Parameter that collects values that are not bound with any parameter (
-i x y ..., wherexis bound with-ibutyis not). - Parameter that collects all unknown parameters (
--unknown unknown, where--unknownis collected andunknownis unknown token). - Individual collector count limiters (e.g. no more than
5values).
- Parameter
- Parameter with multiple coexisting values (
- Values can be filtered by name (e.g.
-iasiand--longaslong), source (e.g.default), priority (e.g.3) and index (0 - n). - Values can be counted by name, source and priority (e.g.
3). - Values can be filtered as the last or the first with the highest or the lowest priority.
- Values can be counted as the highest or the lowest priority.
- Parameter default name that is shown in error messages (print name) can be replaced with custom string (constant or generated).
- Auto-generated typo suggestions (e.g. Did You mean
--longinstead of--song?). - Auto-generated unknown parameter error messages.
- Abstract format and content check functionality with auto-generated error messages.
- Abstract parameter transformation or repair functionality.
- Abstract Wildcard expander (can be used to make
-i *work on Windows).- Implemented wildcards for Windows file system.
- Abstract object parsing functionality (e.g. extract double or file).
- Multiple parameter sets can be merged.
- Task set, composed of multiple tasks, where from a task can be extracted by specified parameter set.
- Auto-generated suggestions between multiple tasks for the user when it is not possible to resolve which task the user wants to perform.
- Auto-generated suggestions how to fix the task user tries to perform.
- Parameters can be bound with description and formatted to human readable list for help text.
The API full reference is available here https://guardtime.github.io/libparamset/.
To use libparamset in your C/C++ project, link it against the libparamset binary.
In order to install the libparamset on CentOS/RHEL:
cd /etc/yum.repos.d
# In case of RHEL/CentOS 7
sudo curl -O https://download.guardtime.com/ksi/configuration/guardtime.el7.repo
# In case of RHEL/CentOS 8
sudo curl -O https://download.guardtime.com/ksi/configuration/guardtime.el8.repo
# In case of RHEL/CentOS 9
sudo curl -O https://download.guardtime.com/ksi/configuration/guardtime.el9.repo
yum install libparamset
In order to install the libparamset on Debian / Ubuntu:
# Add Guardtime pgp key.
sudo curl https://download.guardtime.com/ksi/GUARDTIME-GPG-KEY-2 | sudo apt-key add -
# In case of Debian 12 (Bookworm)
sudo curl -o /etc/apt/sources.list.d/guardtime.list https://download.guardtime.com/ksi/configuration/guardtime.bookworm.list
sudo apt update
apt-get install libparamset
In order to install the libparamset on OS X:
brew tap guardtime/ksi
brew install libparamset
If the latest version is needed or the package is not available for the platform you are using, check out source code from Github and build it using gcc or VS. To build the libparamset, you need to have gcc and autotools. For building in Windows you need the Windows SDK.
- Include
param_set.handtask_def.h. - Configure parameters:
- Create new
PARAM_SETobject with set of parametersPARAM_SET_new. - Add implementations for format, control (and convert) functions with
PARAM_SET_addControl. - Add implementation for wildcard expander (e.g. to implement wildcards when getting file input on Windows
-i *.txt)PARAM_SET_setWildcardExpander. - Add parsing options for parameters with
PARAM_SET_setParseOptions.
- Create new
- Configure tasks:
- Create new
TASK_SETobject withTASK_SET_new. - Add task definitions to the
TASK_SETwithTASK_SET_add.
- Create new
- Get parameters:
- Parse command line with
PARAM_SET_parseCMD. - Read parameters from configuration file with
PARAM_SET_readFromFile. - Check and report user if configuration file contained some syntax errors with
PARAM_SET_isSyntaxErrorandPARAM_SET_syntaxErrorsToString. - Merge different
PARAM_SETobjects withPARAM_SET_IncludeSet. - Check for unknown parameters and typos with
PARAM_SET_isUnknownandPARAM_SET_isTypoFailure. - Check for invalid parameters that failed format or content checks with
PARAM_SET_isFormatOK. - If there are some errors, help user with error messages by using following functions:
PARAM_SET_unknownsToString,PARAM_SET_typosToStringandPARAM_SET_invalidParametersToString.
- Parse command line with
- Analyze task set against given input:
- Analyze the
TASK_SETagainstPARAM_SETwithTASK_SET_analyzeConsistency. - Extract consistent task from
TASK_SETwithTASK_SET_getConsistentTask. - In case of failure, check if there is an invalid task that stands out from the others and give user some hints how to fix it with functions
TASK_SET_isOneFromSetTheTargetandTASK_SET_howToRepair_toString. When it's hard to distinguish which task user is trying to accomplish, give some suggestions that do have the most similar pattern to the given input withTASK_SET_suggestions_toString.
- Analyze the
- Use functions
TASK_getIDandTASK_getSetand perform the selected task:- To check if a parameter is set, use function
PARAM_SET_isSetByName. - To get parameters value from the set, use functions
PARAM_SET_getStrandPARAM_SET_getObj. - To get parameter value count, use function
PARAM_SET_getValueCount.
- To check if a parameter is set, use function
- Release object with
TASK_SET_freeandPARAM_SET_free.
A very basic example that illustrates how to parse the command-line options without any error handling and perform the task. See Example 2 for more advanced use case.
#include <stdio.h>
#include <param_set/param_set.h>
int main(int argc, char** argv) {
PARAM_SET *set = NULL;
char buf[0xffff];
/* Create new param_set object. */
PARAM_SET_new("{i}{o}{dump}{debug}{r}{help|h}", &set);
/* Parse command-line. */
PARAM_SET_parseCMD(set, argc, argv, NULL, 0);
/* Document options. */
PARAM_SET_setHelpText(set, "i", "file", "File input. To specify multiple input files, use -i multiple times.");
PARAM_SET_setHelpText(set, "o", "file", "Output file.");
PARAM_SET_setHelpText(set, "r", NULL, "Reverse file.");
PARAM_SET_setHelpText(set, "help", NULL, "Show help message (You are reading it right now!).");
PARAM_SET_setHelpText(set, "dump", NULL, "Dump file content.");
PARAM_SET_setHelpText(set, "debug", NULL, "Print param_setobject.");
/*
* See PARAM_SET_isSetByName, PARAM_SET_isOneOfSetByName, PARAM_SET_getStr,
* PARAM_SET_getValueCount and PARAM_SET_getObj to work with parameters.
*/
if (PARAM_SET_isSetByName(set, "h")) {
printf( "Usage:\n"
" util -i file [-r -o file][--dump]\n"
" util --debug\n\n");
printf( "Options:\n%s", PARAM_SET_helpToString(set, "i,o,r,h,dump,debug", 2, 10, 80, buf, sizeof(buf)));
} else if (PARAM_SET_isSetByName(set, "i,dump") && !PARAM_SET_isSetByName(set, "r,o,debug")) {
printf("Dump File.\n");
} else if (PARAM_SET_isSetByName(set, "i,r,o") && !PARAM_SET_isSetByName(set, "debug")) {
printf("Reverse File.\n");
} else if (PARAM_SET_isSetByName(set, "debug")) {
printf("Debug information:\n%s\n", PARAM_SET_toString(set, buf, sizeof(buf)));
} else {
printf("Unknown task. Use -h to get some help.\n");
}
PARAM_SET_free(set);
}A simple example of a command-line tool that uses libparamset to specify parameter set and task set, parse the command line, handle errors and give some feedback to the user to help get things working.
#include <stdio.h>
#include <param_set/param_set.h>
#include <param_set/task_def.h>
#ifdef _WIN32
# include <param_set/wildcardexpanders.h>
#endif
enum {
VALUE_OK = 0,
VALUE_IS_NULL = 0x01,
VALUE_IS_EMPTY = 0x02,
VALUE_FILE_DOES_NOT_EXIST = 0x03,
};
int convertRepair_path(const char* arg, char* buf, unsigned len);
int isContentOk_path(const char* fname);
int isFormatOk_path(const char* fname);
const char *parameter_error_to_string(int err);
int main(int argc, char** argv, char **envp) {
PARAM_SET *set = NULL;
TASK_SET *task_set = NULL;
TASK *pTask = NULL;
char buf[1024];
char debug[0xffff];
/*
* Configure parameter set and its parameters.
* 1) Both o and i must not be NULL or empty string.
* 2) Both o and i converts '\' into '/'.
* 3) i must be a path to a file that must exist.
* 4) Next token after o and i is always bound with the flag.
* 5) All options with true or false do not bound anything.
*/
PARAM_SET_new("{i}{o}{dump}{debug}{r}{help|h}", &set);
PARAM_SET_addControl(set, "o", isFormatOk_path, NULL, convertRepair_path, NULL);
PARAM_SET_addControl(set, "i", isFormatOk_path, isContentOk_path, convertRepair_path, NULL);
PARAM_SET_setParseOptions(set, "o", PST_PRSCMD_HAS_VALUE);
PARAM_SET_setParseOptions(set, "dump,debug,h,r", PST_PRSCMD_HAS_NO_VALUE);
/* Document options. */
PARAM_SET_setHelpText(set, "i", "file", "File input. To specify multiple input files, use -i multiple times.");
PARAM_SET_setHelpText(set, "o", "file", "Output file.");
PARAM_SET_setHelpText(set, "r", NULL, "Reverse file.");
PARAM_SET_setHelpText(set, "help", NULL, "Show help message (You are reading it right now!).");
PARAM_SET_setHelpText(set, "dump", NULL, "Dump file content.");
PARAM_SET_setHelpText(set, "debug", NULL, "Print param_setobject.");
/*
* To enable Windows file system wildcards, specify the wildcard expander
* function implementation and enable parsing option that enable wildcard
* processor.
*/
#ifdef _WIN32
PARAM_SET_setWildcardExpander(set, "i", NULL, NULL, NULL, PST_WCF_Win32FileWildcard);
PARAM_SET_setParseOptions(set, "i", PST_PRSCMD_HAS_VALUE | PST_PRSCMD_EXPAND_WILDCARD);
#else
PARAM_SET_setParseOptions(set, "i", PST_PRSCMD_HAS_VALUE);
#endif
/*
* Describe different tasks:
* util -h
* util -i file_in --dump
* util -i file_in -o file_out -r
* util --debug [options, except -h]
*/
TASK_SET_new(&task_set);
TASK_SET_add(task_set, 0, "Help", "h", NULL, NULL, NULL);
TASK_SET_add(task_set, 1, "Only Dump file", "i,dump", NULL, "h,r,o,debug",NULL);
TASK_SET_add(task_set, 2, "Reverse file", "i,r,o", NULL, "h,debug", NULL);
TASK_SET_add(task_set, 3, "Debug", "debug", NULL, "h", NULL);
/* Parse command-line. */
PARAM_SET_parseCMD(set, argc, argv, NULL, 0);
/* Check for typos and unknown parameters. */
if (PARAM_SET_isTypoFailure(set)) {
printf("%s\n", PARAM_SET_typosToString(set, NULL, buf, sizeof(buf)));
goto cleanup;
} else if (PARAM_SET_isUnknown(set)){
printf("%s\n", PARAM_SET_unknownsToString(set, "Error: ", buf, sizeof(buf)));
goto cleanup;
}
/* Check for invalid values. */
if (!PARAM_SET_isFormatOK(set)) {
printf("%s\n", PARAM_SET_invalidParametersToString(set, NULL, parameter_error_to_string, buf, sizeof(buf)));
goto cleanup;
}
/* As input parameter passed all checks try to extract a consistent task. */
TASK_SET_analyzeConsistency(task_set, set, 0.2);
TASK_SET_getConsistentTask(task_set, &pTask);
/* If task is not extracted try to give user some suggestions what to do to make things work. */
if (pTask == NULL) {
int ID;
if (TASK_SET_isOneFromSetTheTarget(task_set, 0.1, &ID)) {
printf("%s", TASK_SET_howToRepair_toString(task_set, set, ID, NULL, buf, sizeof(buf)));
} else {
printf("%s", TASK_SET_suggestions_toString(task_set, 3, buf, sizeof(buf)));
}
goto cleanup;
}
/*
* Task is extracted, check which one to run.
* See PARAM_SET_isSetByName, PARAM_SET_isOneOfSetByName, PARAM_SET_getStr,
* PARAM_SET_getValueCount and PARAM_SET_getObj to work with parameters.
*/
switch(TASK_getID(pTask)) {
case 0:
printf( "Usage:\n"
" util -i file [-r -o file][--dump]\n"
" util --debug\n\n");
printf( "Options:\n%s", PARAM_SET_helpToString(set, "i,o,r,h,dump,debug", 2, 10, 80, buf, sizeof(buf)));
break;
case 1:
printf("Dump File.\n");
break;
case 2:
printf("Reverse File.\n");
break;
case 3:
printf("Debug information:\n%s\n", PARAM_SET_toString(set, debug, sizeof(debug)));
break;
default:
printf("Error.\n");
break;
}
cleanup:
TASK_SET_free(task_set);
PARAM_SET_free(set);
}
const char *parameter_error_to_string(int err) {
switch(err) {
case VALUE_OK: return "OK";
case VALUE_IS_NULL: return "Parameter must have value";
case VALUE_IS_EMPTY: return "Parameter must have content";
case VALUE_FILE_DOES_NOT_EXIST: return "File does not exist";
default: return "Unknown error";
}
}
int isFormatOk_path(const char* fname) {
if (fname == NULL) return VALUE_IS_NULL;
else if (*fname == '\0');
else return VALUE_OK;
}
int isContentOk_path(const char* fname) {
int result = 1;
FILE *f = NULL;
f = fopen(fname, "r");
result = f == NULL ? VALUE_FILE_DOES_NOT_EXIST : 0;
if (f != NULL) fclose(f);
return result;
}
int convertRepair_path(const char* arg, char* buf, unsigned len){
char *toBeReplaced = NULL;
if (arg == NULL || buf == NULL) return PST_INVALID_ARGUMENT;
strncpy(buf, arg, len - 1);
toBeReplaced = buf;
while ((toBeReplaced = strchr(toBeReplaced, '\\')) != NULL){
*toBeReplaced = '/';
toBeReplaced++;
}
return PST_OK;
}See the LICENSE file.
See the CONTRIBUTING.md file.
| Dependency | Version | License type | Source | Notes |
|---|---|---|---|---|
| CuTest | 1.5 | Zlib | Required only for testing. |
| OS / Platform | Compatibility |
|---|---|
| CentOS/RHEL 7,8,9, x86_64 architecture | Fully compatible and tested. |
| Debian 12+ | Fully compatible and tested. |
| Ubuntu | Compatible but not tested on regular basis. |
| OS X | Compatible but not tested on regular basis. |
| Windows 7, 8, 10, 11 | Compatible but not tested on a regular basis. Build combination of DLL=dll and RTL=MT(d) not supported. |