Commit 22ec72d8 authored by Robert Izzard's avatar Robert Izzard
Browse files

update for gitlab markdown

parent 266b6c95
Loading
Loading
Loading
Loading
+67 −90
Original line number Diff line number Diff line
@@ -42,52 +42,11 @@ Many thanks to the authors of those amazing codes!
Contents
========

[Installation instructions](#Installation)

[Usage guide](#Usage)

0. <a href="#cdict_headers">cdict headers</a>
1. <a href="#make_cdict">Make a new cdict struct</a>
2. <a href="#free_cdict">Freeing a cdict, and perhaps its contents</a>
3. <a href="#setting_data_implicitly">Setting data in a cdict (implicit types)</a>
4. <a href="#setting_data_explicitly">Setting data in a cdict (explicit types)</a>
5. <a href="#set_nested_data">Set nested data in a cdict</a>
6. <a href="#access_nested_data">Access nested data in a cdict</a>
7. <a href="#access_data_by_loop">Access cdict data by a loop</a>
8. <a href="#cdict_to_JSON">cdict to JSON output</a>
9. <a href="#cdict_custom_formatting">Custom formatting of output</a>
10. <a href="#delete_cdict_entry">Delete a cdict entry</a>
11. <a href="#append_cdict_entry">Append data to a cdict entry</a>
12. <a href="#locate_cdict_entry">Locate a cdict entry and return it</a>
13. <a href="#sort_cdict">Sort a cdict</a>
14. <a href="#internal_functionality">Internal functionality</a>
15. <a href="#metadata">Setting metadata</a>
16. <a href="#config_and_testing">Configuration information and testing</a>
17. <a href="#error_handling">Error handling</a>
18. <a href="#parenting">Parenting</a>
19. <a href="#copy_dict">Copying a cdict</a>
20. <a href="#debugging">Debugging</a>
21. <a href="#thread_safety">Thread safety</a>
22. <a href="#speed_vs_memory">Speed vs memory</a>
23. <a href="#external_languages">External languages via JSON</a>

[FORTRAN interface](#FORTRAN)

0. <a href="#fortran_cdict_module">cdict module</a>
1. <a href="#fortran_make_cdict">Make a new cdict</a>
2. <a href="#fortran_free_cdict">Free a cdict</a>
3. <a href="#fortran_cdict_set">Set data in a cdict</a>
4. <a href="#fortran_cdict_nest">Nest data in a cdict</a>
5. <a href="#fortran_cdict_copy">Copy a cdict</a>
6. <a href="#fortran_cdict_to_JSON">cdict to JSON</a>
7. <a href="#fortran_cdict_stats">cdict stats</a>

[FORTRAN example](#FORTRAN-EXAMPLE)
[[_TOC_]]

------------------------------------------------------------

Installation
============
# Installation

Please see the INSTALL file for full installation details.

@@ -127,24 +86,23 @@ Fortunately, gcc is available to all from https://gcc.gnu.org/ and clang is at h
Please note:
If you use gcc version >=10 or clang >= 9, you should include the compiler flag `-Wno-sizeof-pointer-div` to prevent spurious warnings. This is done by default.

OSX requirements
================
## OSX requirements

Please install *gawk* (`brew install gawk`) and *timeout* (`brew install coreutils`).


------------------------------------------------------------

Usage
=====
# libcdict Usage Instructions : C

## 0. Cdict headers

0. <a id="cdict_headers"></a>Include the cdict header file in your C source code.
Include the cdict header file in your C source code.

```c
    #include <cdict/cdict.h>
```

1. <a id="make_cdict"></a>Make a new cdict struct
## 1. Make a new cdict struct

    To make a cdict called `c`, use:

@@ -158,7 +116,7 @@ Usage
    CDict_new(new_cdict,parent_cdict);
    ```

2. <a id="free_cdict"></a>Free the memory associated with a cdict struct, and any nested cdict structs,
## 2. Free the memory associated with a cdict struct, and any nested cdict structs,

      - If you just want to free the cdict `c` and any associated metadata (if set)

@@ -181,7 +139,7 @@ Usage

    Please note: if a `cdict` is freed which is pointed to as the ancestor of another `cdict` this will probaly cause an error. You should thus free cdicts in the reverse order they are accessed, or just free the ancestor (which will free its children).

3. <a id="setting_data_implicitly"></a>Setting scalars, arrays and pointers, including other cdicts, in your cdict struct, with implicit type guessing.
## 3. Setting scalars, arrays and pointers, including other cdicts, in your cdict, with implicit type guessing.

      You can set entries containing scalars, pointers and arrays into the cdict with the `CDict_set()` function. This implicitly guesses the types of the key and value you try to set as well as array sizes.

@@ -246,7 +204,7 @@ Note: Such metadata is not output as JSON.
               free_metadata_function);
    ```

    4. <a id="setting_data_explicitly"></a> Setting scalars and pointers, and arrays, in the cdict - the explicit way.
## 4. Setting scalars and pointers, and arrays, in your cdict, with explicit types.

    You can set scalars, pointers and arrays in the cdict with the functions `CDict_set_with_types(cdict,key,keytype,value,valuetype)` and `CDict_set_with_types_and_metadata(cdict,key,keytype,value,valuetype,metadata,metadata_free_function)`. These are different to `CDict_set()` in that they do not guess the data's C type, instead you must set this manually.

@@ -330,7 +288,9 @@ Note: Such metadata is not output as JSON.

    Note that all elements in the array must be of the same type (as in C). This is not a limitation, it is a design choice: when you want to have many elements of different types, you can use a cdict instead (see above).

5. <a id="set_nested_data"></a>Setting nested variables in the cdict can be done either using the above function calls, or the `CDict_nest(cdict,key,value,...)` function, where "..." is a list of keys which define the nested location (usually statically, i.e. not with `malloc` or `calloc`, allocated scalar types, e.g. numbers or strings). This is a powerful method for setting, or appending to, complicated nested cdicts quickly. Note that if a cdict entry already exists at the nested location, it will be appended if possible. In the case of numbers this means adding them, strings and arrays are concatenated, Booleans are ANDed, while pointers are incremented by casting the appending value to a ptrdiff_t and then adding it. Note that you cannot append a cdict on a cdict: such cases should be prevented using `CDict_contains(cdict,key)` or `CDict_nest_get_entry(cdict,...)`.
## 5. Set nested variables 

Setting nested variables in the cdict can be done either using the above function calls, or the `CDict_nest(cdict,key,value,...)` function, where "..." is a list of keys which define the nested location (usually statically, i.e. not with `malloc` or `calloc`, allocated scalar types, e.g. numbers or strings). This is a powerful method for setting, or appending to, complicated nested cdicts quickly. Note that if a cdict entry already exists at the nested location, it will be appended if possible. In the case of numbers this means adding them, strings and arrays are concatenated, Booleans are ANDed, while pointers are incremented by casting the appending value to a ptrdiff_t and then adding it. Note that you cannot append a cdict on a cdict: such cases should be prevented using `CDict_contains(cdict,key)` or `CDict_nest_get_entry(cdict,...)`.

    ```c
    /*
@@ -439,7 +399,9 @@ Note: Such metadata is not output as JSON.
    Static strings are likely to be more efficiently stored in memory.


6. <a id="access_nested_data"></a>Accessing nested cdict data is relatively simple. To access an entry, simply call
## 6. Accessing nested cdict data

Accessing nested cdict data is relatively simple. To access an entry, simply call

    ```c
    struct cdict_entry_t * entry =
@@ -482,7 +444,9 @@ Note: Such metadata is not output as JSON.
    ```
    If the data does not exist, an error is raised.

7.  <a id="access_entries_by_loop"></a>You can loop over the keys in a cdict, access the entries' keys and values, with code like
## 7. Access cdict entries by looping over its keys

You can loop over the keys in a cdict, access the entries' keys and values, with code like

    ```c
    /* Loop over cdict stored in cdict */
@@ -525,7 +489,9 @@ Note: Such metadata is not output as JSON.

    Note that these key/value to string functions return the number of bytes put in the string (the value string in the case they are both set), or a negative number in case of an error.

8.  <a id="cdict_to_JSON"></a><A NAME="CDict_print_JSON"></A> You can easily output a cdict's contents to a JSON buffer using. If you just want to output to stdout (the usual case), use `CDict_print_JSON()`. This takes the cdict itself as the first argument, and the second argument chooses whether to sort the cdict or not, it should be either `CDICT_JSON_SORT` or `CDICT_JSON_NO_SORT`. (It is slower to sort the cdict hence you have the option.)
## 8. cdict to JSON 

You can easily output a cdict's contents to a JSON buffer using. If you just want to output to stdout (the usual case), use `CDict_print_JSON()`. This takes the cdict itself as the first argument, and the second argument chooses whether to sort the cdict or not, it should be either `CDICT_JSON_SORT` or `CDICT_JSON_NO_SORT`. (It is slower to sort the cdict hence you have the option.)

    ```c
    /*
@@ -586,7 +552,9 @@ Note: Such metadata is not output as JSON.
    CDict_JSON_file_to_CDict(cdict,filename);
    ```

9.  <a id="cdict_custom_formatting"></a>Output formatting of keys and values is done automatically, but you can set a custom format at the same time as setting your data in place. For example, the following sets a double as a key and an int as a value, with the format strings `"%.15e"` and `"%d"` respectively. You can use `CDict_set_with_types_and_formats(cdict,key,keytype,keyformat,value,valuetype,valueformat)` and `CDict_set_with_types_formats_and_metadata(cdict,key,keytype,keyformat,value,valuetype,valueformat,metadata,metadata_free_function)`.
## 9. Custom output formatting 

Output formatting of keys and values is done automatically, but you can set a custom format at the same time as setting your data in place. For example, the following sets a double as a key and an int as a value, with the format strings `"%.15e"` and `"%d"` respectively. You can use `CDict_set_with_types_and_formats(cdict,key,keytype,keyformat,value,valuetype,valueformat)` and `CDict_set_with_types_formats_and_metadata(cdict,key,keytype,keyformat,value,valuetype,valueformat,metadata,metadata_free_function)`.

    ```c
      double r1 = 10.0;
@@ -601,7 +569,9 @@ Note: Such metadata is not output as JSON.

    ```

10. <a id="delete_cdict_entry"></a>Delete a cdict entry and its value's contents, if appropriate (e.g. if they are a pointer) with the following.
## 10. Delete cdict entry

Delete a cdict entry and its value's contents, if appropriate (e.g. if they are a pointer) with the following.

    ```c
    CDict_del_and_contents(cdict,entry,TRUE);
@@ -619,7 +589,9 @@ Note: Such metadata is not output as JSON.
    CDict_del(cdict,entry);
    ```

11. <a id="append_cdict_entry"></a>Append to a cdict entry, with given key, by value, with the following code. As with `CDict_set()` the key and value types are guessed automatically.
## 11. Append cdict entry 

Append to a cdict entry, with given key, by value, with the following code. As with `CDict_set()` the key and value types are guessed automatically.

    ```c
    CDict_append(cdict,key,value);
@@ -629,7 +601,9 @@ Note: Such metadata is not output as JSON.

    You can also use `CDict_append_with_types(cdict,key,keytype,value,valuetype)` and `CDict_append_with_types_and_metadata(cdict,key,keytype,value,valuetype,metadata,metadata_free_function)` should you require more control.

12. <a id="locate_cdict_entry"></a>Find out if the cdict contains an entry with
## 12. Locate an entry 

Find out if the cdict contains an entry with

    ```c
    /*
@@ -644,7 +618,9 @@ Note: Such metadata is not output as JSON.

    ```

13. <a id="sort_cdict"></a>Sort a cdict, e.g. prior to looping (this is implicitly done if you use `CDict_sorted_loop()`).
## 13. Sort a cdict

Sort a cdict, e.g. prior to looping (this is implicitly done if you use `CDict_sorted_loop()`).

    ```c
    /*
@@ -673,7 +649,9 @@ Note: Such metadata is not output as JSON.

    where the `sortfunc` should be defined as for the Gnu C standard-library `qsort` function.

14. <a id="internal_functionality"></a>A word on some internal functionality. Because *libcdict* automatically handles floating-point numbers, it has to make some choices. These come down to:
## 14. Internal functionality

A word on some internal functionality. Because *libcdict* automatically handles floating-point numbers, it has to make some choices. These come down to:

    -  Choosing how to put floats and doubles into hash buckets, i.e. how to "hash" them. We currently do this by truncating the precision of the float or double to the leading `n` bytes, where you can set `n` as shown below. This algorithm is not perfect [^1], but works enough of the time for reasonable choice of `n`. If you have a very large number of hash items, it makes sense to have a larger `n` so there are more buckets. If you choose `n` to be very small (< 3) there will possibly be few buckets so your hash lookups will be slow.

@@ -692,7 +670,9 @@ Note: Such metadata is not output as JSON.
    By default, we set `abseps=releps=2.0*DBL_EPSILON`, `nbytes_double=4` and `nbytes_float=3`. You may well need to use different tolerances in your projects.


15. <a id="metadata"></a>You can set metadata into cdict entries. This data can be used for anything you like, but most often it is used as a label for some kind of internal processing. Metadata is not output as JSON.
## 15. Metadata

You can set metadata into cdict entries. This data can be used for anything you like, but most often it is used as a label for some kind of internal processing. Metadata is not output as JSON.

    To set metadata when setting an item in the cdict, to set a metadata label string do something like this:

@@ -796,7 +776,8 @@ Note: Such metadata is not output as JSON.

    ```

16. <a id="config_and_testing"></a>Configuration information and testing

## 16. Configuration information and testing

    If you want to acquire information on the configuration of cdict, after running `ninja install`, and assuming your `$PATH` is set to point to wherever you decided to install *libcdict*, run the following in your terminal:

@@ -841,7 +822,7 @@ libcdict 1.31 : git 183:20230104:a731965 git@gitlab.com:rob.izzard/libcdict.git

    Note that the "--" are optional.

17. <a id="error_handling"></a>Error handling
## 17. Error handling

    In case of an error, you can set a function pointer as an error handler and set a custom data pointer for it. This means you can pass whatever you like in this pointer to the handler function, and hence deal with the error in any way you like.

@@ -877,7 +858,7 @@ libcdict 1.31 : git 183:20230104:a731965 git@gitlab.com:rob.izzard/libcdict.git
    cdict->error_data    = &my_data_structure;
    ```

18. <a id="parenting"></a>Parenting
## 18. Parenting

    You can set the parent of a cdict using the two-argument version of `CDict_new()`

@@ -899,7 +880,7 @@ libcdict 1.31 : git 183:20230104:a731965 git@gitlab.com:rob.izzard/libcdict.git

    Both `parent` and `ancestor` are `NULL` when the single-argument form of `CDict_new()` is used.

19. <a id="copy_cdict"></a>Copying a cdict
## 19. Copying a cdict

    You can use `CDict_copy()` to copy a cdict. The new cdict has its array content (e.g. strings and arrays of scalars) copied so you can delete the original cdict, if required.

@@ -909,7 +890,7 @@ libcdict 1.31 : git 183:20230104:a731965 git@gitlab.com:rob.izzard/libcdict.git
    CDict_copy(cdict,cdict_copy);
    ```

20. <a id="debugging"></a>Debugging
## 20. Debugging

    You have access to *libcdict*'s debugging API. For example, to assert that x is true, use:

@@ -930,11 +911,11 @@ libcdict 1.31 : git 183:20230104:a731965 git@gitlab.com:rob.izzard/libcdict.git
    cdict->vb = TRUE;
    ```

21. <a id="thread_safety"></a>Thread safety
## 21. Thread safety

    *libcdict* is not designed to be explicitly thread safe: you'll need to implement some kind of asyncrhonous thread-locking, e.g. with libpthread mutexes, should you wish to use a single cdict struct in multiple threads. That said, as long as you do this, it should just work: there are no problems with global variables (the only global variables are the floating-point epsilons which you will probably never change). 

22. <a id="speed_vs_memory"></a>Speed vs memory: the force_maps boolean
## 22. Speed vs memory: the force_maps boolean

    When comparing cdict keys to determine whether a path exists in a cdict, often the only way, e.g. when the keys are of different type, is to convert the keys to strings. By default these strings are stored so that further comparisons are as fast as possible. This costs RAM, however. You can change this behaviour with the cdict->force_maps boolean.

@@ -943,9 +924,9 @@ libcdict 1.31 : git 183:20230104:a731965 git@gitlab.com:rob.izzard/libcdict.git

    You should just choose which is most important to you: RAM or speed.

23. <a id="external_languages"></a>Use with external languages, e.g. *Perl* and *Python*, via JSON.
## 23. External languages via JSON

    You can export *libcdict* JSON data (see [point 8 above](#CDict_print_JSON)) to a file or buffer which can easily be imported into *Perl* or *Python*, both of which have JSON modules to do this. For example, in Python try something like this.
    You can export *libcdict* JSON data (see [point 8 above](#cdict-to-JSON)) to a file or buffer which can easily be imported into *Perl* or *Python*, both of which have JSON modules to do this. For example, in Python try something like this.
    
    ```python
    # read from a string 
@@ -1007,8 +988,7 @@ data = keys_to_floats(data)
print('keys converted to floats:',data.keys())
    ```

FORTRAN
=======
# FORTRAN

The FORTRAN module for libcdict is a set of FORTRAN interfaces that directly call the C API.
It supports the same general functionality defined above with a few limitations, namely:
@@ -1022,9 +1002,6 @@ It supports the same general functionality defined above with a few limitations,

The module requires FORTRAN 90 or higher to use iso_c_binding.

FORTRAN Usage
=============

The following functions are currently supported in the FORTRAN API:
1. CDict_new
2. CDict_copy
@@ -1036,7 +1013,9 @@ The following functions are currently supported in the FORTRAN API:

Most of the above documentation is applicable to the FORTRAN API for these methods, so please read that first. The following is a brief summary of how to call the FORTRAN subroutines and a short example of a complete program that uses libcdict in FORTRAN.

0. <a id="fortran_cdict_module"></a>Include the cdict module file (cdict_fortran_interface.f90) in your FORTRAN source code.
## 0. Fortran cdict module

Include the cdict module file (cdict_fortran_interface.f90) in your FORTRAN source code.

    First, cdict must be installed in the project directory using the above instructions. This allows `cdict_fortran_interface.f90`,`cdict_fortran_api.h`, and `libcdict.so` to be available. The module file (cdict_fortran_interface.f90) must be compiled with your FORTRAN source code and the cdict library (libcdict.so) must be linked. See the full example below to see how to do this with a Makefile.

@@ -1048,7 +1027,7 @@ Most of the above documentation is applicable to the FORTRAN API for these metho
    implicit none
    ```

1. <a id="fortran_make_cdict"></a>CDict_new
## 1. New Fortran cdict

    To make a cdict:

@@ -1066,7 +1045,7 @@ Most of the above documentation is applicable to the FORTRAN API for these metho
    c = CDict_new(p)
    ```

2. <a id="fortran_free_cdict"></a>CDict_free
## 2. Free Fortran cdict

    To free a cdict and any associated metadata (if set):

@@ -1077,7 +1056,7 @@ Most of the above documentation is applicable to the FORTRAN API for these metho
    call CDict_free(c)
    ```

3. <a id="fortran_cdict_set"></a>CDict_set
## 3. Set data in Fortran cdict 

    To set entries into a cdict:

@@ -1115,7 +1094,7 @@ Most of the above documentation is applicable to the FORTRAN API for these metho
    call CDict_set(c, trim(string_key)//C_NULL_CHAR, 100.91)
    ```

4. <a id="#fortran_cdict_nest"></a>CDict_nest
## 4. Nest data in Fortran cdict

To set nested variables in a cdict:

@@ -1132,7 +1111,7 @@ To set nested variables in a cdict:

    Note that `CDict_nest` currently has a maximum nesting depth of 2. To achieve a deeper nesting level, set a cdict inside a cdict with repeated calls to `CDict_nest`. If you know how to achieve deeper nesting in FORTRAN, please let us know!

5. <a id="#fortran_cdict_copy"></a>CDict_copy
## 5. Copy Fortran cdict

    To copy a cdict `c` into a new cdict `c_copy`, you must first make the new cdict with `CDict_new()` and then call `CDict_copy`:

@@ -1146,7 +1125,7 @@ To set nested variables in a cdict:
    call CDict_copy(c, c_copy)
    ```

6. <a id="#fortran_cdict_to_JSON"></a>CDict_print_JSON
## 6. Fortran cdict to JSON

    To print the contents of a cdict `c`, call `CDict_print_JSON()` using one of the sorting constants defined in the module:

@@ -1162,7 +1141,7 @@ To set nested variables in a cdict:

    The constants are `CDICT_JSON_SORT` and `CDICT_JSON_NO_SORT` and are defined as `.true.` and `.false.`, respectively.

7. <a id="fortran_cdict_stats"></a>CDict_stats
## 7. Fortran cdict statistics

    To print the statistics of a cdict `c`:

@@ -1173,8 +1152,7 @@ To set nested variables in a cdict:
    call CDict_stats(c)
    ```

FORTRAN EXAMPLE
===============
# FORTRAN EXAMPLE

Here is a full example of a Fortran file that uses cdicts along with a Makefile to
compile it.
@@ -1305,8 +1283,7 @@ Cdict 0x55d2cf155980 is not its own ancestor (which is 0x55d2cf155910): find the
Cdict 0x55d2cf157030 : nkeys 7, nvalues 7, max_depth 2
```

Authors
=======
# Authors

Of libcdict, Robert Izzard. 
Daniel Nemergut very kindly contributed the FORTRAN interface.