Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 79 additions & 0 deletions .github/workflows/abi-compatibility.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
name: ABI Compatibility

on: [check_run, push, pull_request]

env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true

jobs:
abi-compatibility:
runs-on: ${{ matrix.os }}

strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
shared_libs: [ON, OFF]
include:
- jsoncpp_std: 11
app_std: 23
- jsoncpp_std: 23
app_std: 11

steps:
- name: checkout project
uses: actions/checkout@v4

- name: build and install JsonCpp (C++${{ matrix.jsoncpp_std }})
shell: bash
run: |
mkdir build-jsoncpp
cd build-jsoncpp
cmake .. -DCMAKE_CXX_STANDARD=${{ matrix.jsoncpp_std }} \
-DCMAKE_CXX_STANDARD_REQUIRED=ON \
-DCMAKE_INSTALL_PREFIX=$GITHUB_WORKSPACE/install-jsoncpp \
-DBUILD_SHARED_LIBS=${{ matrix.shared_libs }} \
-DJSONCPP_WITH_TESTS=OFF
cmake --build . --config Release
cmake --install . --config Release

- name: create example app
shell: bash
run: |
mkdir example-app
cat << 'EOF' > example-app/CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(abi_test)

find_package(jsoncpp REQUIRED CONFIG)

add_executable(abi_test stringView.cpp)
target_link_libraries(abi_test PRIVATE JsonCpp::JsonCpp)
EOF

cp $GITHUB_WORKSPACE/example/stringView/stringView.cpp example-app/stringView.cpp

- name: build example app (C++${{ matrix.app_std }})
shell: bash
run: |
cd example-app
mkdir build
cd build
cmake .. -DCMAKE_CXX_STANDARD=${{ matrix.app_std }} \
-DCMAKE_CXX_STANDARD_REQUIRED=ON \
-DCMAKE_PREFIX_PATH=$GITHUB_WORKSPACE/install-jsoncpp
cmake --build . --config Release

- name: run example app
shell: bash
run: |
if [ "$RUNNER_OS" == "Windows" ]; then
export PATH=$GITHUB_WORKSPACE/install-jsoncpp/bin:$PATH
./example-app/build/Release/abi_test.exe
elif [ "$RUNNER_OS" == "macOS" ]; then
export DYLD_LIBRARY_PATH=$GITHUB_WORKSPACE/install-jsoncpp/lib:$DYLD_LIBRARY_PATH
./example-app/build/abi_test
else
export LD_LIBRARY_PATH=$GITHUB_WORKSPACE/install-jsoncpp/lib:$LD_LIBRARY_PATH
./example-app/build/abi_test
fi
6 changes: 6 additions & 0 deletions example/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,9 @@ cc_binary(
srcs = ["stringWrite/stringWrite.cpp"],
deps = ["//:jsoncpp"],
)

cc_binary(
name = "stringView",
srcs = ["stringView/stringView.cpp"],
deps = ["//:jsoncpp"],
)
1 change: 1 addition & 0 deletions example/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ set(EXAMPLES
readFromStream
stringWrite
streamWrite
stringView
)
add_definitions(-D_GLIBCXX_USE_CXX11_ABI)

Expand Down
29 changes: 29 additions & 0 deletions example/stringView/stringView.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#include "json/json.h"
#include <cstdlib>
#include <iostream>

#if defined(JSONCPP_HAS_STRING_VIEW)
#include <string_view>
#endif

