Added new example.

This commit is contained in:
Takatoshi Kondo 2017-01-09 16:13:33 +09:00
parent 4466bda819
commit c704d4bfab
8 changed files with 535 additions and 52 deletions

View File

@ -88,17 +88,22 @@ IF (MSGPACK_32BIT)
ENDIF () ENDIF ()
ENDIF () ENDIF ()
OPTION (MSGPACK_BUILD_EXAMPLES "Build msgpack examples." ON)
IF (MSGPACK_BOOST) IF (MSGPACK_BOOST)
SET (CMAKE_CXX_FLAGS "-DMSGPACK_USE_BOOST ${CMAKE_CXX_FLAGS}") SET (CMAKE_CXX_FLAGS "-DMSGPACK_USE_BOOST ${CMAKE_CXX_FLAGS}")
ENDIF ()
SET (Boost_USE_STATIC_LIBS ON) # only find static libs SET (Boost_USE_STATIC_LIBS ON) # only find static libs
SET (Boost_USE_MULTITHREADED ON) SET (Boost_USE_MULTITHREADED ON)
SET (Boost_USE_STATIC_RUNTIME OFF) SET (Boost_USE_STATIC_RUNTIME OFF)
FIND_PACKAGE (Boost COMPONENTS chrono timer system) FIND_PACKAGE (Boost COMPONENTS chrono context timer system)
IF (Boost_INCLUDE_DIRS) IF (Boost_INCLUDE_DIRS)
INCLUDE_DIRECTORIES ( INCLUDE_DIRECTORIES (
${Boost_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS}
) )
ENDIF () ENDIF ()
IF (MSGPACK_BOOST_DIR)
INCLUDE_DIRECTORIES ( INCLUDE_DIRECTORIES (
${MSGPACK_BOOST_DIR} ${MSGPACK_BOOST_DIR}
) )
@ -141,7 +146,6 @@ FIND_PACKAGE (Threads)
IF (GTEST_FOUND AND ZLIB_FOUND AND THREADS_FOUND) IF (GTEST_FOUND AND ZLIB_FOUND AND THREADS_FOUND)
OPTION (MSGPACK_BUILD_TESTS "Build msgpack tests." ON) OPTION (MSGPACK_BUILD_TESTS "Build msgpack tests." ON)
ENDIF () ENDIF ()
OPTION (MSGPACK_BUILD_EXAMPLES "Build msgpack examples." ON)
OPTION (MSGPACK_ENABLE_CXX "Enable C++ interface." ON) OPTION (MSGPACK_ENABLE_CXX "Enable C++ interface." ON)
OPTION (MSGPACK_ENABLE_SHARED "Build shared libaries in addition to static libraries." ON) OPTION (MSGPACK_ENABLE_SHARED "Build shared libaries in addition to static libraries." ON)

View File

@ -2,3 +2,4 @@ ADD_SUBDIRECTORY (c)
ADD_SUBDIRECTORY (cpp03) ADD_SUBDIRECTORY (cpp03)
ADD_SUBDIRECTORY (cpp11) ADD_SUBDIRECTORY (cpp11)
ADD_SUBDIRECTORY (boost) ADD_SUBDIRECTORY (boost)
ADD_SUBDIRECTORY (x3)

View File

