- Supports v2 and v3 files. These versions are respectively used by The Legend of Zelda: Breath of the Wild and Super Mario Odyssey.
- Supports 64-bit node types which are used in Super Mario Odyssey.
- Supports both endianness. The little-endian format is used on the Switch.
- Low overhead; no dynamic memory allocation.
- API is similar to Nintendo's official BYML parser; conversions work exactly the same.
#include <byml/byml.h>
and link to the byml::byml
interface target.
const byml::Reader r{byml::Buffer{ptr, size}};
The data pointer must stay valid as long as the reader exists.
It is strongly recommended to validate the BYML by calling isValid()
before doing anything else
to avoid crashing because of malformed data.
Use getArray
or getHash
to obtain the root container:
std::optional<byml::Array> array = r.getArray();
// or
std::optional<byml::Hash> hash = r.getHash();
The reader must outlive any container or item.
You can iterate over containers and get items from them:
size_t size = container.numItems();
std::optional<ItemType> item = container.getByIndex(idx);
for (const ItemType& item : container) {
// ...
}
For arrays, ItemType is byml::ItemData. For hashes, ItemType is byml::HashItem (name + item data).
Arrays also have a subscript operator. The index is assumed to be valid.
byml::ItemData item = array[idx];
Hashes have the following extra functions:
const char* key = "actors";
std::optional<byml::ItemData> item = hash.getByKey(key);
// WARNING: the key is assumed to be valid.
byml::ItemData item = hash[key];
bool containsActors = hash.contains(key);
Hashes can be iterated on directly, with keys()
or with values()
. You get ranges of byml::HashItem
, const char*
and ItemData
respectively.
For a Hash node:
std::optional<Hash> value = item.getHash();
For an Array node:
std::optional<Array> value = item.getArray();
For a String node:
const char* value = item.getString();
For a Bool node, use getBool
. This returns true if the BYML value is non zero and false otherwise.
std::optional<bool> value = item.getBool();
For an Int node, use getInt
.
std::optional<s32> value = item.getInt();
To get an unsigned integer, use getUInt
. Int and UInt nodes are accepted. For Int nodes, the value must be greater than or equal to 0.
std::optional<u32> value = item.getUInt();
For a Float node:
std::optional<f32> value = item.getFloat();
To get a 64-bit integer, use getInt64
. Int and Int64 nodes are accepted.
std::optional<s64> value = item.getInt64();
To get a 64-bit unsigned integer, use getUInt64
. UInt, UInt64, Int and Int64 nodes are accepted. For Int and Int64 nodes, the value must be greater than or equal to 0.
std::optional<u64> value = item.getUInt64();
For a Double node:
std::optional<f64> value = item.getDouble();
The value can also be returned as a std::variant. The type of the contained value is determined by the node type.
byml::ItemData::Variant value = item.val();
Python bindings are also available thanks to pybind11. They can be installed by running pip3 install pybind11/
.
The API is pretty much the same, though there are some minor differences. You do not need to care about lifetime; the library will ensure that objects stay alive as long as needed.
import bymlplus
r = bymlplus.Reader(bymlplus.Buffer(byteslike))
It is strongly recommended to validate the BYML by calling isValid()
before doing anything else
to avoid crashing because of malformed data.
Use getArray
or getHash
to obtain the root container:
container: typing.Optional[byml.Array] = r.getArray()
# or
container: typing.Optional[byml.Hash] = r.getHash()
You can iterate over containers and get items from them:
size = len(container)
# IndexError is raised for bad indexes.
item = container[idx]
for item in container:
...
Hashes have a overloaded subscript operator that takes strings:
# KeyError is raised for bad keys.
item = container["actors"]
Hashes also support iteration and some standard dict functions: __contains__, keys, values, items.
The getXXX
functions work exactly the same as in the C++ API.
Alternatively, just use val
to get the value:
value = item.val()
# value is a bool, int, str etc. depending on the node type
Important note: because of lifetime issues, the bindings prohibit using val
for arrays and hashes.
Use getArray
or getHash
for those.
This software is licensed under the terms of the GNU General Public License, version 2 or later.