/**
* \brief Example using std::string_view with JsonCpp.
*/
int main() {
Json::Value root;
root["key"] = "value";

#if defined(JSONCPP_HAS_STRING_VIEW)
std::cout << "Has string_view support" << std::endl;
std::string_view sv("key");
if (root.isMember(sv)) {
std::cout << root[sv].asString() << std::endl;
}
#else
std::cout << "No string_view support" << std::endl;
if (root.isMember("key")) {
std::cout << root["key"].asString() << std::endl;
}
#endif
return EXIT_SUCCESS;
}
54 changes: 36 additions & 18 deletions include/json/value.h
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,8 @@ class JSON_API Value {
Value(const StaticString& value);
Value(const String& value);
#ifdef JSONCPP_HAS_STRING_VIEW
Value(std::string_view value);
inline Value(std::string_view value)
: Value(value.data(), value.data() + value.length()) {}
#endif
Value(bool value);
Value(std::nullptr_t ptr) = delete;
Expand Down Expand Up @@ -405,7 +406,14 @@ class JSON_API Value {
/** Get string_view of string-value.
* \return false if !string. (Seg-fault if str is NULL.)
*/
bool getString(std::string_view* str) const;
inline bool getString(std::string_view* str) const {
char const* begin;
char const* end;
if (!getString(&begin, &end))
return false;
*str = std::string_view(begin, static_cast<size_t>(end - begin));
return true;
}
#endif
Int asInt() const;
UInt asUInt() const;
Expand Down Expand Up @@ -496,12 +504,19 @@ class JSON_API Value {
#ifdef JSONCPP_HAS_STRING_VIEW
/// Access an object value by name, create a null member if it does not exist.
/// \param key may contain embedded nulls.
Value& operator[](std::string_view key);
inline Value& operator[](std::string_view key) {
return resolveReference(key.data(), key.data() + key.length());
}
/// Access an object value by name, returns null if there is no member with
/// that name.
/// \param key may contain embedded nulls.
const Value& operator[](std::string_view key) const;
#else
inline const Value& operator[](std::string_view key) const {
Value const* found = find(key.data(), key.data() + key.length());
if (!found)
return nullSingleton();
return *found;
}
#endif
/// Access an object value by name, create a null member if it does not exist.
/// \note Because of our implementation, keys are limited to 2^30 -1 chars.
/// Exceeding that will cause an exception.
Expand All @@ -516,7 +531,6 @@ class JSON_API Value {
/// that name.
/// \param key may contain embedded nulls.
const Value& operator[](const String& key) const;
#endif
/** \brief Access an object value by name, create a null member if it does not
* exist.
*
Expand All @@ -533,16 +547,17 @@ class JSON_API Value {
#ifdef JSONCPP_HAS_STRING_VIEW
/// Return the member named key if it exist, defaultValue otherwise.
/// \note deep copy
Value get(std::string_view key, const Value& defaultValue) const;
#else
inline Value get(std::string_view key, const Value& defaultValue) const {
return get(key.data(), key.data() + key.length(), defaultValue);
}
#endif
/// Return the member named key if it exist, defaultValue otherwise.
/// \note deep copy
Value get(const char* key, const Value& defaultValue) const;
/// Return the member named key if it exist, defaultValue otherwise.
/// \note deep copy
/// \param key may contain embedded nulls.
Value get(const String& key, const Value& defaultValue) const;
#endif
/// Return the member named key if it exist, defaultValue otherwise.
/// \note deep copy
/// \note key may contain embedded nulls.
Expand Down Expand Up @@ -588,27 +603,29 @@ class JSON_API Value {
/// \pre type() is objectValue or nullValue
/// \post type() is unchanged
#if JSONCPP_HAS_STRING_VIEW
void removeMember(std::string_view key);
#else
inline void removeMember(std::string_view key) {
removeMember(key.data(), key.data() + key.length(), nullptr);
}
#endif
void removeMember(const char* key);
/// Same as removeMember(const char*)
/// \param key may contain embedded nulls.
void removeMember(const String& key);
#endif
/** \brief Remove the named map member.
*
* Update 'removed' iff removed.
* \param key may contain embedded nulls.
* \return true iff removed (no exceptions)
*/
#if JSONCPP_HAS_STRING_VIEW
bool removeMember(std::string_view key, Value* removed);
#else
inline bool removeMember(std::string_view key, Value* removed) {
return removeMember(key.data(), key.data() + key.length(), removed);
}
#endif
bool removeMember(String const& key, Value* removed);
/// Same as removeMember(const char* begin, const char* end, Value* removed),
/// but 'key' is null-terminated.
bool removeMember(const char* key, Value* removed);
#endif
/// Same as removeMember(String const& key, Value* removed)
bool removeMember(const char* begin, const char* end, Value* removed);
/** \brief Remove the indexed array element.
Expand All @@ -622,15 +639,16 @@ class JSON_API Value {
#ifdef JSONCPP_HAS_STRING_VIEW
/// Return true if the object has a member named key.
/// \param key may contain embedded nulls.
bool isMember(std::string_view key) const;
#else
inline bool isMember(std::string_view key) const {
return isMember(key.data(), key.data() + key.length());
}
#endif
/// Return true if the object has a member named key.
/// \note 'key' must be null-terminated.
bool isMember(const char* key) const;
/// Return true if the object has a member named key.
/// \param key may contain embedded nulls.
bool isMember(const String& key) const;
#endif
/// Same as isMember(String const& key)const
bool isMember(const char* begin, const char* end) const;

Expand Down
9 changes: 0 additions & 9 deletions src/lib_json/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -131,9 +131,6 @@ if(BUILD_SHARED_LIBS)

target_compile_features(${SHARED_LIB} PUBLIC ${REQUIRED_FEATURES})

if(JSONCPP_HAS_STRING_VIEW)
target_compile_definitions(${SHARED_LIB} PUBLIC JSONCPP_HAS_STRING_VIEW=1)
endif()

target_include_directories(${SHARED_LIB} PUBLIC
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
Expand Down Expand Up @@ -168,9 +165,6 @@ if(BUILD_STATIC_LIBS)

target_compile_features(${STATIC_LIB} PUBLIC ${REQUIRED_FEATURES})

if(JSONCPP_HAS_STRING_VIEW)
target_compile_definitions(${STATIC_LIB} PUBLIC JSONCPP_HAS_STRING_VIEW=1)
endif()

target_include_directories(${STATIC_LIB} PUBLIC
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
Expand Down Expand Up @@ -198,9 +192,6 @@ if(BUILD_OBJECT_LIBS)

target_compile_features(${OBJECT_LIB} PUBLIC ${REQUIRED_FEATURES})

if(JSONCPP_HAS_STRING_VIEW)
target_compile_definitions(${OBJECT_LIB} PUBLIC JSONCPP_HAS_STRING_VIEW=1)
endif()

target_include_directories(${OBJECT_LIB} PUBLIC
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
Expand Down
Loading
Loading