Skip to content

Commit c2e6b12

Browse files
committed
Доработана возможность собирать библиотеку в виде экспорта из разделяемой библиотеки.
1 parent 129b30a commit c2e6b12

5 files changed

Lines changed: 98 additions & 64 deletions

File tree

CMakeLists.txt

Lines changed: 17 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,7 @@ elseif(${CMAKE_CXX_COMPILER_ID} STREQUAL Clang)
2222
endif()
2323

2424
option(SIMJSON_BUILD_TESTS "Построить тесты" ON)
25-
option(SIMJSON_BENCHMARKS "Построить замеры производительности" OFF)
26-
option(SIMJSON_SHARED "Функции simjson должны экспортироваться или импортироваться" OFF)
25+
option(SIMJSON_IN_SHARED "Функции simjson должны экспортироваться или импортироваться" Off)
2726

2827
add_library(simjson_simjson
2928
src/json.cpp
@@ -53,10 +52,10 @@ set_target_properties(
5352
OUTPUT_NAME simjson
5453
)
5554

56-
function(Simstr)
55+
function(add_simstr)
5756
set(SIMSTR_BUILD_TESTS OFF)
5857
set(SIMSTR_BENCHMARKS OFF)
59-
if(SIMJSON_SHARED)
58+
if(SIMJSON_IN_SHARED)
6059
set(SIMSTR_SHARED On)
6160
endif()
6261
FetchContent_Declare(
@@ -69,14 +68,14 @@ function(Simstr)
6968
FetchContent_MakeAvailable(simstr)
7069
endfunction()
7170

72-
Simstr()
71+
add_simstr()
7372

7473
target_link_libraries(simjson_simjson PUBLIC simstr::simstr)
7574

76-
if(SIMJSON_SHARED)
77-
add_compile_definitions(SIMJSON_SHARED)
75+
if(SIMJSON_IN_SHARED)
76+
add_compile_definitions(SIMJSON_IN_SHARED)
7877
target_compile_definitions(simjson_simjson PRIVATE SIMJSON_EXPORT)
79-
endif(SIMJSON_SHARED)
78+
endif(SIMJSON_IN_SHARED)
8079

8180
if(SIMJSON_BUILD_TESTS)
8281
enable_testing()
@@ -86,38 +85,24 @@ if(SIMJSON_BUILD_TESTS)
8685
googletest
8786
# Specify the commit you depend on and update it regularly.
8887
URL https://github.com/google/googletest/archive/refs/tags/release-1.12.1.zip
88+
FIND_PACKAGE_ARGS NAMES GTest
8989
)
90-
9190
# For Windows: Prevent overriding the parent project's compiler/linker settings
9291
set(gtest_force_shared_crt FALSE CACHE BOOL "" FORCE)
9392
FetchContent_MakeAvailable(googletest)
9493
add_subdirectory(tests)
9594
endif()
9695

97-
function(GBencmark)
98-
# Load and build Google benchmarks
99-
include(FetchContent)
100-
FetchContent_Declare(
101-
googlebench
102-
# Specify the commit you depend on and update it regularly.
103-
URL https://github.com/google/benchmark/archive/refs/tags/v1.7.0.zip
104-
)
105-
set(CMAKE_CXX_STANDARD 20)
106-
set(BENCHMARK_ENABLE_TESTING OFF)
107-
set(BENCHMARK_ENABLE_LTO OFF)
108-
set(BENCHMARK_ENABLE_INSTALL OFF)
109-
set(BENCHMARK_INSTALL_DOCS OFF)
110-
set(BENCHMARK_DOWNLOAD_DEPENDENCIES ON)
111-
set(BENCHMARK_ENABLE_GTEST_TESTS OFF)
112-
add_compile_definitions(BENCHMARK_STATIC_DEFINE)
113-
FetchContent_MakeAvailable(googlebench)
114-
endfunction()
115-
116-
if(SIMJSON_BENCHMARKS) # AND CMAKE_BUILD_TYPE STREQUAL Release)
117-
set(BUILD_BENCHMARKS ON)
118-
GBencmark()
119-
add_subdirectory(bench)
96+
#[[
97+
# Пример построения shared библиотеки, которая включит в себя simjson и simstr.
98+
# Необходимо также задать опцию SIMJSON_IN_SHARED. Как при этом создать экзешник,
99+
# пользующийся этой dll - пример в tests/CMakeLists.txt
100+
if (SIMJSON_IN_SHARED)
101+
add_library(simjson_dll SHARED include/simjson/json.h)
102+
target_link_libraries(simjson_dll PRIVATE "$<LINK_LIBRARY:WHOLE_ARCHIVE,simjson::simjson>,simstr_simstr>")
103+
set_property(TARGET simjson_dll PROPERTY LINK_LIBRARY_OVERRIDE "WHOLE_ARCHIVE,simstr_simstr")
120104
endif()
105+
#]]
121106

122107
# ---- Install rules ----
123108

include/simjson/json.h

Lines changed: 46 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
/*
2+
* (c) Проект "SimJson", Александр Орефков orefkov@gmail.com
3+
* ver. 1.0
4+
* Классы для работы с JSON
5+
*/
6+
17
#pragma once
28
#include <memory>
39
#include <optional>
@@ -7,6 +13,27 @@
713
#include <type_traits>
814
#include <utility>
915

16+
#pragma once
17+
#ifndef __has_declspec_attribute
18+
#define __has_declspec_attribute(x) 0
19+
#endif
20+
21+
#ifdef SIMJSON_IN_SHARED
22+
#if defined(_MSC_VER) || (defined(__clang__) && __has_declspec_attribute(dllexport))
23+
#ifdef SIMJSON_EXPORT
24+
#define SIMJSON_API __declspec(dllexport)
25+
#else
26+
#define SIMJSON_API __declspec(dllimport)
27+
#endif
28+
#elif (defined(__GNUC__) || defined(__GNUG__)) && defined(SIMSTR_EXPORT)
29+
#define SIMJSON_API __attribute__((visibility("default")))
30+
#else
31+
#define SIMJSON_API
32+
#endif
33+
#else
34+
#define SIMJSON_API
35+
#endif
36+
1037
namespace simjson {
1138
using namespace simstr;
1239
using namespace simstr::literals;
@@ -93,7 +120,6 @@ concept JsonObjectSource = requires(const T& t) {
93120
template<typename K>
94121
class JsonValueTempl : public Json {
95122
public:
96-
97123
using strType = sstring<K>;
98124
using ssType = simple_str<K>;
99125

@@ -106,7 +132,7 @@ class JsonValueTempl : public Json {
106132
/// Создает пустой объект с типом Undefined
107133
JsonValueTempl() : type_(Undefined) {}
108134
/// Конструктор копирования. Объекты и массивы копируются по ссылке
109-
JsonValueTempl(const JsonValueTempl& other);
135+
SIMJSON_API JsonValueTempl(const JsonValueTempl& other);
110136
/// Конструктор перемещения
111137
JsonValueTempl(JsonValueTempl&& other) noexcept {
112138
type_ = other.type_;
@@ -126,7 +152,7 @@ class JsonValueTempl : public Json {
126152
other.type_ = Undefined;
127153
}
128154
/// Деструктор
129-
~JsonValueTempl();
155+
SIMJSON_API ~JsonValueTempl();
130156

131157
/// Конструктор из int8_t
132158
JsonValueTempl(int8_t v) : type_(Integer) { val_.integer = v; }
@@ -172,7 +198,7 @@ class JsonValueTempl : public Json {
172198
new (&val_.array) json_array(std::make_shared<arr_type>());
173199
}
174200
/// Конструктор для создания дефолтного значения с типом type
175-
JsonValueTempl(Type type);
201+
SIMJSON_API JsonValueTempl(Type type);
176202

177203
struct KeyInit : std::pair<const jt::KeyType<K>, json_value> {
178204
using base = std::pair<const jt::KeyType<K>, json_value>;
@@ -213,7 +239,7 @@ class JsonValueTempl : public Json {
213239
const json_value& from;
214240
};
215241
/// Конструктор клонирования. В этом случае для объектов и массивов создаются "глубокие" копии
216-
JsonValueTempl(const Clone& clone);
242+
SIMJSON_API JsonValueTempl(const Clone& clone);
217243
/// Получить тип значения
218244
Type type() const { return type_; }
219245
/// Клонировать значение
@@ -262,7 +288,7 @@ class JsonValueTempl : public Json {
262288
throw Exc(std::forward<Args>(args)...);
263289
}
264290
/// Получить значение, конвертированное в boolean. Логика работы как в javascript `!!val`. Пример: bool val = json.to_boolean();
265-
bool to_boolean() const;
291+
SIMJSON_API bool to_boolean() const;
266292

267293
// ---------------------------------------- Integer -------------------------------------
268294
/// Получить значение как integer. В отладочной версии проверяется, что значение действительно integer
@@ -288,7 +314,7 @@ class JsonValueTempl : public Json {
288314
/// Получить значение, конвертированное в integer, или ничего. Логика работы как в javascript `1 * val`.
289315
/// Если в результате NaN или Inf, то ничего. Нецелые числа - переводятся в целое.
290316
/// Пример: int val = json.to_integer().value_or(10);
291-
std::optional<int64_t> to_integer() const;
317+
SIMJSON_API std::optional<int64_t> to_integer() const;
292318
/// Получить значение из to_integer, если оно есть, или выкинуть исключение.
293319
template<typename Exc, typename ... Args> requires (std::is_constructible_v<Exc, Args...>)
294320
int64_t to_integer_or_throw(Args&&...args) const {
@@ -320,7 +346,7 @@ class JsonValueTempl : public Json {
320346
}
321347

322348
/// Получить значение, конвертированное в double. Логика работы как в javascript `1 * val`. Для "не чисел" возвращает NaN.
323-
double to_real() const;
349+
SIMJSON_API double to_real() const;
324350
// --------------------------------------- Number -----------------------------
325351
// В нашей реализации в отличии от чистого json числа могут быть int64_t или double
326352
// Поэтому добавим ещё логику для работы только с обоими вариантами чисел
@@ -336,7 +362,7 @@ class JsonValueTempl : public Json {
336362
throw Exc(std::forward<Args>(args)...);
337363
}
338364
/// Возвращает double, если хранится double или int64_t, либо ничего
339-
std::optional<double> number_real() const;
365+
SIMJSON_API std::optional<double> number_real() const;
340366
/// Получить double, если хранится double или int64_t, либо выбросить исключение
341367
template<typename Exc, typename ... Args> requires (std::is_constructible_v<Exc, Args...>)
342368
double number_real_or_throw(Args&&...args) const {
@@ -379,7 +405,7 @@ class JsonValueTempl : public Json {
379405
}
380406

381407
/// Получить значение, конвертированное в текст. Логика работы как в javascript `"" + val`.
382-
strType to_text() const;
408+
SIMJSON_API strType to_text() const;
383409

384410
/// Получить значение как json Object. В отладочной версии проверяется, что значение действительно Object
385411
json_object& as_object() {
@@ -552,7 +578,7 @@ class JsonValueTempl : public Json {
552578
* Если оба JSONа объекты - то сливаются по ключам. Ключи из другого объекта, которых нет в текущем - добавятся в текущий
553579
* объект. Которые есть - при replace == true будут заменены.
554580
*/
555-
void merge(const json_value& other, bool replace = true, bool append_arrays = false);
581+
SIMJSON_API void merge(const json_value& other, bool replace = true, bool append_arrays = false);
556582
/*!
557583
* @brief Распарсить текст с json.
558584
*
@@ -574,7 +600,7 @@ class JsonValueTempl : public Json {
574600
* @param indent_symbol - при "украшении" задаёт символ для отступов, по умолчанию пробел.
575601
* @param indent_count - количество символов отступа на один уровень, по умолчанию 2.
576602
*/
577-
void store(lstring<K, 0, true>& stream, bool prettify = false, bool order_keys = false, K indent_symbol = ' ', unsigned indent_count = 2) const;
603+
SIMJSON_API void store(lstring<K, 0, true>& stream, bool prettify = false, bool order_keys = false, K indent_symbol = ' ', unsigned indent_count = 2) const;
578604
/*!
579605
* @brief Сериализовать json-значение в строку
580606
* @param prettify - "украшать", в случае true в строке будут добавляться переносы строк и отступы.
@@ -593,8 +619,8 @@ class JsonValueTempl : public Json {
593619
}
594620

595621
protected:
596-
// Один объект "пустышка"
597-
static const json_value UNDEFINED;
622+
SIMJSON_API static const json_value UNDEFINED;
623+
598624
// Тип значения
599625
Type type_;
600626
// Хранимое значение
@@ -648,7 +674,7 @@ struct StreamedJsonParser : StreamedJsonParserBase {
648674
protected:
649675

650676
template<bool All, bool Last>
651-
JsonParseResult process(ssType chunk);
677+
SIMJSON_API JsonParseResult process(ssType chunk);
652678

653679
static bool isWhiteSpace(K symbol) {
654680
return symbol == ' ' || symbol == '\t' || symbol == '\n' || symbol == '\r';
@@ -688,14 +714,17 @@ using JsonValueU = JsonValueTempl<u16s>;
688714
using JsonValueUU = JsonValueTempl<u32s>;
689715

690716
/// Один объект "пустышка"
717+
#if defined (SIMJSON_EXPORT) || !defined (SIMJSON_IN_SHARED)
691718
template<typename K>
692-
inline const JsonValueTempl<K> JsonValueTempl<K>::UNDEFINED;
719+
inline SIMJSON_API const JsonValueTempl<K> JsonValueTempl<K>::UNDEFINED;
720+
#else
721+
#endif
693722

694723
/*!
695724
* @brief Прочитать файл в строку
696725
* @param filePath
697726
* @return stringa
698727
*/
699-
stringa get_file_content(stra filePath);
728+
SIMJSON_API stringa get_file_content(stra filePath);
700729

701730
} // namespace simjson

readme.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
Версия 1.0.
77

8-
В этой библиотеке содержится простая реализация простого объекта JsonValue для работы с JSON с использование строковых объектов
8+
В этой библиотеке содержится простая реализация простого объекта JsonValue для работы с JSON с использованием строковых объектов
99
библиотеки *simstr*, так как другие библиотеки работают в основном с `std::string` или сырыми `const char*`.
1010
Задача как-то соревноваться по производительности или оптимальности с другими библиотеками не ставилась, я её применяю в-основном
1111
для работы с небольшими конфиг-файлами - прочитать, изменить, записать.

0 commit comments

Comments
 (0)