[c++] Reduce included headers for Simple JSON

This change introduces a `BOND_LIB_TYPE` macro and moves some utility
functions used by the Simple JSON protocol to corresponding source file
which reduces the number of included files by over 240.

The `BOND_LIB_TYPE` macro will allow:
- to keep some expensive-to-compile headers away from public ones
- pre-compile some common parts of the library
This commit is contained in:
Ara Ayvazyan 2017-11-17 11:30:05 -08:00 коммит произвёл Christopher Warrington
Родитель 55ca8fa7d1
Коммит edf6bdc62c
11 изменённых файлов: 134 добавлений и 27 удалений

Просмотреть файл

@ -22,6 +22,7 @@ set (BOND_IDL ${CMAKE_CURRENT_SOURCE_DIR}/idl)
set (BOND_INCLUDE ${CMAKE_CURRENT_SOURCE_DIR}/cpp/inc)
set (BOND_PYTHON_INCLUDE ${CMAKE_CURRENT_SOURCE_DIR}/python/inc)
set (BOND_GENERATED ${CMAKE_CURRENT_SOURCE_DIR}/cpp/generated)
set (BOND_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/cpp/src)
set (BOND_COMPAT_TEST_DIR ${CMAKE_CURRENT_SOURCE_DIR}/test/compat)
include (Config)

Просмотреть файл

