Skip to content

Commit

Permalink
Merge branch 'example-u8string'
Browse files Browse the repository at this point in the history
  • Loading branch information
ToruNiina committed Jul 20, 2024
2 parents 886801d + 88aaefd commit feda835
Show file tree
Hide file tree
Showing 6 changed files with 197 additions and 2 deletions.
1 change: 1 addition & 0 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ add_subdirectory(boost_container)
add_subdirectory(boost_multiprecision)
add_subdirectory(parse_file)
add_subdirectory(reflect)
add_subdirectory(u8string)
add_subdirectory(unicode)
1 change: 1 addition & 0 deletions examples/u8string/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
u8string
5 changes: 5 additions & 0 deletions examples/u8string/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
add_executable(u8string u8string.cpp)
target_link_libraries(u8string PRIVATE toml11::toml11)
target_compile_features(u8string PRIVATE cxx_std_20)
set_target_properties(u8string PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}")
23 changes: 23 additions & 0 deletions examples/u8string/spec_example.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# This is a TOML document

title = "TOML Example"

[owner]
name = "Tom Preston-Werner"
dob = 1979-05-27T07:32:00-08:00

[database]
enabled = true
ports = [ 8000, 8001, 8002 ]
data = [ ["delta", "phi"], [3.14] ]
temp_targets = { cpu = 79.5, case = 72.0 }

[servers]

[servers.alpha]
ip = "10.0.0.1"
role = "frontend"

[servers.beta]
ip = "10.0.0.2"
role = "backend"
120 changes: 120 additions & 0 deletions examples/u8string/u8string.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
#include <toml.hpp>

#include <iostream>
#include <map>

#include <cassert>

struct u8config
{
using comment_type = toml::preserve_comments;

using boolean_type = bool;
using integer_type = std::int64_t;
using floating_type = double;
using string_type = std::u8string; // XXX

template<typename T>
using array_type = std::vector<T>;
template<typename K, typename T>
using table_type = std::unordered_map<K, T>;

static toml::result<integer_type, toml::error_info>
parse_int(const std::string& str, const toml::source_location src, const std::uint8_t base)
{
return toml::read_int<integer_type>(str, src, base);
}
static toml::result<floating_type, toml::error_info>
parse_float(const std::string& str, const toml::source_location src, const bool is_hex)
{
return toml::read_float<floating_type>(str, src, is_hex);
}
};

int main()
{
const auto root = toml::parse<u8config>("spec_example.toml");

// using member functions
{
assert(root.at(u8"title").as_string() == u8"TOML Example");

assert(root.at(u8"owner").at(u8"name").as_string() == u8"Tom Preston-Werner");

const auto dob = root.at(u8"owner").at(u8"dob" ).as_offset_datetime();
assert(dob.date .year == 1979);
assert(dob.date .month == static_cast<int>(toml::month_t::May));
assert(dob.date .day == 27);
assert(dob.time .hour == 7);
assert(dob.time .minute == 32);
assert(dob.time .second == 0);
assert(dob.offset.hour == -8);
assert(dob.offset.minute == 0);

assert(root.at(u8"database").at(u8"enabled").as_boolean());
assert(root.at(u8"database").at(u8"ports").at(0).as_integer() == 8000);
assert(root.at(u8"database").at(u8"ports").at(1).as_integer() == 8001);
assert(root.at(u8"database").at(u8"ports").at(2).as_integer() == 8002);
assert(root.at(u8"database").at(u8"data").at(0).at(0).as_string() == u8"delta");
assert(root.at(u8"database").at(u8"data").at(0).at(1).as_string() == u8"phi");
assert(root.at(u8"database").at(u8"data").at(1).at(0).as_floating() == 3.14);
assert(root.at(u8"database").at(u8"temp_targets").at(u8"cpu" ).as_floating() == 79.5);
assert(root.at(u8"database").at(u8"temp_targets").at(u8"case").as_floating() == 72.0);

assert(root.at(u8"servers").at(u8"alpha").at(u8"ip" ).as_string() == u8"10.0.0.1");
assert(root.at(u8"servers").at(u8"alpha").at(u8"role").as_string() == u8"frontend");
assert(root.at(u8"servers").at(u8"beta" ).at(u8"ip" ).as_string() == u8"10.0.0.2");
assert(root.at(u8"servers").at(u8"beta" ).at(u8"role").as_string() == u8"backend");
}

// using toml::find
{
// you can get as std::string from u8string, using toml::get/find
assert(toml::find<std::string>(root, u8"title") == "TOML Example");

assert(toml::find<std::string>(root, u8"owner", u8"name") == "Tom Preston-Werner");

const auto dob = toml::find<toml::offset_datetime>(root, u8"owner", u8"dob");
assert(dob.date .year == 1979);
assert(dob.date .month == static_cast<int>(toml::month_t::May));
assert(dob.date .day == 27);
assert(dob.time .hour == 7);
assert(dob.time .minute == 32);
assert(dob.time .second == 0);
assert(dob.offset.hour == -8);
assert(dob.offset.minute == 0);

assert(toml::find<bool>(root, u8"database", u8"enabled"));

const auto ports = toml::find<std::vector<int>>(root, u8"database", u8"ports");
assert(ports.at(0) == 8000);
assert(ports.at(1) == 8001);
assert(ports.at(2) == 8002);

const auto data = toml::find<std::pair<std::vector<std::string>, std::vector<double>>>(root, u8"database", u8"data");
assert(data.first.at(0) == "delta");
assert(data.first.at(1) == "phi");
assert(data.second.at(0) == 3.14);

const auto temp_targets = toml::find<std::map<std::string, double>>(root, u8"database", u8"temp_targets");
assert(temp_targets.at("cpu" ) == 79.5);
assert(temp_targets.at("case") == 72.0);

const auto servers = toml::find<std::map<std::string, std::map<std::string, std::string>>>(root, u8"servers");
assert(servers.at("alpha").at("ip" ) == "10.0.0.1");
assert(servers.at("alpha").at("role") == "frontend");
assert(servers.at("beta" ).at("ip" ) == "10.0.0.2");
assert(servers.at("beta" ).at("role") == "backend" );
}

const std::u8string out = toml::format(root);

std::string printable;
std::transform(out.begin(), out.end(), std::back_inserter(printable),
[](const char8_t c) {return static_cast<char>(c);});
std::cout << printable << std::endl;

std::cout << "ok." << std::endl;

return 0;
}
49 changes: 47 additions & 2 deletions include/toml11/get.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -218,16 +218,33 @@ template<typename T, typename TC>
cxx::enable_if_t<detail::is_std_tuple<T>::value, T>
get(const basic_value<TC>&);

