diff --git a/CMakeLists.txt b/CMakeLists.txt index 61d3ce13..5c4dd5b4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -88,20 +88,25 @@ IF (MSGPACK_32BIT) ENDIF () ENDIF () +OPTION (MSGPACK_BUILD_EXAMPLES "Build msgpack examples." ON) + IF (MSGPACK_BOOST) SET (CMAKE_CXX_FLAGS "-DMSGPACK_USE_BOOST ${CMAKE_CXX_FLAGS}") - SET (Boost_USE_STATIC_LIBS ON) # only find static libs - SET (Boost_USE_MULTITHREADED ON) - SET (Boost_USE_STATIC_RUNTIME OFF) - FIND_PACKAGE (Boost COMPONENTS chrono timer system) - IF (Boost_INCLUDE_DIRS) - INCLUDE_DIRECTORIES ( - ${Boost_INCLUDE_DIRS} - ) - ENDIF () - INCLUDE_DIRECTORIES ( - ${MSGPACK_BOOST_DIR} - ) +ENDIF () + +SET (Boost_USE_STATIC_LIBS ON) # only find static libs +SET (Boost_USE_MULTITHREADED ON) +SET (Boost_USE_STATIC_RUNTIME OFF) +FIND_PACKAGE (Boost COMPONENTS chrono context timer system) +IF (Boost_INCLUDE_DIRS) + INCLUDE_DIRECTORIES ( + ${Boost_INCLUDE_DIRS} + ) +ENDIF () +IF (MSGPACK_BOOST_DIR) + INCLUDE_DIRECTORIES ( + ${MSGPACK_BOOST_DIR} + ) ENDIF () IF (MSGPACK_CHAR_SIGN) @@ -141,7 +146,6 @@ FIND_PACKAGE (Threads) IF (GTEST_FOUND AND ZLIB_FOUND AND THREADS_FOUND) OPTION (MSGPACK_BUILD_TESTS "Build msgpack tests." ON) ENDIF () -OPTION (MSGPACK_BUILD_EXAMPLES "Build msgpack examples." ON) OPTION (MSGPACK_ENABLE_CXX "Enable C++ interface." ON) OPTION (MSGPACK_ENABLE_SHARED "Build shared libaries in addition to static libraries." ON) diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt index e447d1a2..ea3c7db2 100644 --- a/example/CMakeLists.txt +++ b/example/CMakeLists.txt @@ -2,3 +2,4 @@ ADD_SUBDIRECTORY (c) ADD_SUBDIRECTORY (cpp03) ADD_SUBDIRECTORY (cpp11) ADD_SUBDIRECTORY (boost) +ADD_SUBDIRECTORY (x3) diff --git a/example/cpp03/CMakeLists.txt b/example/cpp03/CMakeLists.txt index 6fee0cc2..1fa2ade4 100644 --- a/example/cpp03/CMakeLists.txt +++ b/example/cpp03/CMakeLists.txt @@ -22,13 +22,11 @@ IF (NOT MSVC) ) ENDIF () -IF (MSGPACK_BOOST) - IF (NOT MSVC) - LIST (APPEND with_boost_lib_PROGRAMS - speed_test.cpp - speed_test_nested_array.cpp - ) - ENDIF () +IF (Boost_TIMER_LIBRARY AND Boost_CHRONO_LIBRARY AND Boost_SYSTEM_LIBRARY) + LIST (APPEND with_boost_lib_PROGRAMS + speed_test.cpp + speed_test_nested_array.cpp + ) ENDIF () FOREACH (source_file ${exec_PROGRAMS}) @@ -56,10 +54,10 @@ FOREACH (source_file ${with_pthread_PROGRAMS}) ${source_file} ) TARGET_LINK_LIBRARIES (${source_file_we} - pthread + ${CMAKE_THREAD_LIBS_INIT} ) IF ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") - SET_PROPERTY (TARGET ${source_file_we} APPEND_STRING PROPERTY COMPILE_FLAGS "-Wall -Wextra -Werror -g -O3 -pthread") + SET_PROPERTY (TARGET ${source_file_we} APPEND_STRING PROPERTY COMPILE_FLAGS "-Wall -Wextra -Werror -g -O3") ENDIF () IF ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") IF (CMAKE_CXX_FLAGS MATCHES "/W[0-4]") diff --git a/example/x3/CMakeLists.txt b/example/x3/CMakeLists.txt new file mode 100644 index 00000000..f4b944f1 --- /dev/null +++ b/example/x3/CMakeLists.txt @@ -0,0 +1,64 @@ +IF (MSGPACK_USE_X3_PARSE) + INCLUDE_DIRECTORIES ( + ../include + ) + + LIST (APPEND exec_PROGRAMS + unpack.cpp + parse.cpp + ) + IF (Boost_CONTEXT_LIBRARY AND Boost_SYSTEM_LIBRARY AND CMAKE_THREAD_LIBS_INIT) + LIST (APPEND with_boost_PROGRAMS + stream_unpack.cpp + ) + ENDIF () + FOREACH (source_file ${exec_PROGRAMS}) + GET_FILENAME_COMPONENT (source_file_we ${source_file} NAME_WE) + ADD_EXECUTABLE ( + ${source_file_we} + ${source_file} + ) + IF ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + SET_PROPERTY (TARGET ${source_file_we} APPEND_STRING PROPERTY COMPILE_FLAGS "-Wall -Wextra -Werror -g ") + ENDIF () + + IF ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + SET_PROPERTY (TARGET ${source_file_we} APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-mismatched-tags") + ENDIF () + + IF ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") + IF (CMAKE_CXX_FLAGS MATCHES "/W[0-4]") + STRING(REGEX REPLACE "/W[0-4]" "/W3 /WX" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") + ELSE () + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W3 /WX") + ENDIF () + ENDIF () + ENDFOREACH () + FOREACH (source_file ${with_boost_PROGRAMS}) + GET_FILENAME_COMPONENT (source_file_we ${source_file} NAME_WE) + ADD_EXECUTABLE ( + ${source_file_we} + ${source_file} + ) + TARGET_LINK_LIBRARIES (${source_file_we} + ${Boost_CONTEXT_LIBRARY} + ${Boost_SYSTEM_LIBRARY} + ${CMAKE_THREAD_LIBS_INIT} + ) + IF ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + SET_PROPERTY (TARGET ${source_file_we} APPEND_STRING PROPERTY COMPILE_FLAGS "-Wall -Wextra -Werror -g ") + ENDIF () + + IF ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + SET_PROPERTY (TARGET ${source_file_we} APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-mismatched-tags") + ENDIF () + + IF ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") + IF (CMAKE_CXX_FLAGS MATCHES "/W[0-4]") + STRING(REGEX REPLACE "/W[0-4]" "/W3 /WX" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") + ELSE () + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W3 /WX") + ENDIF () + ENDIF () + ENDFOREACH () +ENDIF () diff --git a/example/x3/parse.cpp b/example/x3/parse.cpp new file mode 100644 index 00000000..6ee1b3e8 --- /dev/null +++ b/example/x3/parse.cpp @@ -0,0 +1,119 @@ +// MessagePack for C++ example +// +// Copyright (C) 2017 KONDO Takatoshi +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#include +#include +#include + +// MSGPACK_USE_X3_PARSE should be defined before including msgpack.hpp +// It usually defined as a compiler option as -DMSGPACK_USE_X3_PARSE. + +#include + +struct json_like_visitor : msgpack::v2::null_visitor { + json_like_visitor(std::string& s):m_s(s) {} + + bool visit_nil() { + m_s += "null"; + return true; + } + bool visit_boolean(bool v) { + if (v) m_s += "true"; + else m_s += "false"; + return true; + } + bool visit_positive_integer(uint64_t v) { + std::stringstream ss; + ss << v; + m_s += ss.str(); + return true; + } + bool visit_negative_integer(int64_t v) { + std::stringstream ss; + ss << v; + m_s += ss.str(); + return true; + } + bool visit_float(double v) { + std::stringstream ss; + ss << v; + m_s += ss.str(); + return true; + } + bool visit_str(const char* v, uint32_t size) { + m_s += '"' + std::string(v, size) + '"'; + return true; + } + bool start_array(uint32_t /*num_elements*/) { + m_s += "["; + return true; + } + bool end_array_item() { + m_s += ","; + return true; + } + bool end_array() { + m_s.erase(m_s.size() - 1, 1); // remove the last ',' + m_s += "]"; + return true; + } + bool start_map(uint32_t /*num_kv_pairs*/) { + m_s += "{"; + return true; + } + bool end_map_key() { + m_s += ":"; + return true; + } + bool end_map_value() { + m_s += ","; + return true; + } + bool end_map() { + m_s.erase(m_s.size() - 1, 1); // remove the last ',' + m_s += "}"; + return true; + } + void parse_error(size_t /*parsed_offset*/, size_t /*error_offset*/) { + } + void insufficient_bytes(size_t /*parsed_offset*/, size_t /*error_offset*/) { + } + std::string& m_s; +}; + +int main() { + std::stringstream ss; + std::map> v1 { + { "ABC", { 1, 2, 3 } }, + { "DEFG", { 4, 5 } } + }; + std::vector v2 { + "HIJ", "KLM", "NOP" + }; + msgpack::pack(ss, v1); + msgpack::pack(ss, v2); + + std::string const& buf = ss.str(); + auto it = buf.begin(); + auto end = buf.end(); + { + std::string str; + bool ret = msgpack::parse(it, end, json_like_visitor(str)); + // it is updated here. + assert(ret); + std::cout << str << std::endl; + } + { + std::string str; + bool ret = msgpack::parse(it, end, json_like_visitor(str)); + // it is updated here. + assert(ret); + std::cout << str << std::endl; + } +} diff --git a/example/x3/stream_unpack.cpp b/example/x3/stream_unpack.cpp new file mode 100644 index 00000000..ccfd9afe --- /dev/null +++ b/example/x3/stream_unpack.cpp @@ -0,0 +1,239 @@ +// MessagePack for C++ example +// +// Copyright (C) 2017 KONDO Takatoshi +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#include +#include +#include +#include + +// MSGPACK_USE_X3_PARSE should be defined before including msgpack.hpp +// It usually defined as a compiler option as -DMSGPACK_USE_X3_PARSE. + +//#define MSGPACK_USE_X3_PARSE + +#include + +#include +#include +#include + + +namespace as = boost::asio; +namespace x3 = boost::spirit::x3; +namespace coro2 = boost::coroutines2; + +using pull_type = coro2::asymmetric_coroutine>>::pull_type; + +// iterator fetching data from coroutine2. +class buffered_iterator : public std::iterator { +public: + using pointer_t = typename iterator::pointer; + using reference_t = typename iterator::reference; + + explicit buffered_iterator(pull_type& source) noexcept + : source_{ &source } { + fetch_(); + } + buffered_iterator() = default; + + bool operator==(buffered_iterator const& other) const noexcept { + if (!other.source_ && !source_ && !other.buf_ && !buf_) return true; + return other.it_ == it_; + } + + bool operator!=(buffered_iterator const& other) const noexcept { + return !(other == *this); + } + + buffered_iterator & operator++() { + increment_(); + return * this; + } + + buffered_iterator operator++(int) = delete; + + reference_t operator*() noexcept { + return *it_; + } + + pointer_t operator->() noexcept { + return std::addressof(*it_); + } + +private: + void fetch_() noexcept { + BOOST_ASSERT( nullptr != source_); + if (*source_) { + buf_ = source_->get(); + it_ = buf_->begin(); + } + else { + source_ = nullptr; + buf_.reset(); + } + } + + void increment_() { + BOOST_ASSERT( nullptr != source_); + BOOST_ASSERT(*source_); + if (++it_ == buf_->end()) { + (*source_)(); + fetch_(); + } + } + +private: + pull_type* source_{ nullptr }; + std::shared_ptr> buf_; + std::vector::iterator it_; +}; + +// session class that corresponding to each client +class session : public std::enable_shared_from_this { +public: + session(as::ip::tcp::socket socket) + : socket_(std::move(socket)) { + } + + void start() { + sink_ = std::make_shared>>::push_type>( + [&, this](pull_type& source) { + // *1 is started when the first sink is called. + + std::cout << "session started" << std::endl; + do_read(); + source(); + + // use buffered_iterator here + // b is incremented in msgpack::unpack() and fetch data from sink + // via coroutine2 mechanism + auto b = boost::spirit::make_default_multi_pass(buffered_iterator(source)); + auto e = boost::spirit::make_default_multi_pass(buffered_iterator()); + + // This is usually an infinity look, but for test, loop is finished when + // two message pack data is processed. + for (int i = 0; i != 2; ++i) { + auto oh = msgpack::unpack(b, e); + std::cout << oh.get() << std::endl; + } + } + ); + // send dummy data to start *1 + (*sink_)({}); + } + +private: + void do_read() { + std::cout << "session do_read() is called" << std::endl; + auto self(shared_from_this()); + auto data = std::make_shared>(static_cast(max_length)); + socket_.async_read_some( + boost::asio::buffer(*data), + [this, self, data] + (boost::system::error_code ec, std::size_t length) { + if (!ec) { + data->resize(length); + (*sink_)(data); + do_read(); + } + } + ); + } + + as::ip::tcp::socket socket_; + static constexpr std::size_t const max_length = 1024; + std::shared_ptr>>::push_type> sink_; +}; + +class server { +public: + server( + as::io_service& ios, + std::uint16_t port) + : acceptor_(ios, as::ip::tcp::endpoint(as::ip::tcp::v4(), port)), + socket_(ios) { + do_accept(); + std::cout << "server start accept" << std::endl; + ios.run(); + } + +private: + void do_accept() { + acceptor_.async_accept( + socket_, + [this](boost::system::error_code ec) { + if (!ec) { + std::make_shared(std::move(socket_))->start(); + } + // for test, only one session is accepted. + // do_accept(); + } + ); + } + + as::ip::tcp::acceptor acceptor_; + as::ip::tcp::socket socket_; +}; + +int main() { + std::thread srv( + []{ + boost::asio::io_service ios; + server s(ios, 12345); + } + ); + + std::thread cli( + []{ + std::this_thread::sleep_for(std::chrono::seconds(1)); + std::cout << "client start" << std::endl; + + std::stringstream ss; + std::map> v1 { + { "ABC", { 1, 2, 3 } }, + { "DEFG", { 4, 5 } } + }; + std::vector v2 { + "HIJ", "KLM", "NOP" + }; + msgpack::pack(ss, v1); + msgpack::pack(ss, v2); + + auto send_data = ss.str(); + + boost::asio::io_service ios; + as::ip::tcp::resolver::query q("127.0.0.1", "12345"); + as::ip::tcp::resolver r(ios); + auto it = r.resolve(q); + + std::cout << "client connect" << std::endl; + as::ip::tcp::socket s(ios); + as::connect(s, it); + + + std::size_t const size = 5; + std::size_t rest = send_data.size(); + std::size_t index = 0; + while (rest != 0) { + std::cout << "client send data" << std::endl; + auto send_size = size < rest ? size : rest; + as::write(s, as::buffer(&send_data[index], send_size)); + rest -= send_size; + index += send_size; + std::cout << "client wait" << std::endl; + std::this_thread::sleep_for(std::chrono::seconds(1)); + } + } + ); + + cli.join(); + std::cout << "client joinded" << std::endl; + srv.join(); + std::cout << "server joinded" << std::endl; +} diff --git a/example/x3/unpack.cpp b/example/x3/unpack.cpp new file mode 100644 index 00000000..8200c663 --- /dev/null +++ b/example/x3/unpack.cpp @@ -0,0 +1,43 @@ +// MessagePack for C++ example +// +// Copyright (C) 2017 KONDO Takatoshi +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#include +#include +#include + +// MSGPACK_USE_X3_PARSE should be defined before including msgpack.hpp +// It usually defined as a compiler option as -DMSGPACK_USE_X3_PARSE. + +#include + +int main() { + std::stringstream ss; + std::map> v1 { + { "ABC", { 1, 2, 3 } }, + { "DEFG", { 4, 5 } } + }; + std::vector v2 { + "HIJ", "KLM", "NOP" + }; + msgpack::pack(ss, v1); + msgpack::pack(ss, v2); + + std::string const& buf = ss.str(); + auto it = buf.begin(); + auto end = buf.end(); + { + auto oh = msgpack::unpack(it, end); + // it is updated here. + assert(v1 == (oh.get().as>>())); + } + { + auto oh = msgpack::unpack(it, end); + assert(v2 == oh.get().as>()); + } +} diff --git a/include/msgpack/v2/x3_parse.hpp b/include/msgpack/v2/x3_parse.hpp index c58a57f4..e824c727 100644 --- a/include/msgpack/v2/x3_parse.hpp +++ b/include/msgpack/v2/x3_parse.hpp @@ -332,7 +332,7 @@ const auto mp_object_def = ) ] >> - x3:: raw [ + x3::raw [ *(x3::eps [more] >> x3::char_) >> x3::eps [done] ][ @@ -340,7 +340,8 @@ const auto mp_object_def = [](auto& ctx){ auto& app_specific = x3::get(ctx).get(); auto const& str = _attr(ctx); - app_specific.vis.visit_str(str.size() ? &str[0] : nullptr, str.size()); + std::size_t size = std::distance(str.begin(), str.end()); + app_specific.vis.visit_str(size ? &str.front() : nullptr, size); } ) ] @@ -355,7 +356,7 @@ const auto mp_object_def = ) ] >> - x3:: raw [ + x3::raw [ *(x3::eps [more] >> x3::char_) >> x3::eps [done] ][ @@ -363,7 +364,8 @@ const auto mp_object_def = [](auto& ctx){ auto& app_specific = x3::get(ctx).get(); auto const& str = _attr(ctx); - app_specific.vis.visit_str(str.size() ? &str[0] : nullptr, str.size()); + std::size_t size = std::distance(str.begin(), str.end()); + app_specific.vis.visit_str(size ? &str.front() : nullptr, size); } ) ] @@ -378,7 +380,7 @@ const auto mp_object_def = ) ] >> - x3:: raw [ + x3::raw [ *(x3::eps [more] >> x3::char_) >> x3::eps [done] ][ @@ -386,7 +388,8 @@ const auto mp_object_def = [](auto& ctx){ auto& app_specific = x3::get(ctx).get(); auto const& str = _attr(ctx); - app_specific.vis.visit_str(str.size() ? &str[0] : nullptr, str.size()); + std::size_t size = std::distance(str.begin(), str.end()); + app_specific.vis.visit_str(size ? &str.front() : nullptr, size); } ) ] @@ -401,7 +404,7 @@ const auto mp_object_def = ) ] >> - x3:: raw [ + x3::raw [ *(x3::eps [more] >> x3::char_) >> x3::eps [done] ][ @@ -409,7 +412,8 @@ const auto mp_object_def = [](auto& ctx){ auto& app_specific = x3::get(ctx).get(); auto const& str = _attr(ctx); - app_specific.vis.visit_str(str.size() ? &str[0] : nullptr, str.size()); + std::size_t size = std::distance(str.begin(), str.end()); + app_specific.vis.visit_str(size ? &str.front() : nullptr, size); } ) ] @@ -424,7 +428,7 @@ const auto mp_object_def = ) ] >> - x3:: raw [ + x3::raw [ *(x3::eps [more] >> x3::char_) >> x3::eps [done] ][ @@ -432,7 +436,8 @@ const auto mp_object_def = [](auto& ctx){ auto& app_specific = x3::get(ctx).get(); auto const& bin = _attr(ctx); - app_specific.vis.visit_bin(bin.size() ? &bin[0] : nullptr, bin.size()); + std::size_t size = std::distance(bin.begin(), bin.end()); + app_specific.vis.visit_bin(size ? &bin.front() : nullptr, size); } ) ] @@ -447,7 +452,7 @@ const auto mp_object_def = ) ] >> - x3:: raw [ + x3::raw [ *(x3::eps [more] >> x3::char_) >> x3::eps [done] ][ @@ -455,7 +460,8 @@ const auto mp_object_def = [](auto& ctx){ auto& app_specific = x3::get(ctx).get(); auto const& bin = _attr(ctx); - app_specific.vis.visit_bin(bin.size() ? &bin[0] : nullptr, bin.size()); + std::size_t size = std::distance(bin.begin(), bin.end()); + app_specific.vis.visit_bin(size ? &bin.front() : nullptr, size); } ) ] @@ -470,7 +476,7 @@ const auto mp_object_def = ) ] >> - x3:: raw [ + x3::raw [ *(x3::eps [more] >> x3::char_) >> x3::eps [done] ][ @@ -478,7 +484,8 @@ const auto mp_object_def = [](auto& ctx){ auto& app_specific = x3::get(ctx).get(); auto const& bin = _attr(ctx); - app_specific.vis.visit_bin(bin.size() ? &bin[0] : nullptr, bin.size()); + std::size_t size = std::distance(bin.begin(), bin.end()); + app_specific.vis.visit_bin(size ? &bin.front() : nullptr, size); } ) ] @@ -577,7 +584,7 @@ const auto mp_object_def = ) ] >> - x3:: raw [ + x3::raw [ *(x3::eps [more] >> x3::char_) >> x3::eps [done] ][ @@ -585,7 +592,8 @@ const auto mp_object_def = [](auto& ctx){ auto& app_specific = x3::get(ctx).get(); auto const& ext = _attr(ctx); - app_specific.vis.visit_ext(ext.size() ? &ext[0] : nullptr, ext.size()); + std::size_t size = std::distance(ext.begin(), ext.end()); + app_specific.vis.visit_ext(size ? &ext.front() : nullptr, size); } ) ] @@ -600,7 +608,7 @@ const auto mp_object_def = ) ] >> - x3:: raw [ + x3::raw [ *(x3::eps [more] >> x3::char_) >> x3::eps [done] ][ @@ -608,7 +616,8 @@ const auto mp_object_def = [](auto& ctx){ auto& app_specific = x3::get(ctx).get(); auto const& ext = _attr(ctx); - app_specific.vis.visit_ext(ext.size() ? &ext[0] : nullptr, ext.size()); + std::size_t size = std::distance(ext.begin(), ext.end()); + app_specific.vis.visit_ext(size ? &ext.front() : nullptr, size); } ) ] @@ -623,7 +632,7 @@ const auto mp_object_def = ) ] >> - x3:: raw [ + x3::raw [ *(x3::eps [more] >> x3::char_) >> x3::eps [done] ][ @@ -631,7 +640,8 @@ const auto mp_object_def = [](auto& ctx){ auto& app_specific = x3::get(ctx).get(); auto const& ext = _attr(ctx); - app_specific.vis.visit_ext(ext.size() ? &ext[0] : nullptr, ext.size()); + std::size_t size = std::distance(ext.begin(), ext.end()); + app_specific.vis.visit_ext(size ? &ext.front() : nullptr, size); } ) ] @@ -646,7 +656,7 @@ const auto mp_object_def = ) ] >> - x3:: raw [ + x3::raw [ *(x3::eps [more] >> x3::char_) >> x3::eps [done] ][ @@ -654,7 +664,8 @@ const auto mp_object_def = [](auto& ctx){ auto& app_specific = x3::get(ctx).get(); auto const& ext = _attr(ctx); - app_specific.vis.visit_ext(ext.size() ? &ext[0] : nullptr, ext.size()); + std::size_t size = std::distance(ext.begin(), ext.end()); + app_specific.vis.visit_ext(size ? &ext.front() : nullptr, size); } ) ] @@ -669,7 +680,7 @@ const auto mp_object_def = ) ] >> - x3:: raw [ + x3::raw [ *(x3::eps [more] >> x3::char_) >> x3::eps [done] ][ @@ -677,7 +688,8 @@ const auto mp_object_def = [](auto& ctx){ auto& app_specific = x3::get(ctx).get(); auto const& ext = _attr(ctx); - app_specific.vis.visit_ext(ext.size() ? &ext[0] : nullptr, ext.size()); + std::size_t size = std::distance(ext.begin(), ext.end()); + app_specific.vis.visit_ext(size ? &ext.front() : nullptr, size); } ) ] @@ -692,7 +704,7 @@ const auto mp_object_def = ) ] >> - x3:: raw [ + x3::raw [ *(x3::eps [more] >> x3::char_) >> x3::eps [done] ][ @@ -700,7 +712,8 @@ const auto mp_object_def = [](auto& ctx){ auto& app_specific = x3::get(ctx).get(); auto const& ext = _attr(ctx); - app_specific.vis.visit_ext(ext.size() ? &ext[0] : nullptr, ext.size()); + std::size_t size = std::distance(ext.begin(), ext.end()); + app_specific.vis.visit_ext(size ? &ext.front() : nullptr, size); } ) ] @@ -715,7 +728,7 @@ const auto mp_object_def = ) ] >> - x3:: raw [ + x3::raw [ *(x3::eps [more] >> x3::char_) >> x3::eps [done] ][ @@ -723,7 +736,8 @@ const auto mp_object_def = [](auto& ctx){ auto& app_specific = x3::get(ctx).get(); auto const& ext = _attr(ctx); - app_specific.vis.visit_ext(ext.size() ? &ext[0] : nullptr, ext.size()); + std::size_t size = std::distance(ext.begin(), ext.end()); + app_specific.vis.visit_ext(size ? &ext.front() : nullptr, size); } ) ] @@ -738,7 +752,7 @@ const auto mp_object_def = ) ] >> - x3:: raw [ + x3::raw [ *(x3::eps [more] >> x3::char_) >> x3::eps [done] ][ @@ -746,7 +760,8 @@ const auto mp_object_def = [](auto& ctx){ auto& app_specific = x3::get(ctx).get(); auto const& ext = _attr(ctx); - app_specific.vis.visit_ext(ext.size() ? &ext[0] : nullptr, ext.size()); + std::size_t size = std::distance(ext.begin(), ext.end()); + app_specific.vis.visit_ext(size ? &ext.front() : nullptr, size); } ) ];