@ -203,7 +203,7 @@ set (BOND_LIBRARIES_ONLY
set (BOND_LIBRARIES_INSTALL_CPP
"FALSE"
CACHE BOOL "If TRUE, the generated .cpp files for the Bond libraries will be installed under src/ as part of the INSTALL target.")
CACHE BOOL "If TRUE, the .cpp files for the Bond libraries will be installed under src/ as part of the INSTALL target.")
set (BOND_ENABLE_COMM
"FALSE"

Просмотреть файл

@ -54,6 +54,10 @@ set (generated_files_apply)
list (APPEND generated_files_apply
${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bond/core/bond_apply.cpp)
set (precompiled_sources)
list (APPEND precompiled_sources
"src/bond/protocol/detail/rapidjson_utils.cpp")
list (APPEND headers
${core_headers}
${core_detail_headers}
@ -140,8 +144,11 @@ add_library (bond
STATIC
${schemas}
${generated_files_types}
${precompiled_sources}
${headers})
target_compile_definitions (bond PUBLIC -DBOND_LIB_TYPE=BOND_LIB_TYPE_STATIC)
# Boost thread is only needed if the C++ standard library doesn't support
# std::call_once. However std::once seems problematic on Linux
# (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60662) so for now we use
@ -177,6 +184,11 @@ if (BOND_LIBRARIES_INSTALL_CPP)
DIRECTORY ${BOND_GENERATED}/bond/
DESTINATION src/bond/generated
FILES_MATCHING PATTERN "*.cpp")
install (
DIRECTORY ${BOND_SOURCE_DIR}/
DESTINATION src/
FILES_MATCHING PATTERN "*.cpp")
endif()
add_subdirectory (test)

Просмотреть файл

@ -40,3 +40,24 @@
#define BOND_CONSTEXPR BOOST_CONSTEXPR
#define BOND_CONSTEXPR_OR_CONST BOOST_CONSTEXPR_OR_CONST
#define BOND_STATIC_CONSTEXPR BOOST_STATIC_CONSTEXPR
#define BOND_LIB_TYPE_HEADER 1
#define BOND_LIB_TYPE_STATIC 2
#define BOND_LIB_TYPE_DYNAMIC 3 // Not implemented
#ifndef BOND_LIB_TYPE
#define BOND_LIB_TYPE BOND_LIB_TYPE_HEADER
#elif (BOND_LIB_TYPE != BOND_LIB_TYPE_HEADER) && (BOND_LIB_TYPE != BOND_LIB_TYPE_STATIC)
#error Unsupported library type is defined for BOND_LIB_TYPE
#endif
#ifndef BOND_DETAIL_HEADER_ONLY_INLINE
#if BOND_LIB_TYPE == BOND_LIB_TYPE_HEADER
#define BOND_DETAIL_HEADER_ONLY_INLINE inline
#else
#define BOND_DETAIL_HEADER_ONLY_INLINE
#endif
#else
#error BOND_DETAIL_HEADER_ONLY_INLINE is already defined
#endif

Просмотреть файл

@ -9,13 +9,12 @@
#include <bond/core/bond_const_enum.h>
#include <bond/core/detail/sdl.h>
#include <bond/core/exception.h>
#include <boost/call_traits.hpp>
#include <boost/noncopyable.hpp>
#include <boost/locale.hpp>
#include "rapidjson/rapidjson.h"
#include "rapidjson/error/en.h"
#include "rapidjson_utils.h"
// rapidjson/document.h v1.1 uses std::min/max in ways that conflict
// with macros defined in windows. This works around the issue.
@ -279,26 +278,17 @@ template <typename T>
typename boost::enable_if<is_wstring<T> >::type
Read(const rapidjson::Value& value, T& var)
{
try
{
const std::basic_string<uint16_t> str =
boost::locale::conv::utf_to_utf<uint16_t>(
value.GetString(),
value.GetString() + value.GetStringLength(),
boost::locale::conv::stop);
const std::basic_string<uint16_t> str = utf_to_utf(
value.GetString(),
value.GetString() + value.GetStringLength());
const size_t length = str.size();
resize_string(var, static_cast<uint32_t>(length));
const size_t length = str.size();
resize_string(var, static_cast<uint32_t>(length));
std::copy(
str.begin(),
str.end(),
make_checked_array_iterator(string_data(var), length));
}
catch (const boost::locale::conv::conversion_error &)
{
UnicodeConversionException();
}
std::copy(
str.begin(),
str.end(),
make_checked_array_iterator(string_data(var), length));
}

Просмотреть файл

@ -0,0 +1,31 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
#pragma once
#include <string>
#include <stdint.h>
namespace bond
{
namespace detail
{
std::basic_string<uint16_t> utf_to_utf(const char* begin, const char* end);
bool try_lexical_convert(const char* str, uint16_t& result);
} // namespace detail
} // namespace bond
#ifdef BOND_LIB_TYPE
#if BOND_LIB_TYPE == BOND_LIB_TYPE_HEADER
#include "rapidjson_utils_impl.h"
#endif
#else
#error BOND_LIB_TYPE is undefined
#endif

Просмотреть файл

@ -0,0 +1,39 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
#pragma once
#include <bond/core/exception.h>
#include <boost/locale.hpp>
#include <boost/lexical_cast.hpp>
namespace bond
{
namespace detail
{
BOND_DETAIL_HEADER_ONLY_INLINE
std::basic_string<uint16_t> utf_to_utf(const char* begin, const char* end)
{
try
{
return boost::locale::conv::utf_to_utf<uint16_t>(begin, end, boost::locale::conv::stop);
}
catch (const boost::locale::conv::conversion_error&)
{
UnicodeConversionException();
}
}
BOND_DETAIL_HEADER_ONLY_INLINE
bool try_lexical_convert(const char* str, uint16_t& result)
{
return boost::conversion::try_lexical_convert(str, result);
}
} // namespace detail
} // namespace bond

Просмотреть файл

@ -4,7 +4,6 @@
#pragma once
#include "simple_json_reader.h"
#include "boost/lexical_cast.hpp"
namespace bond
{
@ -32,7 +31,7 @@ SimpleJsonReader<BufferT>::FindField(uint16_t id, const Metadata& metadata, Bond
}
uint16_t parsedId;
if (boost::conversion::try_lexical_convert(it->name.GetString(), parsedId) && id == parsedId)
if (detail::try_lexical_convert(it->name.GetString(), parsedId) && id == parsedId)
{
// string id match
return &it->value;

Просмотреть файл

@ -0,0 +1,11 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
#include <bond/core/config.h>
#if BOND_LIB_TYPE == BOND_LIB_TYPE_HEADER
#error This source file should not be compiled for BOND_LIB_TYPE_HEADER
#endif
#include <bond/protocol/detail/rapidjson_utils.h>
#include <bond/protocol/detail/rapidjson_utils_impl.h>

Просмотреть файл

@ -23,9 +23,7 @@ function (add_unit_test)
-DBOND_FAST_BINARY_PROTOCOL
-DBOND_SIMPLE_JSON_PROTOCOL)
target_link_libraries (${name} PRIVATE
bond
core_test_common
${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
core_test_common)
endfunction()
@ -61,7 +59,8 @@ target_compile_definitions (core_test_common PUBLIC
-DBOND_SIMPLE_BINARY_PROTOCOL
-DBOND_FAST_BINARY_PROTOCOL
-DBOND_SIMPLE_JSON_PROTOCOL)
target_link_libraries (core_test_common PRIVATE
target_link_libraries (core_test_common PUBLIC
bond
${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})

Просмотреть файл

@ -1775,6 +1775,10 @@ to reuse the pre-instantiated code. The one exception are applications using
custom protocols - by definition templates pre-instantiated at the time Bond
library was built can't support custom protocols.
If header-only consumption of the library is not required, then defining the
`BOND_LIB_TYPE` macro to `BOND_LIB_TYPE_STATIC` will pre-compile more common
code into the `bond.lib`/`libbond.a` library and will reduce the number of included headers.
When using the Microsoft Visual Studio toolchain there are two important things
to be aware related to build time. First, always use 64-bit tools. In
particular the 32-bit version of link.exe is not capable of linking large