Skip to content

Commit

Permalink
0.9.2: Added struct sorting, fixes and some tests
Browse files Browse the repository at this point in the history
  • Loading branch information
attipaci committed Sep 1, 2024
1 parent 4f3ae34 commit 9de6cb0
Show file tree
Hide file tree
Showing 8 changed files with 507 additions and 55 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ README-orig.md: README.md
dox: README-orig.md

.INTERMEDIATE: Doxyfile.local
Doxyfile.local: Doxyfile
Doxyfile.local: Doxyfile Makefile
sed "s:resources/header.html::g" $< > $@

# Local documentation without specialized headers. The resulting HTML documents do not have
Expand Down
25 changes: 20 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -275,30 +275,45 @@ of them if appropriate:
You can also remove existing fields from structures using `xRemoveField()`, e.g.
```c
// Remove and then destroy the fiueld named "blah" in structure 's'.
// Remove and then destroy the field named "blah" in structure 's'.
xDestroyField(xRemoveField(s, "blah"));
```

#### Large structures

The normal `xGetField()` and `xGetSubstruct()` functions have computational costs that scale linearly with the number
of direct fields in the structure. It is not much of an issue for structures that contain dozens of fields (per layer).
For much larger structures, which have a fixed layout, there is an option for significantly faster hash-based lookup
also. E.g. instead of `xGetField()` you may use `xLookupField()`:
of direct fields in the structure. It is not much of an issue for structures that contain dozens, or even hundreds, of
fields (per layer). For much larger structures, which have a fixed layout, there is an option for a potentially much
faster hash-based lookup also. E.g. instead of `xGetField()` you may use `xLookupField()`:

```c
XStructure *s = ...

// Let's create a lookup table for all fields of 's' and all its substructures.
// Create a lookup table for all fields of 's' and all its substructures.
XLookupTable *l = xCreateLookupTable(s, TRUE);

// Now use a hash-based lookup to locate the field by name
XField *f = xLookupField(l, "subsystem:property");

...

// Once done with the lookup, destroy it.
xDestroyLookup(l);
```
Note however, that preparing the lookup table has significant _O(N)_ computational cost also. Therefore, a lookup
table is practical only if you are going to use it repeatedly, many times over. As a rule of thumb, lookups may have
the advantage if accessing fields in a structure by name hundreds of times, or more.
The same performance limitation also applies to building large structures, since the `xSetField()` and
`xSetSubstruct()` functions iterate over the existing fields to check if a prior field by the same name was already
present, and which should be removed before the new field is set (hence the time to build up a structure with _N_
fields will scale as _O(N<sup>2</sup>)_ in general). The user may consider using `xInsertField()` instead, which is
much more scalable for building large structures, since it does not check for duplicates (hence scales as _O(N)_
overall). However, `xInsertField()` also makes the ordering of fields less intuitive, and it is left up to the caller
to ensure that field names added this way are never duplicated.
#### Iterating over elements
You can easily iterate over the elements also. This is one application where you may want to know the internal layout
Expand Down
13 changes: 12 additions & 1 deletion include/xchange.h
Original file line number Diff line number Diff line change
Expand Up @@ -208,9 +208,20 @@ XField *xSetSubstruct(XStructure *s, const char *name, XStructure *substruct);
int xReduceDims(int *ndim, int *sizes);
int xReduceAllDims(XStructure *s);

// Fast field lookup
// Sorting, ordering
int xSortFields(XStructure *s, int (*cmp)(const XField **f1, const XField **f2), boolean recursive);
int xSortFieldsByName(XStructure *s, boolean recursive);
int xReverseFieldOrder(XStructure *s, boolean recursive);

// Field lookup
XLookupTable *xAllocLookup(unsigned int size);
XLookupTable *xCreateLookup(const XStructure *s, boolean recursive);
XField *xLookupField(const XLookupTable *tab, const char *id);
int xLookupPut(XLookupTable *tab, const char *prefix, const XField *field, XField **oldValue);
XField *xLookupRemove(XLookupTable *tab, const char *id);
int xLookupPutAll(XLookupTable *tab, const char *prefix, const XStructure *s, boolean recursive);
int xLookupRemoveAll(XLookupTable *tab, const char *prefix, const XStructure *s, boolean recursive);
long xLookupCount(const XLookupTable *tab);
void xDestroyLookup(XLookupTable *tab);

// Convenience field creator methods
Expand Down
Loading

0 comments on commit 9de6cb0

Please sign in to comment.