Skip to content

Commit

Permalink
Add get_value_inplace API to basic_node (#443)
Browse files Browse the repository at this point in the history
* added get_value_inplace() to basic_node

* updated API documentation contents

* fixed some typos in doc

* added link to the documentation page for get_value_inplace()

* fixed error in building test suite with older compilers

* added test case for get_value_inplace

* fixed issue reported from codacy
  • Loading branch information
fktn-k authored Dec 15, 2024
1 parent 2b8f925 commit 5aaa028
Show file tree
Hide file tree
Showing 10 changed files with 1,110 additions and 66 deletions.
54 changes: 54 additions & 0 deletions docs/examples/ex_basic_node_get_value_inplace.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// _______ __ __ __ _____ __ __ __
// | __| |_/ | \_/ |/ _ \ / \/ \| | fkYAML: A C++ header-only YAML library (supporting code)
// | __| _ < \_ _/| ___ | _ | |___ version 0.4.0
// |__| |_| \__| |_| |_| |_|___||___|______| https://github.com/fktn-k/fkYAML
//
// SPDX-FileCopyrightText: 2023-2024 Kensuke Fukutani <fktn.dev@gmail.com>
// SPDX-License-Identifier: MIT

#include <iostream>
#include <fkYAML/node.hpp>

struct not_default_constructible {
not_default_constructible() = delete;
explicit not_default_constructible(int v) noexcept
: value(v) {
}
not_default_constructible(const not_default_constructible&) = default;

int value {0};
};
// Custom implementation of from_node() for not_default_constructible objects.
// This function is called inside get_value_inplace().
// See https://fktn-k.github.io/fkYAML/api/node_value_converter/from_node/ for details.
inline void from_node(const fkyaml::node& n, not_default_constructible& ndc) {
ndc.value = n.get_value<int>();
}

int main() {
// create a sequence node.
fkyaml::node seq = {true, false};

// fill the node values into a 1D C-style array
bool bools[2] {};
seq.get_value_inplace(bools);
for (auto b : bools) {
std::cout << std::boolalpha << b << " ";
}
std::cout << "\n\n";

// create an integer scalar node
fkyaml::node integer = 123;

// get_value_inplace() accepts a type which is not default constructible.
not_default_constructible ndc {0};
integer.get_value_inplace(ndc);
std::cout << ndc.value << std::endl;

// of course, you can pass a value of default constructible type as well.
integer = -123;
integer.get_value_inplace(ndc.value);
std::cout << ndc.value << std::endl;

return 0;
}
4 changes: 4 additions & 0 deletions docs/examples/ex_basic_node_get_value_inplace.output
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
true false

123
-123
30 changes: 18 additions & 12 deletions docs/mkdocs/docs/api/basic_node/get_value.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ template <typename BasicNodeType>
BasicNodeType get_value() const; // (2)
```
This function converts a [fkyaml::basic_node](./index.md) to either
This function converts a [`fkyaml::basic_node`](./index.md) to either
1. a compatible value ([copy-constructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible) and [default-constructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible))
The function is equivalent to executing
Expand All @@ -21,7 +21,8 @@ This function converts a [fkyaml::basic_node](./index.md) to either
return ret;
```
This library implements conversions from a node to a number of STL container types and scalar types. (see the notes down below)
Note that ValueType cannot be either a reference, pointer or C-style array type except `std::nullptr_t`.
Note that ValueType cannot be either a reference, pointer or C-style array type except `std::nullptr_t` since safe conversion is impossible with such types.
If you want to convert a node into a C-style array, consider using the [`get_value_inplace`](./get_value_inplace.md) function instead.
2. a [fkyaml::basic_node](./index.md) object
The function is equivalent to executing
```cpp
Expand All @@ -35,24 +36,24 @@ This API makes a copy of the value, and if the copying costs too much, or if you

This library implements conversions from a sequence node to a number of STL container types whose element type is not a key-value pair. The implementation can be used for custom container types, but they need to have both `iterator` member type and `insert()` member function. The test suite confirms successful conversions to the following types.

* std::vector, std::deque, std::list *(sequence containers)*
* std::set, std::multiset *(associative containers for keys)*
* std::unordered_set, std::unordered_multiset *(unordered associative containers for keys)*
* [std::vector](https://en.cppreference.com/w/cpp/container/vector), [std::deque](https://en.cppreference.com/w/cpp/container/deque), [std::list](https://en.cppreference.com/w/cpp/container/list) *(sequence containers)*
* [std::set](https://en.cppreference.com/w/cpp/container/set), [std::multiset](https://en.cppreference.com/w/cpp/container/multiset) *(associative containers for keys)*
* [std::unordered_set](https://en.cppreference.com/w/cpp/container/unordered_set), [std::unordered_multiset](https://en.cppreference.com/w/cpp/container/unordered_multiset) *(unordered associative containers for keys)*

And you can also convert to these types which do not have `insert()` member function though.

* std::array, std::valarray *(sequence containers)*
* std::stack, std::queue, std::priority_queue *(sequence container adapters)*
* std::pair, std::tuple
* [std::array](https://en.cppreference.com/w/cpp/container/array), [std::valarray](https://en.cppreference.com/w/cpp/numeric/valarray) *(sequence containers)*
* [std::stack](https://en.cppreference.com/w/cpp/container/stack), [std::queue](https://en.cppreference.com/w/cpp/container/queue), [std::priority_queue](https://en.cppreference.com/w/cpp/container/priority_queue) *(sequence container adapters)*
* [std::pair](https://en.cppreference.com/w/cpp/utility/pair), [std::tuple](https://en.cppreference.com/w/cpp/utility/tuple)

Note that the above types cannot be converted from a non-sequence node, which results in throwing a [type_error](../exception/type_error.md).

???+ Note "Convert from a Mapping Node"

This library implements conversions from a mapping node to STL container types whose element type is a key-value pair. The implementation can be used for custom container types, but they need to have `key_type`, `mapped_type` and `value_type` member types and `emplace()` member function. The test suite confirms successful conversions to the following types.

* std::map, std::multimap *(associative containers for key-value pairs)*
* std::unordered_map, std::unordered_multi_map *(unordered associative containers for key-value pairs)*
* [std::map](https://en.cppreference.com/w/cpp/container/map), [std::multimap](https://en.cppreference.com/w/cpp/container/multimap) *(associative containers for key-value pairs)*
* [std::unordered_map](https://en.cppreference.com/w/cpp/container/unordered_map), [std::unordered_multi_map](https://en.cppreference.com/w/cpp/container/unordered_multimap) *(unordered associative containers for key-value pairs)*

???+ Note "Convert from a Null or Numeric Scalar Node"

Expand All @@ -78,8 +79,12 @@ This API makes a copy of the value, and if the copying costs too much, or if you

String scalar nodes can be converted to STL container types which can be constructible from `const fkyaml::basic_node::string_type&` (`const std::string&` by default). The test suite confirms successful conversions to the following types.

* std::string
* std::string_view (from C++17)
* [std::string](https://en.cppreference.com/w/cpp/string/basic_string)
* [std::string_view](https://en.cppreference.com/w/cpp/string/basic_string_view) (from C++17)

???+ Note "Convert as an optional value"

Since C++17, [std::optional](https://en.cppreference.com/w/cpp/utility/optional) can be used as `ValueType` to indicate the conversion result to be optional. In such cases, a returned [std::optional](https://en.cppreference.com/w/cpp/utility/optional) value contains a value only if the conversion was successful, or [`std::nullopt`](https://en.cppreference.com/w/cpp/utility/optional/nullopt) otherwise.

## **Template Parameters**

Expand Down Expand Up @@ -112,5 +117,6 @@ A compatible native data value converted from the [basic_node](./index.md) objec
## **See Also**

* [basic_node](index.md)
* [get_value_inplace](get_value_inplace.md)
* [get_value_ref](get_value_ref.md)
* [node_value_converter::from_node](../node_value_converter/from_node.md)
64 changes: 64 additions & 0 deletions docs/mkdocs/docs/api/basic_node/get_value_inplace.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<small>Defined in header [`<fkYAML/node.hpp>`](https://github.com/fktn-k/fkYAML/blob/develop/include/fkYAML/node.hpp)</small>

# <small>fkyaml::basic_node::</small>get_value

```cpp
template <typename T>
void get_value_inplace(T& value_ref) const noexcept(
noexcept(ConverterType<T>::from_node(std::declval<const basic_node&>(), std::declval<T&>()))); // (1)

template <typename BasicNodeType>
void get_value_inplace(BasicNodeType& value_ref) const; // (2)
```
This function converts a [`fkyaml::basic_node`](./index.md) to either of the followings and fills the conversion result into the given `value_ref` parameter.
1. a compatible value ([copy-constructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible))
The function is equivalent to executing
```cpp
ConverterType<T>::from_node(*this, value_ref);
```
Unlike the [`get_value`](./get_value.md) function, this function does not require the template parameter type `T` to be [default-constructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible) since no instantiation of `T` is necessary inside the function to return the conversion result.
2. a [fkyaml::basic_node](./index.md) object
The function is equivalent to executing
```cpp
value_ref = *this; // Copy-assigns a current basic_node object.
```

This function shares internal implementation with the [`get_value`](./get_value.md).
Thus, all the STL container & scalar types which are supported by that function, is also supported by this function as well.
See the notes there for details.

???+ Note "Difference from `get_value()`"

One crutial difference from the [`get_value`](./get_value.md) function is, this function does not require the template parameter type `T` to be [default-constructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible) since no instantiation of `T` is necessary inside the function to return the conversion result anymore.
So, you might prefer this function, for example, if you already created a `T` object as a member variable and want to assign a node value to it.

Another is C-style array support.
While [`get_value`](./get_value.md) cannot accept any kind of C-style array types since returning such array objects is impossible due to its implementation, this function accepts 1D, 2D and 3D arrays. Note that, if `T` is one of them, the target basic_node object must be a sequence. A [`type_error`](../exception/type_error.md) is thrown otherwise.

## **Template Parameters**

***T***
: A compatible value type.

***BasicNodeType***
: A basic_node template instance type.

???+ Example

```cpp
--8<-- "examples/ex_basic_node_get_value_inplace.cpp:9"
```

output:
```bash
--8<-- "examples/ex_basic_node_get_value_inplace.output"
```

## **See Also**

* [basic_node](index.md)
* [get_value](get_value.md)
* [get_value_ref](get_value_ref.md)
* [node_value_converter::from_node](../node_value_converter/from_node.md)
21 changes: 11 additions & 10 deletions docs/mkdocs/docs/api/basic_node/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,16 +93,17 @@ This class provides features to handle YAML nodes.
| [is_string](is_string.md) | checks if a basic_node has a string node value. |
### Conversions
| Name | | Description |
| --------------------------------------- | -------- | ------------------------------------------------------------------ |
| [deserialize](deserialize.md) | (static) | deserializes the first YAML document into a basic_node. |
| [deserialize_docs](deserialize_docs.md) | (static) | deserializes all YAML documents into basic_node objects. |
| [operator>>](extraction_operator.md) | | deserializes an input stream into a basic_node. |
| [serialize](serialize.md) | (static) | serializes a basic_node into a YAML formatted string. |
| [serialize_docs](serialize_docs.md) | (static) | serializes basic_node objects into a YAML formatted string. |
| [operator<<](insertion_operator.md) | | serializes a basic_node into an output stream. |
| [get_value](get_value.md) | | converts a basic_node into a target native data type. |
| [get_value_ref](get_value_ref.md) | | converts a basic_node into reference to a target native data type. |
| Name | | Description |
| ----------------------------------------- | -------- | ----------------------------------------------------------------------- |
| [deserialize](deserialize.md) | (static) | deserializes the first YAML document into a basic_node. |
| [deserialize_docs](deserialize_docs.md) | (static) | deserializes all YAML documents into basic_node objects. |
| [operator>>](extraction_operator.md) | | deserializes an input stream into a basic_node. |
| [serialize](serialize.md) | (static) | serializes a basic_node into a YAML formatted string. |
| [serialize_docs](serialize_docs.md) | (static) | serializes basic_node objects into a YAML formatted string. |
| [operator<<](insertion_operator.md) | | serializes a basic_node into an output stream. |
| [get_value](get_value.md) | | converts a basic_node into a target type. |
| [get_value_inplace](get_value_inplace.md) | | converts a basic_node into a target type and write it to a destination. |
| [get_value_ref](get_value_ref.md) | | converts a basic_node into reference to a target type. |
### Iterators
| Name | Description |
Expand Down
1 change: 1 addition & 0 deletions docs/mkdocs/mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ nav:
- get_tag_name: api/basic_node/get_tag_name.md
- get_type: api/basic_node/get_type.md
- get_value: api/basic_node/get_value.md
- get_value_inplace: api/basic_node/get_value_inplace.md
- get_value_ref: api/basic_node/get_value_ref.md
- get_yaml_version: api/basic_node/get_yaml_version.md
- get_yaml_version_type: api/basic_node/get_yaml_version_type.md
Expand Down
Loading

0 comments on commit 5aaa028

Please sign in to comment.