Skip to content
Merged
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
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,5 @@ target_link_libraries(yaml_c_wrapper PUBLIC ryml)
add_executable(example_rw examples/example_rw.cpp)
target_link_libraries(example_rw yaml_c_wrapper ryml)

add_executable(get_lattices src/get_lattices.cpp)
target_link_libraries(get_lattices yaml_c_wrapper ryml)
add_executable(print_lattices examples/print_lattices.cpp)
target_link_libraries(print_lattices yaml_c_wrapper ryml)
21 changes: 8 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,35 +16,31 @@ cmake -S . -B build
cmake --build build
```

This builds `libyaml_c_wrapper.dylib`, a shared object library that can interface with other languages.
This builds `libyaml_c_wrapper.dylib`, a shared object library that can interface with other languages. Make sure to rebuild after making any changes to files, and before running tests. All lattice files should go in `lattice_files/`.

It also builds an executable at build/example_rw containing examples for how
to use the library to read lattice files, perform basic manipulations, and write
to the lattice back to a file. To see the output, navigate to the build directory and run
### Example 1
`examples/example_rw.cpp` contains examples for how to use the library API to read lattice files, perform basic manipulations (adding and removing elements, renaming, etc.), print to console, and write the lattice back to a file. The example uses `ex.pals.yaml` and writes to `expand.pals.yaml`. To see the consle output, navigate to the build directory and run

```console
./example_rw
```

The program `get_lattices` will create a struct containing three lattices:
### Example 2
The program `examples/print_lattices` performs lattice expansion on a user-specified lattice. The first argument is the file name where the lattice is defined. It also takes an option argument using `-lat lattice_name` to specify a specific lattice to expand, otherwise it will choose a default (the lattice in the last `use` statement, or the last lattice in the file if none is present). The program will create and print a struct containing three lattices:
- `original` is a map containing the base lattice as well as any lattices included
in the base lattice.
- `included` is the base lattice but with all included files substituted in.
- `expanded` is the base lattice after lattice expansion has been performed.
Specify the lattice file with the first argument to the function. On default,
the lattice specified by the last `use` statement will be used, and if no `use`
statement exists, the lattice lattice in the file will be used. An optional flag
`-lat lattice_name` can be used to specify the lattice to expand, which has greatest
priority. For example, in the build directory, run
To see the console output, in the build directory, run

```console
./get_lattices ex.pals.yaml -lat lat2
./print_lattices ex.pals.yaml -lat lat2
```

## Developer Notes
`YAMLTreeHandle` wraps `ryml::Tree` into C objects so they can be part of a shared object library to interface with other languages. `ryml::Tree`s are stored in memory simply as arrays. `ryml::NodeRef` acts as a simple wrapper around nodes, which are just indices in the tree array. Trees are obtained by parsing C++ std::string, and values are simply pointers to locations in the string. Therefore, the string must be kept in memory as long as the tree is in use.

Most of the relevant ryml code for reference is contained in /build/_deps/rapidyaml-src/src/c4/yml/tree.hpp
Most of the relevant ryml code for reference is contained in `/build/_deps/rapidyaml-src/src/c4/yml/tree.hpp`.

Documentation generated by Doxygen. Run in the root directory

Expand All @@ -64,5 +60,4 @@ ctest --test-dir build -R "Test Name"
```

## To Do
Update test cases
Search by kind
58 changes: 31 additions & 27 deletions examples/example_rw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,54 +3,58 @@
#include "../src/yaml_c_wrapper.h"