@ -22,14 +22,12 @@ IF (NOT MSVC)
) )
ENDIF () ENDIF ()
IF (MSGPACK_BOOST) IF (Boost_TIMER_LIBRARY AND Boost_CHRONO_LIBRARY AND Boost_SYSTEM_LIBRARY)
IF (NOT MSVC)
LIST (APPEND with_boost_lib_PROGRAMS LIST (APPEND with_boost_lib_PROGRAMS
speed_test.cpp speed_test.cpp
speed_test_nested_array.cpp speed_test_nested_array.cpp
) )
ENDIF () ENDIF ()
ENDIF ()
FOREACH (source_file ${exec_PROGRAMS}) FOREACH (source_file ${exec_PROGRAMS})
GET_FILENAME_COMPONENT (source_file_we ${source_file} NAME_WE) GET_FILENAME_COMPONENT (source_file_we ${source_file} NAME_WE)
@ -56,10 +54,10 @@ FOREACH (source_file ${with_pthread_PROGRAMS})
${source_file} ${source_file}
) )
TARGET_LINK_LIBRARIES (${source_file_we} 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") 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 () ENDIF ()
IF ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") IF ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
IF (CMAKE_CXX_FLAGS MATCHES "/W[0-4]") IF (CMAKE_CXX_FLAGS MATCHES "/W[0-4]")

64
example/x3/CMakeLists.txt Normal file
View File

@ -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 ()

119
example/x3/parse.cpp Normal file
View File

@ -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 <iostream>
#include <sstream>
#include <cassert>
// MSGPACK_USE_X3_PARSE should be defined before including msgpack.hpp
// It usually defined as a compiler option as -DMSGPACK_USE_X3_PARSE.
#include <msgpack.hpp>
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<std::string, std::vector<int>> v1 {
{ "ABC", { 1, 2, 3 } },
{ "DEFG", { 4, 5 } }
};
std::vector<std::string> 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;
}
}

View File