// map-like
// std::map<key, value> (key is convertible from toml::value::key_type)
template<typename T, typename TC>
cxx::enable_if_t<cxx::conjunction<
detail::is_map<T>, // T is map
detail::is_not_toml_type<T, basic_value<TC>>, // but not toml::table
std::is_convertible<typename basic_value<TC>::key_type,
typename T::key_type>, // keys are convertible
cxx::negation<detail::has_from_toml_method<T, TC>>, // no T.from_toml()
cxx::negation<detail::has_specialized_from<T>>, // no toml::from<T>
cxx::negation<std::is_constructible<T, const basic_value<TC>&>>
>::value, T>
get(const basic_value<TC>&);
get(const basic_value<TC>& v);

// std::map<key, value> (key is not convertible from toml::value::key_type, but
// is a std::basic_string)
template<typename T, typename TC>
cxx::enable_if_t<cxx::conjunction<
detail::is_map<T>, // T is map
detail::is_not_toml_type<T, basic_value<TC>>, // but not toml::table
cxx::negation<std::is_convertible<typename basic_value<TC>::key_type,
typename T::key_type>>, // keys are NOT convertible
detail::is_1byte_std_basic_string<typename T::key_type>, // is std::basic_string
cxx::negation<detail::has_from_toml_method<T, TC>>, // no T.from_toml()
cxx::negation<detail::has_specialized_from<T>>, // no toml::from<T>
cxx::negation<std::is_constructible<T, const basic_value<TC>&>>
>::value, T>
get(const basic_value<TC>& v);

// toml::from<T>::from_toml(v)
template<typename T, typename TC>
Expand Down Expand Up @@ -384,10 +401,13 @@ get(const basic_value<TC>& v)
// ============================================================================
// map-like types; most likely STL map, like std::map or std::unordered_map.

// key is convertible from toml::value::key_type
template<typename T, typename TC>
cxx::enable_if_t<cxx::conjunction<
detail::is_map<T>, // T is map
detail::is_not_toml_type<T, basic_value<TC>>, // but not toml::table
std::is_convertible<typename basic_value<TC>::key_type,
typename T::key_type>, // keys are convertible
cxx::negation<detail::has_from_toml_method<T, TC>>, // no T.from_toml()
cxx::negation<detail::has_specialized_from<T>>, // no toml::from<T>
cxx::negation<std::is_constructible<T, const basic_value<TC>&>>
Expand All @@ -409,6 +429,31 @@ get(const basic_value<TC>& v)
return m;
}

// key is NOT convertible from toml::value::key_type but std::basic_string
template<typename T, typename TC>
cxx::enable_if_t<cxx::conjunction<
detail::is_map<T>, // T is map
detail::is_not_toml_type<T, basic_value<TC>>, // but not toml::table
cxx::negation<std::is_convertible<typename basic_value<TC>::key_type,
typename T::key_type>>, // keys are NOT convertible
detail::is_1byte_std_basic_string<typename T::key_type>, // is std::basic_string
cxx::negation<detail::has_from_toml_method<T, TC>>, // no T.from_toml()
cxx::negation<detail::has_specialized_from<T>>, // no toml::from<T>
cxx::negation<std::is_constructible<T, const basic_value<TC>&>>
>::value, T>
get(const basic_value<TC>& v)
{
using key_type = typename T::key_type;
using mapped_type = typename T::mapped_type;

T m;
for(const auto& kv : v.as_table())
{
m.emplace(detail::string_conv<key_type>(kv.first), get<mapped_type>(kv.second));
}
return m;
}

// ============================================================================
// user-defined, but convertible types.

Expand Down

0 comments on commit feda835

Please sign in to comment.