int main(int argc, char* argv[]) {
std::cout << "============ Printing Developer Information ============" << std::endl;
std::string text = "Use the function 'parse_file(filename)' to read a lattice file. For example,\n\n"
"YAMLTreeHandle tree = parse_file(\"../lattice_files/ex.pals.yaml\")\n"
"reads the file 'ex.pals.yaml' into a tree named 'tree'.\n\n";
// reading a lattice from a yaml file
std::cout << text;
YAMLTreeHandle tree = parse_file("../lattice_files/ex.pals.yaml");
std::cout << "Output of example_read_write.cpp" << std::endl;

// printing to terminal
std::cout << node_to_string(tree, get_root(tree)) << std::endl << std::endl;
std::cout << "To print a tree to console, use the 'tree_to_string(tree_name)' function.\n";
std::cout << tree_to_string(tree) << std::endl << std::endl;

// type checking
// prints "handle is of type sequence: 1", 1 meaning true
std::cout << "handle is of type sequence: "
std::cout << "The root node of 'ex.pals.yaml' is a sequence, so is_sequence(tree, get_root(tree)) = "
<< is_sequence(tree, get_root(tree)) << "\n";

// accessing sequence
YAMLNodeId node = get_child_by_index(tree, get_root(tree), 0);
/* prints
the first element is:
thingB:
kind: Sextupole
*/
std::cout << "the first element is: \n"
<< node_to_string(tree, node) << "\n";
std::cout << "Elements in a sequence may be accessed by their index.\n";
YAMLNodeId seq1 = get_child_by_index(tree, get_root(tree), 0);
std::cout << "The first element of 'tree' is: \n"
<< node_to_string(tree, seq1) << "\n";

// accessing map
// prints "the value at key 'thingB' is: kind: Sextupole"
std::cout << "\nthe value at key 'thingB' is: "
<< node_to_string(tree, get_child_by_key(tree, node, "thingB"))
<< "\n";
std::cout << "Elements in a map may be accessed by their key.\n";
YAMLNodeId map1 = get_child_by_key(tree, get_child_by_index(tree, seq1, 0), "kind");
std::cout << "The element 'thingB' has:\n "
<< node_to_string(tree, map1) << "\n";

// add a new sequence element to the root containing new_map: {apples: 5}
std::cout << "Adding a new element '-apples: 5' to root.\n";
YAMLNodeId new_map_entry = add_map(tree, get_root(tree), NULL, END);
YAMLNodeId map = add_map(tree, new_map_entry, "new_map", END);
add_scalar(tree, map, "apples", "5", END);

// add a new sequence element to the root containing magnets: {magnet_list:
// [...]}
// add a new sequence element to the root containing magnets
std::cout << "Adding a new element\n"
<< " - magnet_list:\n"
<< " - magnet1\n"
<< " - magnet2\n"
<< "to root.\n\n";
YAMLNodeId magnets_entry = add_map(tree, get_root(tree), NULL, END);
YAMLNodeId magnets = add_map(tree, magnets_entry, "magnets", END);
YAMLNodeId sequence = add_sequence(tree, magnets, "magnet_list", END);
YAMLNodeId sequence = add_sequence(tree, magnets_entry, "magnet_list", END);
add_scalar(tree, sequence, NULL, "magnet1", END);
add_scalar(tree, sequence, NULL, "magnet2", 1);

// writing trees to files
std::cout << "Use 'write_file(tree, filename)' to write the edited tree to a file.\n";
write_file(tree, "../lattice_files/expand.pals.yaml");
std::cout << "Wrote tree to 'expand.pals.yaml`\n\n\n\n";

// print tree after modifications — if new nodes don't appear here the issue
// is in add_*, if they do appear but not in the file the issue is in
// write_file
std::cout << "\nTree after modifications:\n";
std::cout << node_to_string(tree, get_root(tree)) << std::endl;
std::cout << "========== Printing Final Modified Tree ==========\n";
std::cout << tree_to_string(tree) << std::endl;

bool ok = write_file(tree, "../lattice_files/expand.pals.yaml");
std::cout << "write_file returned: " << ok << std::endl;
return 0;
}
22 changes: 14 additions & 8 deletions src/get_lattices.cpp → examples/print_lattices.cpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
#include <iostream>
#include <string>
#include <ryml.hpp>
#include <ryml_std.hpp>

#include "../src/yaml_c_wrapper.h"

int main(int argc, char* argv[]) {
const char* file_name = "../lattice_files/ex.pals.yaml";
const char* file_name = nullptr;
const char* lattice_name = "";

for (int i = 1; i < argc; i++) {
Expand All @@ -21,17 +22,22 @@ int main(int argc, char* argv[]) {
}
}

struct lattices lat = get_lattices(file_name, lattice_name);

std::cout << "Printing original lattice: " << std::endl;
if (!file_name) {
std::cerr << "Usage: " << argv[0] << " <file> [-lat <lattice_name>]" << std::endl;
return 1;
}

std::string file_path = std::string("../lattice_files/") + file_name;

struct lattices lat = get_lattices(file_path.c_str(), lattice_name);

std::cout << "========== Printing original lattice ==========" << std::endl;
std::cout << tree_to_string(lat.original) << std::endl << "\n\n";

std::cout << "Printing included lattice: " << std::endl;
std::cout << "========== Printing included lattice ==========" << std::endl;
std::cout << tree_to_string(lat.included) << std::endl << "\n\n";

std::cout << "Printing expanded lattice: " << std::endl;
std::cout << "========== Printing expanded lattice ==========" << std::endl;
std::cout << tree_to_string(lat.expanded) << std::endl;

write_file(lat.expanded, "../lattice_files/expand.pals.yaml");
return 0;
}
Loading