@ -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 <iostream>
#include <sstream>
#include <cassert>
#include <thread>
// 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 <msgpack.hpp>
#include <boost/asio.hpp>
#include <boost/coroutine2/all.hpp>
#include <boost/spirit/home/support/multi_pass.hpp>
namespace as = boost::asio;
namespace x3 = boost::spirit::x3;
namespace coro2 = boost::coroutines2;
using pull_type = coro2::asymmetric_coroutine<std::shared_ptr<std::vector<char>>>::pull_type;
// iterator fetching data from coroutine2.
class buffered_iterator : public std::iterator<std::input_iterator_tag, char> {
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<std::vector<char>> buf_;
std::vector<char>::iterator it_;
};
// session class that corresponding to each client
class session : public std::enable_shared_from_this<session> {
public:
session(as::ip::tcp::socket socket)
: socket_(std::move(socket)) {
}
void start() {
sink_ = std::make_shared<coro2::asymmetric_coroutine<std::shared_ptr<std::vector<char>>>::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<std::vector<char>>(static_cast<std::size_t>(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<coro2::asymmetric_coroutine<std::shared_ptr<std::vector<char>>>::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<session>(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<std::string, std::vector<int>> v1 {
{ "ABC", { 1, 2, 3 } },
{ "DEFG", { 4, 5 } }
};
std::vector<std::string> 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;
}

43
example/x3/unpack.cpp Normal file
View File

@ -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 <iostream>
#include <sstream>
#include <cassert>
// MSGPACK_USE_X3_PARSE should be defined before including msgpack.hpp
// It usually defined as a compiler option as -DMSGPACK_USE_X3_PARSE.
#include <msgpack.hpp>
int main() {
std::stringstream ss;
std::map<std::string, std::vector<int>> v1 {
{ "ABC", { 1, 2, 3 } },
{ "DEFG", { 4, 5 } }
};
std::vector<std::string> 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<std::map<std::string, std::vector<int>>>()));
}
{
auto oh = msgpack::unpack(it, end);
assert(v2 == oh.get().as<std::vector<std::string>>());
}
}

View File

@ -340,7 +340,8 @@ const auto mp_object_def =
[](auto& ctx){ [](auto& ctx){
auto& app_specific = x3::get<tag_app_specific>(ctx).get(); auto& app_specific = x3::get<tag_app_specific>(ctx).get();
auto const& str = _attr(ctx); 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);
} }
) )
] ]
@ -363,7 +364,8 @@ const auto mp_object_def =
[](auto& ctx){ [](auto& ctx){
auto& app_specific = x3::get<tag_app_specific>(ctx).get(); auto& app_specific = x3::get<tag_app_specific>(ctx).get();
auto const& str = _attr(ctx); 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);
} }
) )
] ]
@ -386,7 +388,8 @@ const auto mp_object_def =
[](auto& ctx){ [](auto& ctx){
auto& app_specific = x3::get<tag_app_specific>(ctx).get(); auto& app_specific = x3::get<tag_app_specific>(ctx).get();
auto const& str = _attr(ctx); 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);
} }
) )
] ]
@ -409,7 +412,8 @@ const auto mp_object_def =
[](auto& ctx){ [](auto& ctx){
auto& app_specific = x3::get<tag_app_specific>(ctx).get(); auto& app_specific = x3::get<tag_app_specific>(ctx).get();
auto const& str = _attr(ctx); 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);
} }
) )
] ]
@ -432,7 +436,8 @@ const auto mp_object_def =
[](auto& ctx){ [](auto& ctx){
auto& app_specific = x3::get<tag_app_specific>(ctx).get(); auto& app_specific = x3::get<tag_app_specific>(ctx).get();
auto const& bin = _attr(ctx); 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);
} }
) )
] ]
@ -455,7 +460,8 @@ const auto mp_object_def =
[](auto& ctx){ [](auto& ctx){
auto& app_specific = x3::get<tag_app_specific>(ctx).get(); auto& app_specific = x3::get<tag_app_specific>(ctx).get();
auto const& bin = _attr(ctx); 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);
} }
) )
] ]
@ -478,7 +484,8 @@ const auto mp_object_def =
[](auto& ctx){ [](auto& ctx){
auto& app_specific = x3::get<tag_app_specific>(ctx).get(); auto& app_specific = x3::get<tag_app_specific>(ctx).get();
auto const& bin = _attr(ctx); 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);
} }
) )
] ]
@ -585,7 +592,8 @@ const auto mp_object_def =
[](auto& ctx){ [](auto& ctx){
auto& app_specific = x3::get<tag_app_specific>(ctx).get(); auto& app_specific = x3::get<tag_app_specific>(ctx).get();
auto const& ext = _attr(ctx); 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);
} }
) )
] ]
@ -608,7 +616,8 @@ const auto mp_object_def =
[](auto& ctx){ [](auto& ctx){
auto& app_specific = x3::get<tag_app_specific>(ctx).get(); auto& app_specific = x3::get<tag_app_specific>(ctx).get();
auto const& ext = _attr(ctx); 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);
} }
) )
] ]
@ -631,7 +640,8 @@ const auto mp_object_def =
[](auto& ctx){ [](auto& ctx){
auto& app_specific = x3::get<tag_app_specific>(ctx).get(); auto& app_specific = x3::get<tag_app_specific>(ctx).get();
auto const& ext = _attr(ctx); 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);
} }
) )
] ]
@ -654,7 +664,8 @@ const auto mp_object_def =
[](auto& ctx){ [](auto& ctx){
auto& app_specific = x3::get<tag_app_specific>(ctx).get(); auto& app_specific = x3::get<tag_app_specific>(ctx).get();
auto const& ext = _attr(ctx); 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);
} }
) )
] ]
@ -677,7 +688,8 @@ const auto mp_object_def =
[](auto& ctx){ [](auto& ctx){
auto& app_specific = x3::get<tag_app_specific>(ctx).get(); auto& app_specific = x3::get<tag_app_specific>(ctx).get();
auto const& ext = _attr(ctx); 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);
} }
) )
] ]
@ -700,7 +712,8 @@ const auto mp_object_def =
[](auto& ctx){ [](auto& ctx){
auto& app_specific = x3::get<tag_app_specific>(ctx).get(); auto& app_specific = x3::get<tag_app_specific>(ctx).get();
auto const& ext = _attr(ctx); 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);
} }
) )
] ]
@ -723,7 +736,8 @@ const auto mp_object_def =
[](auto& ctx){ [](auto& ctx){
auto& app_specific = x3::get<tag_app_specific>(ctx).get(); auto& app_specific = x3::get<tag_app_specific>(ctx).get();
auto const& ext = _attr(ctx); 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);
} }
) )
] ]
@ -746,7 +760,8 @@ const auto mp_object_def =
[](auto& ctx){ [](auto& ctx){
auto& app_specific = x3::get<tag_app_specific>(ctx).get(); auto& app_specific = x3::get<tag_app_specific>(ctx).get();
auto const& ext = _attr(ctx); 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);
} }
) )
]; ];