From e40f2835b7037343f6d36868cfe1dc98c67026e1 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Tue, 3 Mar 2026 22:41:41 -0800 Subject: [PATCH 1/5] Revert "removes old cci version (1.0.0)" This reverts commit d02db62f503671ef9e08cfd653ebbc28d8c46c0f. --- third_party/CMakeLists.txt | 6 +- third_party/cci-1.0.0/CMakeLists.txt | 85 + .../cci-1.0.0/cci_cfg/cci_broker_callbacks.h | 89 + .../cci-1.0.0/cci_cfg/cci_broker_handle.cpp | 179 ++ .../cci-1.0.0/cci_cfg/cci_broker_handle.h | 253 +++ third_party/cci-1.0.0/cci_cfg/cci_broker_if.h | 300 ++++ .../cci-1.0.0/cci_cfg/cci_broker_manager.cpp | 93 + .../cci-1.0.0/cci_cfg/cci_broker_manager.h | 112 ++ .../cci-1.0.0/cci_cfg/cci_broker_types.h | 47 + .../cci-1.0.0/cci_cfg/cci_config_macros.h | 48 + .../cci-1.0.0/cci_cfg/cci_macros_undef.h | 47 + .../cci-1.0.0/cci_cfg/cci_mutable_types.h | 42 + .../cci-1.0.0/cci_cfg/cci_originator.cpp | 167 ++ .../cci-1.0.0/cci_cfg/cci_originator.h | 159 ++ .../cci-1.0.0/cci_cfg/cci_param_callbacks.h | 365 ++++ .../cci-1.0.0/cci_cfg/cci_param_if.cpp | 71 + third_party/cci-1.0.0/cci_cfg/cci_param_if.h | 368 ++++ .../cci-1.0.0/cci_cfg/cci_param_typed.h | 986 +++++++++++ .../cci_cfg/cci_param_typed_handle.h | 266 +++ .../cci-1.0.0/cci_cfg/cci_param_untyped.cpp | 291 ++++ .../cci-1.0.0/cci_cfg/cci_param_untyped.h | 624 +++++++ .../cci_cfg/cci_param_untyped_handle.cpp | 313 ++++ .../cci_cfg/cci_param_untyped_handle.h | 298 ++++ .../cci-1.0.0/cci_cfg/cci_report_handler.cpp | 145 ++ .../cci-1.0.0/cci_cfg/cci_report_handler.h | 147 ++ third_party/cci-1.0.0/cci_configuration | 42 + third_party/cci-1.0.0/cci_core/cci_callback.h | 425 +++++ .../cci-1.0.0/cci_core/cci_callback_impl.h | 240 +++ third_party/cci-1.0.0/cci_core/cci_cmnhdr.h | 144 ++ .../cci-1.0.0/cci_core/cci_core_types.h | 60 + .../cci-1.0.0/cci_core/cci_filtered_range.h | 236 +++ third_party/cci-1.0.0/cci_core/cci_meta.h | 90 + .../cci-1.0.0/cci_core/cci_name_gen.cpp | 124 ++ third_party/cci-1.0.0/cci_core/cci_name_gen.h | 55 + third_party/cci-1.0.0/cci_core/cci_value.cpp | 975 +++++++++++ third_party/cci-1.0.0/cci_core/cci_value.h | 1546 +++++++++++++++++ .../cci_core/cci_value_converter.cpp | 361 ++++ .../cci-1.0.0/cci_core/cci_value_converter.h | 412 +++++ .../cci-1.0.0/cci_core/cci_value_iterator.h | 190 ++ third_party/cci-1.0.0/cci_core/cci_version.h | 62 + third_party/cci-1.0.0/cci_core/rapidjson.h | 136 ++ third_party/cci-1.0.0/cci_core/systemc.h | 100 ++ third_party/cci-1.0.0/cci_utils/broker.cpp | 162 ++ third_party/cci-1.0.0/cci_utils/broker.h | 88 + .../cci-1.0.0/cci_utils/consuming_broker.cpp | 375 ++++ .../cci-1.0.0/cci_utils/consuming_broker.h | 154 ++ third_party/cci-1.0.0/cciapi-config.cmake.in | 10 + 47 files changed, 11487 insertions(+), 1 deletion(-) create mode 100644 third_party/cci-1.0.0/CMakeLists.txt create mode 100644 third_party/cci-1.0.0/cci_cfg/cci_broker_callbacks.h create mode 100644 third_party/cci-1.0.0/cci_cfg/cci_broker_handle.cpp create mode 100644 third_party/cci-1.0.0/cci_cfg/cci_broker_handle.h create mode 100644 third_party/cci-1.0.0/cci_cfg/cci_broker_if.h create mode 100644 third_party/cci-1.0.0/cci_cfg/cci_broker_manager.cpp create mode 100644 third_party/cci-1.0.0/cci_cfg/cci_broker_manager.h create mode 100644 third_party/cci-1.0.0/cci_cfg/cci_broker_types.h create mode 100644 third_party/cci-1.0.0/cci_cfg/cci_config_macros.h create mode 100644 third_party/cci-1.0.0/cci_cfg/cci_macros_undef.h create mode 100644 third_party/cci-1.0.0/cci_cfg/cci_mutable_types.h create mode 100644 third_party/cci-1.0.0/cci_cfg/cci_originator.cpp create mode 100644 third_party/cci-1.0.0/cci_cfg/cci_originator.h create mode 100644 third_party/cci-1.0.0/cci_cfg/cci_param_callbacks.h create mode 100644 third_party/cci-1.0.0/cci_cfg/cci_param_if.cpp create mode 100644 third_party/cci-1.0.0/cci_cfg/cci_param_if.h create mode 100644 third_party/cci-1.0.0/cci_cfg/cci_param_typed.h create mode 100644 third_party/cci-1.0.0/cci_cfg/cci_param_typed_handle.h create mode 100644 third_party/cci-1.0.0/cci_cfg/cci_param_untyped.cpp create mode 100644 third_party/cci-1.0.0/cci_cfg/cci_param_untyped.h create mode 100644 third_party/cci-1.0.0/cci_cfg/cci_param_untyped_handle.cpp create mode 100644 third_party/cci-1.0.0/cci_cfg/cci_param_untyped_handle.h create mode 100644 third_party/cci-1.0.0/cci_cfg/cci_report_handler.cpp create mode 100644 third_party/cci-1.0.0/cci_cfg/cci_report_handler.h create mode 100644 third_party/cci-1.0.0/cci_configuration create mode 100644 third_party/cci-1.0.0/cci_core/cci_callback.h create mode 100644 third_party/cci-1.0.0/cci_core/cci_callback_impl.h create mode 100644 third_party/cci-1.0.0/cci_core/cci_cmnhdr.h create mode 100644 third_party/cci-1.0.0/cci_core/cci_core_types.h create mode 100644 third_party/cci-1.0.0/cci_core/cci_filtered_range.h create mode 100644 third_party/cci-1.0.0/cci_core/cci_meta.h create mode 100644 third_party/cci-1.0.0/cci_core/cci_name_gen.cpp create mode 100644 third_party/cci-1.0.0/cci_core/cci_name_gen.h create mode 100644 third_party/cci-1.0.0/cci_core/cci_value.cpp create mode 100644 third_party/cci-1.0.0/cci_core/cci_value.h create mode 100644 third_party/cci-1.0.0/cci_core/cci_value_converter.cpp create mode 100644 third_party/cci-1.0.0/cci_core/cci_value_converter.h create mode 100644 third_party/cci-1.0.0/cci_core/cci_value_iterator.h create mode 100644 third_party/cci-1.0.0/cci_core/cci_version.h create mode 100644 third_party/cci-1.0.0/cci_core/rapidjson.h create mode 100644 third_party/cci-1.0.0/cci_core/systemc.h create mode 100644 third_party/cci-1.0.0/cci_utils/broker.cpp create mode 100644 third_party/cci-1.0.0/cci_utils/broker.h create mode 100644 third_party/cci-1.0.0/cci_utils/consuming_broker.cpp create mode 100644 third_party/cci-1.0.0/cci_utils/consuming_broker.h create mode 100644 third_party/cci-1.0.0/cciapi-config.cmake.in diff --git a/third_party/CMakeLists.txt b/third_party/CMakeLists.txt index 95937708f..a2d5f42c2 100644 --- a/third_party/CMakeLists.txt +++ b/third_party/CMakeLists.txt @@ -10,7 +10,11 @@ if(SystemC_FOUND) add_subdirectory(axi_chi) add_subdirectory(scv-tr) if(NOT TARGET systemc-cci::systemc-cci AND NOT TARGET SystemC::cci) - add_subdirectory(cci-1.0.1) + if(USE_CCI_100) + add_subdirectory(cci-1.0.0) + else() + add_subdirectory(cci-1.0.1) + endif() endif() add_subdirectory(lwtr4sc/src) if(WITH_SCP4SCC) diff --git a/third_party/cci-1.0.0/CMakeLists.txt b/third_party/cci-1.0.0/CMakeLists.txt new file mode 100644 index 000000000..c4f2e2654 --- /dev/null +++ b/third_party/cci-1.0.0/CMakeLists.txt @@ -0,0 +1,85 @@ +project(SystemC-CCI VERSION "1.1.0" LANGUAGES CXX) + +add_library(cciapi +${CMAKE_CURRENT_SOURCE_DIR}/cci_cfg/cci_broker_handle.cpp +${CMAKE_CURRENT_SOURCE_DIR}/cci_cfg/cci_broker_manager.cpp +${CMAKE_CURRENT_SOURCE_DIR}/cci_cfg/cci_originator.cpp +${CMAKE_CURRENT_SOURCE_DIR}/cci_cfg/cci_param_if.cpp +${CMAKE_CURRENT_SOURCE_DIR}/cci_cfg/cci_param_untyped.cpp +${CMAKE_CURRENT_SOURCE_DIR}/cci_cfg/cci_param_untyped_handle.cpp +${CMAKE_CURRENT_SOURCE_DIR}/cci_cfg/cci_report_handler.cpp +${CMAKE_CURRENT_SOURCE_DIR}/cci_core/cci_name_gen.cpp +${CMAKE_CURRENT_SOURCE_DIR}/cci_core/cci_value.cpp +${CMAKE_CURRENT_SOURCE_DIR}/cci_core/cci_value_converter.cpp +${CMAKE_CURRENT_SOURCE_DIR}/cci_utils/broker.cpp +${CMAKE_CURRENT_SOURCE_DIR}/cci_utils/consuming_broker.cpp) +if(USE_NCSC_SYSTEMC OR USE_CWR_SYSTEMC) + target_compile_definitions(cciapi PUBLIC SC_VERSION_CODE=200301) +endif() +target_include_directories(cciapi PUBLIC + $ # for headers when building + $ # for client in install mode +) +if(USE_CWR_SYSTEMC) + get_target_property(SC_COMPILE_OPTIONS ${SystemC_LIBRARIES} INTERFACE_COMPILE_OPTIONS) + if(SC_COMPILE_OPTIONS) + target_compile_definitions(cciapi PUBLIC ${SC_COMPILE_OPTIONS}) + else() + target_compile_definitions(cciapi PUBLIC ${SystemC_DEFINITIONS}) + endif() + get_target_property(SC_INCLUDE_DIRS ${SystemC_LIBRARIES} INTERFACE_INCLUDE_DIRECTORIES) + if(SC_INCLUDE_DIRS) + target_include_directories(cciapi PUBLIC ${SC_INCLUDE_DIRS}) + else() + target_include_directories(cciapi PUBLIC ${SystemC_INCLUDE_DIRS}) + endif() +else() + target_link_libraries(cciapi PUBLIC SystemC::systemc) +endif() +target_link_libraries(cciapi PUBLIC RapidJSON) + +if(NOT TARGET systemc-cci::systemc-cci) + add_library(systemc-cci::systemc-cci ALIAS cciapi) +endif() + +set_target_properties(cciapi PROPERTIES + VERSION ${PROJECT_VERSION} + FRAMEWORK FALSE + PUBLIC_HEADER ${CMAKE_CURRENT_SOURCE_DIR}/cci_configuration + CXX_CLANG_TIDY "" +) + +set(CCIAPI_CMAKE_CONFIG_DIR ${CMAKE_INSTALL_LIBDIR}/cmake/cciapi) +install(TARGETS cciapi COMPONENT cci EXPORT cciapi-targets + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}${SCC_LIBRARY_DIR_MODIFIER} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}${SCC_LIBRARY_DIR_MODIFIER}${SCC_ARCHIVE_DIR_MODIFIER} + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + ) + +install(EXPORT cciapi-targets + DESTINATION ${CCIAPI_CMAKE_CONFIG_DIR}) + +include(CMakePackageConfigHelpers) +write_basic_package_version_file( + ${CMAKE_CURRENT_BINARY_DIR}/cciapi-config-version.cmake + VERSION ${PROJECT_VERSION} + COMPATIBILITY AnyNewerVersion +) + +configure_package_config_file( + ${CMAKE_CURRENT_LIST_DIR}/cciapi-config.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/cciapi-config.cmake + INSTALL_DESTINATION ${CCIAPI_CMAKE_CONFIG_DIR} +) + +install(FILES + ${CMAKE_CURRENT_BINARY_DIR}/cciapi-config.cmake + ${CMAKE_CURRENT_BINARY_DIR}/cciapi-config-version.cmake + DESTINATION ${CCIAPI_CMAKE_CONFIG_DIR}) + +install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/. COMPONENT cci + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} # target directory + FILES_MATCHING # install only matched files + PATTERN "*.h" # select header files + ) diff --git a/third_party/cci-1.0.0/cci_cfg/cci_broker_callbacks.h b/third_party/cci-1.0.0/cci_cfg/cci_broker_callbacks.h new file mode 100644 index 000000000..56cb86ab7 --- /dev/null +++ b/third_party/cci-1.0.0/cci_cfg/cci_broker_callbacks.h @@ -0,0 +1,89 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + ****************************************************************************/ + +#ifndef CCI_CFG_CCI_BROKER_CALLBACKS_H_INCLUDED_ +#define CCI_CFG_CCI_BROKER_CALLBACKS_H_INCLUDED_ + +#include "cci_core/cci_callback.h" +#include "cci_core/cci_value.h" + +CCI_OPEN_NAMESPACE_ + +class cci_param_untyped_handle; +class cci_originator; + +/// Parameter creation callback +typedef cci_callback + cci_param_create_callback; + +/// Parameter creation callback handle +typedef cci_callback_typed_handle + cci_param_create_callback_handle; + +/// Parameter destruction callback +typedef cci_callback + cci_param_destroy_callback; + +/// Parameter destruction callback handle +typedef cci_callback_typed_handle + cci_param_destroy_callback_handle; + +/// Parameter predicate +typedef cci_callback + cci_param_predicate; + +/// Parameter predicate handle +typedef cci_callback_typed_handle + cci_param_predicate_handle; + +/// Preset value predicate +typedef cci_callback&, bool > + cci_preset_value_predicate; + +/// Preset value predicate handle +typedef cci_callback_typed_handle&, + bool > cci_preset_value_predicate_handle; + +/* ------------------------------------------------------------------------ */ + +/// Callback API of CCI brokers +struct cci_broker_callback_if +{ + virtual cci_param_create_callback_handle + register_create_callback( const cci_param_create_callback& cb + , const cci_originator& orig ) = 0; + virtual bool + unregister_create_callback( const cci_param_create_callback_handle& cb + , const cci_originator& orig ) = 0; + + virtual cci_param_destroy_callback_handle + register_destroy_callback( const cci_param_destroy_callback& cb + , const cci_originator& orig ) = 0; + virtual bool + unregister_destroy_callback( const cci_param_destroy_callback_handle& cb + , const cci_originator& orig ) = 0; + + virtual bool unregister_all_callbacks(const cci_originator& orig) = 0; + + virtual bool has_callbacks() const = 0; +}; + +CCI_CLOSE_NAMESPACE_ + +#endif // CCI_CFG_CCI_BROKER_CALLBACKS_H_INCLUDED_ diff --git a/third_party/cci-1.0.0/cci_cfg/cci_broker_handle.cpp b/third_party/cci-1.0.0/cci_cfg/cci_broker_handle.cpp new file mode 100644 index 000000000..0b54a5338 --- /dev/null +++ b/third_party/cci-1.0.0/cci_cfg/cci_broker_handle.cpp @@ -0,0 +1,179 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + +****************************************************************************/ + +/** + * @author Guillaume Delbergue, Ericsson / GreenSocs + */ + +#include "cci_cfg/cci_broker_handle.h" + +#include "cci_cfg/cci_broker_if.h" +#include "cci_cfg/cci_broker_manager.h" +#include "cci_cfg/cci_report_handler.h" + +CCI_OPEN_NAMESPACE_ + +cci_broker_handle::cci_broker_handle(cci_broker_if& broker, + const cci_originator& originator) + : m_broker(&broker) + , m_originator(originator) +{ +} + +cci_broker_handle +cci_broker_handle::create_broker_handle(const cci_originator &originator) +{ + return m_broker->create_broker_handle(originator); +} + +cci_originator cci_broker_handle::get_originator() const +{ + return m_originator; +} + +const char* cci_broker_handle::name() const +{ + return m_broker->name(); +} + +void cci_broker_handle::set_preset_cci_value( + const std::string &parname, + const cci::cci_value &cci_value) +{ + m_broker->set_preset_cci_value(parname, cci_value, m_originator); +} + +cci::cci_value cci_broker_handle::get_preset_cci_value( + const std::string &parname) const +{ + return m_broker->get_preset_cci_value(parname); +} + +std::vector +cci_broker_handle::get_unconsumed_preset_values() const +{ + return m_broker->get_unconsumed_preset_values(); +} + +cci_preset_value_range cci_broker_handle::get_unconsumed_preset_values( + const cci_preset_value_predicate &pred) const +{ + return m_broker->get_unconsumed_preset_values(pred); +} + +void cci_broker_handle::ignore_unconsumed_preset_values( + const cci_preset_value_predicate &pred) +{ + m_broker->ignore_unconsumed_preset_values(pred); +} + +cci_originator +cci_broker_handle::get_value_origin(const std::string &parname) const +{ + return m_broker->get_value_origin(parname); +} + +cci_originator +cci_broker_handle::get_preset_value_origin(const std::string &parname) const +{ + return m_broker->get_preset_value_origin(parname); +} + +void cci_broker_handle::lock_preset_value(const std::string &parname) +{ + m_broker->lock_preset_value(parname); +} + +cci_value cci_broker_handle::get_cci_value(const std::string &parname) const +{ + return m_broker->get_cci_value(parname); +} + +cci_param_untyped_handle +cci_broker_handle::get_param_handle(const std::string &parname) const +{ + return m_broker->get_param_handle(parname, m_originator); +} + +bool cci_broker_handle::has_preset_value(const std::string &parname) const +{ + return m_broker->has_preset_value(parname); +} + +void cci_broker_handle::add_param(cci_param_if *par) +{ + m_broker->add_param(par); +} + +void cci_broker_handle::remove_param(cci_param_if *par) +{ + m_broker->remove_param(par); +} + +std::vector cci_broker_handle::get_param_handles() const +{ + return m_broker->get_param_handles(m_originator); +} + +cci_param_range cci_broker_handle::get_param_handles( + cci_param_predicate& pred) const +{ + return m_broker->get_param_handles(pred, m_originator); +} + +bool cci_broker_handle::is_global_broker() const +{ + return m_broker->is_global_broker(); +} + +cci_param_create_callback_handle cci_broker_handle::register_create_callback( + const cci_param_create_callback& cb) +{ + return m_broker->register_create_callback(cb, m_originator); +} + +bool cci_broker_handle::unregister_create_callback( + const cci_param_create_callback_handle& cb) +{ + return m_broker->unregister_create_callback(cb, m_originator); +} + +cci_param_destroy_callback_handle cci_broker_handle::register_destroy_callback( + const cci_param_destroy_callback& cb) +{ + return m_broker->register_destroy_callback(cb, m_originator); +} + +bool cci_broker_handle::unregister_destroy_callback( + const cci_param_destroy_callback_handle& cb) +{ + return m_broker->unregister_destroy_callback(cb, m_originator); +} + +bool cci_broker_handle::unregister_all_callbacks() +{ + return m_broker->unregister_all_callbacks(m_originator); +} + +bool cci_broker_handle::has_callbacks() const +{ + return m_broker->has_callbacks(); +} + +CCI_CLOSE_NAMESPACE_ diff --git a/third_party/cci-1.0.0/cci_cfg/cci_broker_handle.h b/third_party/cci-1.0.0/cci_cfg/cci_broker_handle.h new file mode 100644 index 000000000..0d12541ea --- /dev/null +++ b/third_party/cci-1.0.0/cci_cfg/cci_broker_handle.h @@ -0,0 +1,253 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + ****************************************************************************/ + +#ifndef CCI_CFG_CCI_BROKER_HANDLE_H_INCLUDED_ +#define CCI_CFG_CCI_BROKER_HANDLE_H_INCLUDED_ + +#include "cci_cfg/cci_broker_types.h" +#include "cci_cfg/cci_originator.h" +#include "cci_cfg/cci_param_typed_handle.h" +#include "cci_core/cci_cmnhdr.h" +#include "cci_core/cci_value.h" + +/** + * @author Guillaume Delbergue, Ericsson / GreenSocs + */ + +CCI_OPEN_NAMESPACE_ + +// Forward declarations +class cci_param_if; +class cci_broker_if; +template class cci_param_typed_handle; + +// CCI Broker handle class +/** +* Broker handle class informing broker of originator when required. +* Provides a broker-like interface. +*/ +class cci_broker_handle +{ +public: + /// Constructor to create handle with given originator. + cci_broker_handle(cci_broker_if& broker, + const cci_originator& originator); + + cci_broker_handle(const cci_broker_handle& broker_handle) + : m_broker(broker_handle.m_broker) + , m_originator(promote_originator(broker_handle.m_originator)) {} + + cci_broker_handle& operator=(const cci_broker_handle& broker_handle) + { + m_broker = broker_handle.m_broker; + // originator is preserved during assignment + return *this; + } + +#if CCI_CPLUSPLUS >= 201103L + cci_broker_handle(cci_broker_handle&& that) + : m_broker(CCI_MOVE_(that.m_broker)) + , m_originator(promote_originator(that.m_originator)) {} + + cci_broker_handle& operator=(cci_broker_handle&& that) + { + m_broker = CCI_MOVE_(that.m_broker); + // originator is preserved during assignment + return *this; + } + + ~cci_broker_handle() = default; +#endif // CCI_CPLUSPLUS + + /// @copydoc cci_broker_if::create_broker_handle + cci_broker_handle + create_broker_handle(const cci_originator &originator = cci_originator()); + + /// Query the originator of the broker. + /** + * The originator identifies the entity accessing the broker + * through this handle. + */ + cci_originator get_originator() const; + + /// @copydoc cci_broker_if::name + const char* name() const; + + /// @copydoc cci_broker_if::set_preset_cci_value + void set_preset_cci_value(const std::string &parname, + const cci_value &cci_value); + + /// @copydoc cci_broker_if::get_preset_cci_value + cci_value get_preset_cci_value(const std::string &parname) const; + + /// @copydoc cci_broker_if::get_unconsumed_preset_values() + std::vector get_unconsumed_preset_values() const; + + /// @copydoc cci_broker_if::has_preset_value + bool has_preset_value(const std::string &parname) const; + + /// @copydoc cci_broker_if::get_unconsumed_preset_values(const cci_preset_value_predicate&) + cci_preset_value_range get_unconsumed_preset_values( + const cci_preset_value_predicate &pred) const; + + /// @copydoc cci_broker_if::ignore_unconsumed_preset_values + void ignore_unconsumed_preset_values( + const cci_preset_value_predicate &pred); + + /// @copydoc cci_broker_if::get_value_origin + cci_originator + get_value_origin(const std::string &parname) const; + + /// @copydoc cci_broker_if::get_preset_value_origin + cci_originator + get_preset_value_origin(const std::string &parname) const; + + /// @copydoc cci_broker_if::lock_preset_value + void lock_preset_value(const std::string &parname); + + /// @copydoc cci_broker_if::get_cci_value + cci_value get_cci_value(const std::string &parname) const; + + /// @copydoc cci_broker_if::add_param + void add_param(cci_param_if *par); + + /// @copydoc cci_broker_if::remove_param + void remove_param(cci_param_if *par); + + /// @copydoc cci_broker_if::get_param_handles(const std::string&) + std::vector get_param_handles() const; + + /// @copydoc cci_broker_if::get_param_handles(cci_param_predicate&) + cci_param_range + get_param_handles(cci_param_predicate& pred) const; + + /// @copydoc cci_broker_if::get_param_handle + cci_param_untyped_handle get_param_handle(const std::string &parname) const; + + /// Convenience function to get a typed parameter handle. + /** + * @param parname Full hierarchical parameter name. + * @return Parameter handle (invalid if not existing or the type is not correct) + */ + template + cci_param_typed_handle get_param_handle(const std::string &parname) const { + return cci_param_typed_handle(get_param_handle(parname)); + } + + /** @name Parameter creation/destruction callbacks */ + //@{ + /// @copydoc cci_broker_callback_if::register_create_callback + cci_param_create_callback_handle + register_create_callback(const cci_param_create_callback& cb); + + /** + * @brief Convenience overload to register callback for a member function + * @param cb Member function pointer to be used as callback + * @param obj Object to invoke member function on + * @see register_create_callback(const cci_param_create_callback&) + */ + template + cci_param_create_callback_handle + register_create_callback( cci_param_create_callback::signature (Owner::*cb) + , Owner* obj ) + { return register_create_callback( sc_bind( cb, obj, sc_unnamed::_1 ) ); } + + /// @copydoc cci_broker_callback_if::unregister_create_callback + bool unregister_create_callback(const cci_param_create_callback_handle& cb); + + /// @copydoc cci_broker_callback_if::register_destroy_callback + cci_param_destroy_callback_handle + register_destroy_callback(const cci_param_destroy_callback& cb); + + /** + * @brief Convenience overload to register callback for a member function + * @param cb Member function pointer to be used as callback + * @param obj Object to invoke member function on + * @see register_destroy_callback(const cci_param_destroy_callback&) + */ + template + cci_param_destroy_callback_handle + register_destroy_callback( cci_param_destroy_callback::signature (Owner::*cb) + , Owner* obj ) + { return register_destroy_callback( sc_bind( cb, obj, sc_unnamed::_1 ) ); } + + /// @copydoc cci_broker_callback_if::unregister_destroy_callback + bool + unregister_destroy_callback(const cci_param_destroy_callback_handle& cb); + + /// @copydoc cci_broker_callback_if::unregister_all_callbacks + bool unregister_all_callbacks(); + + /// @copydoc cci_broker_callback_if::has_callbacks + bool has_callbacks() const; + //@} + + /// @copydoc cci_broker_if::is_global_broker + bool is_global_broker() const; + + /// equality between this handle and a broker pointer (typically 'this' + /// broker) + /** + * @param pointer to a broker + * @return equality + */ + bool operator==(const cci_broker_if *b) const { + return m_broker==b; + } + + /** + * @param pointer to a broker + * @return inequality + */ + bool operator!=(const cci_broker_if *b) const { + return m_broker!=b; + } +protected: + /// Promote a gifted originator to one that represents the current context + /// when possible (i.e. when within the module hierarchy) + /** + * @param gifted_originator associated with the copy ctor broker argument + * @return context originator if possible; otherwise, the gifted_originator + */ + inline const cci_originator promote_originator(const cci_originator &gifted_originator); + +private: + friend class cci_broker_if; + friend class cci_param_if; + cci_broker_if& ref() { return *m_broker; } + const cci_broker_if& ref() const { return *m_broker; } + +private: + cci_broker_if* m_broker; + cci_originator m_originator; +}; + + + +const cci_originator cci_broker_handle::promote_originator( + const cci_originator &gifted_originator) +{ + if (sc_core::sc_get_current_object()) + return cci_originator(); + else + return gifted_originator; +} + +CCI_CLOSE_NAMESPACE_ +#endif // CCI_CFG_CCI_BROKER_HANDLE_H_INCLUDED_ diff --git a/third_party/cci-1.0.0/cci_cfg/cci_broker_if.h b/third_party/cci-1.0.0/cci_cfg/cci_broker_if.h new file mode 100644 index 000000000..44fdc534d --- /dev/null +++ b/third_party/cci-1.0.0/cci_cfg/cci_broker_if.h @@ -0,0 +1,300 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + ****************************************************************************/ + +#ifndef CCI_CFG_CCI_BROKER_IF_H_INCLUDED_ +#define CCI_CFG_CCI_BROKER_IF_H_INCLUDED_ + +#include "cci_cfg/cci_broker_types.h" +#include "cci_cfg/cci_param_untyped_handle.h" + +CCI_OPEN_NAMESPACE_ + +// forward declaration +class cci_param_if; + +// forward declaration +template +class cci_param_typed_handle; + +// forward declaration for friend class +class cci_broker_handle; + +/** + * @brief CCI configuration broker interface + * + * This class provides the core interface for "tools" accessing + * the availabe configuration parameters in a model. Parameters + * are accessed via brokers, implementing this interface. + * + * Usually, brokers are not accessed directly, but via broker + * handles, including an additional cci_originator for access + * tracking. + * + * The functions of this interface can be grouped as follows: + * @li Providing initial preset values for parameters (configuration) + * @li Parameter registration and unregistration + * @li Parameter lookup and enumeration + * @li Callback handling + * + * @see cci_broker_handle, cci_get_broker(), cci_register_broker() + * + * For convenience, the CCI PoC implementation provides two + * simple brokers: + * @see cci_utils::broker, cci_utils::consuming_broker + */ +class cci_broker_if + : public cci_broker_callback_if +{ +public: + friend class cci_broker_handle; + friend class cci_param_if; + + /** + * @brief Convenience function to create a new broker handle + * @param originator Originator for access tracking (forwarded to parameter handles) + * @return broker handle for the given (or current) originator + * @note The default argument can only be reliably used from within + * the SystemC hierarchy during elaboration. + * @see cci_originator + */ + cci_broker_handle + create_broker_handle(const cci_originator &originator = cci_originator()) const; + + /// Name of this broker + /** + * Shall be a system-wide unique broker name. + * Broker handles shall return their underlying broker's name. + * + * @return broker name + */ + virtual const char* name() const = 0; + + // //////////////////////////////////////////////////////////////////// // + // /////////// Access Parameters and Values /////////////////////// // + + /// Set a parameter's preset value. + /** + * The preset value has priority to the default value being set by the owner! + * + * @exception cci::cci_report::set_param_failed Setting parameter + * object failed + * @param parname Full hierarchical parameter name. + * @param cci_value cci::cci_value representation of the preset value the + * parameter has to be set to. + * @param originator originator reference to the originator + * (not applicable in case of broker handle) + */ + virtual void set_preset_cci_value(const std::string &parname, + const cci::cci_value &cci_value, + const cci_originator& originator) = 0; + + /// Get a parameter's preset value. + /** + * + * @param parname Full hierarchical parameter name. + * @return CCI value of the parameter's preset value. Empty value is returned when parameter is not existing or its preset value is not existing + */ + virtual cci::cci_value + get_preset_cci_value(const std::string &parname) const = 0; + + /// Get unconsumed preset values + /** + * Querying of unconsumed values. An unconsumed value is an "preset" value + * supplied to a broker for which no parameter is ever created. + * + * @return Vector of unconsumed parameter's preset value. + */ + virtual std::vector get_unconsumed_preset_values() const = 0; + + /// Get unconsumed preset values with a user-defined predicate callback + /** + * Querying of unconsumed values. An unconsumed value is an "preset" value + * supplied to a broker for which no parameter is ever created. + * + * @param pred Callback to filter unconsumed preset values. + * @return Vector of unconsumed parameter's preset value. + */ + virtual cci_preset_value_range get_unconsumed_preset_values( + const cci_preset_value_predicate &pred) const = 0; + + /// Ignore unconsumed preset values + /** + * Filtering of unconsumed values. An unconsumed value is an "preset" value + * supplied to a broker for which no parameter is ever created. This method + * affects future calls to @see get_unconsumed_preset_values(). + * + * @param pred Callback to ignore unconsumed preset values. + */ + virtual void ignore_unconsumed_preset_values( + const cci_preset_value_predicate &pred) = 0; + + /// Returns the originator that wrote the parameter's current value. + /** + * @param parname Name of a parameter. + * @return originator + */ + virtual cci_originator + get_value_origin(const std::string &parname) const = 0; + + /// Returns originator of the preset value if a preset value exists, otherwise unknown originator. + /** + * @param parname Name of a parameter. + * @return originator which will be the unknown originator when no preset value exists + */ + virtual cci_originator + get_preset_value_origin(const std::string &parname) const = 0; + + /// Lock a parameter's preset value. + /** + * Lock so that this parameter's preset value cannot be overwritten by + * any subsequent set_preset_value call. This allows to emulate a hierarchical + * precendence since a top-level module can prevent the childs from setting + * preset values by locking the preset value before creating the subsystem. + * + * Throws (and does not lock) if no preset value exists + * that can be locked or if a preset value is already locked or if the + * parameter is already existing as object. + * + * @exception cci::cci_report::set_param_failed Locking parameter object failed + * @param parname Hierarchical parameter name. + */ + virtual void lock_preset_value(const std::string &parname) = 0; + + /// Get a parameter's value (CCI value representation). + /** + * Returns the value of the named parameter. + * + * @param parname Full hierarchical name of the parameter whose value should be returned. + * @param originator Reference to the originator + * @return CCI value of the parameter + */ + virtual cci::cci_value get_cci_value(const std::string &parname, + const cci_originator &originator = cci_originator()) const = 0; + + /// Get a parameter handle. + /** + * This returns not the owner's parameter object but a handle. + * + * @param parname Full hierarchical parameter name. + * @param originator Reference to the originator + * @return Parameter handle object (invalid if not existing). + */ + virtual cci_param_untyped_handle + get_param_handle(const std::string &parname, + const cci_originator& originator) const = 0; + + /// Returns if the parameter has a preset value + /** + * @param parname Full hierarchical parameter name. + * @return If the parameter has a preset value set + */ + virtual bool has_preset_value(const std::string &parname) const = 0; + + // //////////////////////////////////////////////////////////////////// // + // /////////////// Registry Functions ///////////////////////////// // + + /// Adds a parameter to the registry. + /** + * Note: addPar (and all related methods) must not call any of the + * pure virtual functions in cci_param_untyped_handle because + * this method may be called by the cci_param_untyped_handle + * constructor. + * + * Note: This function shall never been called for any parameter handle + * objects but only for "real" parameter objects. + * + * @exception cci::cci_report::add_param_failed Adding parameter object + * failed + * @param par Parameter (including name and value). + */ + virtual void add_param(cci_param_if *par) = 0; + + /// Removes a parameter from the registry. May only be called by the + /// parameter destructor, must not be called by anyone else. + /** + * It should be ensured this is not being called from elsewhere than the + * parameter destructor (e.g. by user). + * + * Note: This function shall never been called for any parameter handle + * objects but only for "real" parameter objects. + * + * @exception cci::cci_report::remove_param_failed Remove parameter object + * failed + * @param par Parameter pointer. + */ + virtual void remove_param(cci_param_if *par) = 0; + + /// Return a list of all parameter handles in the given scope + /** + * + * This returns not the owner's parameter objects but handles. + * + * @param pattern Specifies the parameters to be returned. + * @return Vector with parameter handles. + */ + virtual std::vector + get_param_handles(const cci_originator& originator = cci_originator()) const = 0; + + /// Search parameters with a user-defined predicate callback + /** + * @param pred Callback to filter parameters + * @return cci_iterable Iterable parameters + */ + virtual cci_param_range + get_param_handles(cci_param_predicate& pred, + const cci_originator& originator) const = 0; + + ///If this broker is a private broker (or handle) + /** + * @return If this broker is the global broker + */ + virtual bool is_global_broker() const = 0; + +protected: + /// Default Constructor + cci_broker_if() {} + + /// Destructor + virtual ~cci_broker_if() {} + + cci_originator unknown_originator() const + { return cci_originator( cci_originator::unknown_tag() ); } + + static cci_broker_if &unwrap_broker(cci_broker_handle h) + { return h.ref(); } + +private: + // Disabled + cci_broker_if(const cci_broker_if&); + cci_broker_if& operator=(const cci_broker_if&); +#ifdef CCI_HAS_CXX_RVALUE_REFS + cci_broker_if(cci_broker_if&&); + cci_broker_if& operator=(cci_broker_if&&); +#endif +}; + +inline cci_broker_handle +cci_broker_if::create_broker_handle(const cci_originator& originator) const +{ + return cci_broker_handle(*const_cast(this), originator); +} + +CCI_CLOSE_NAMESPACE_ + +#endif // CCI_CFG_CCI_BROKER_IF_H_INCLUDED_ diff --git a/third_party/cci-1.0.0/cci_cfg/cci_broker_manager.cpp b/third_party/cci-1.0.0/cci_cfg/cci_broker_manager.cpp new file mode 100644 index 000000000..5b53dc66a --- /dev/null +++ b/third_party/cci-1.0.0/cci_cfg/cci_broker_manager.cpp @@ -0,0 +1,93 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + ****************************************************************************/ + +#include "cci_cfg/cci_broker_manager.h" + +#include "cci_cfg/cci_broker_if.h" +#include "cci_cfg/cci_originator.h" +#include "cci_cfg/cci_report_handler.h" + +CCI_OPEN_NAMESPACE_ + +std::map cci_broker_manager::m_brokers; + +cci_broker_handle +cci_broker_manager::get_broker(const cci_originator &originator) +{ + const sc_core::sc_object *org=originator.get_object(); + while (true) { + std::map::iterator it = + m_brokers.find(org); + if(it != m_brokers.end()) { + cci_broker_handle broker_handle=(it->second)->create_broker_handle(originator); + return broker_handle; + } + if (!org) { + CCI_REPORT_ERROR("cci_broker_manager","No global broker found!"); + // Abort since no reasonable recovery when the exception is suppressed. + cci_abort(); + } + org = org->get_parent_object(); + } +} + +cci_broker_handle +cci_broker_manager::register_broker(cci_broker_if& broker) +{ + const sc_core::sc_object *obj=sc_core::sc_get_current_object(); + + cci_broker_if* & broker_entry = m_brokers[obj]; // find broker position in registry + if( !broker_entry ) { + broker_entry = &broker; // store broker in registry + } + if( &broker != broker_entry ) { // we already had a different entry! + CCI_REPORT_ERROR("cci_broker_manager/register_broker", + "A broker is already registered in the current" + " hierarchy."); + /* If this error is supproessed, our recovery is to pass back a handle to the existing broker */ + } + if (obj) return broker_entry->create_broker_handle(cci_originator()); + else return broker_entry->create_broker_handle(cci_originator(CCI_UNKNOWN_ORIGINATOR_STRING_)); +} + + +cci_broker_handle cci_get_broker() { + if (!sc_core::sc_get_current_object()) { + CCI_REPORT_ERROR("cci_get_broker","You may not request a broker from outside the SystemC hierarchy (use cci::cci_get_global_broker)"); + /* get broker may well work, so we'll not abort */ + } + return cci_broker_manager::get_broker(cci_originator()); +} +cci_broker_handle cci_register_broker(cci_broker_if& broker) +{ + return cci_broker_manager::register_broker(broker); +} +cci_broker_handle cci_register_broker(cci_broker_if* broker) +{ + return cci_broker_manager::register_broker(broker); +} +cci_broker_handle cci_get_global_broker(const cci_originator &originator) +{ + if (sc_core::sc_get_current_object() || originator.get_object()) { + CCI_REPORT_ERROR("cci_get_global_broker","You may not request the global broker from within the SystemC hierarchy (use cci::cci_get_broker)"); + } + return cci_broker_manager::get_broker(originator).create_broker_handle(originator); +} + +CCI_CLOSE_NAMESPACE_ diff --git a/third_party/cci-1.0.0/cci_cfg/cci_broker_manager.h b/third_party/cci-1.0.0/cci_cfg/cci_broker_manager.h new file mode 100644 index 000000000..0c4eaa2af --- /dev/null +++ b/third_party/cci-1.0.0/cci_cfg/cci_broker_manager.h @@ -0,0 +1,112 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + ****************************************************************************/ + +#ifndef CCI_CCI_BROKER_MANAGER_H_INCLUDED_ +#define CCI_CCI_BROKER_MANAGER_H_INCLUDED_ + +#include "cci_cfg/cci_broker_handle.h" +#include "cci_cfg/cci_broker_if.h" +#include "cci_cfg/cci_config_macros.h" +#include "cci_cfg/cci_report_handler.h" +#include + +CCI_OPEN_NAMESPACE_ + +class cci_broker_if; + +/// +/* this is the implementation class for a cci_broker_manager + * it is only required here to enable cci_param_untyped_handle to have access to + * get_broker(originator) + */ +class cci_broker_manager +{ + friend cci_broker_handle cci_get_broker(); + friend cci_broker_handle cci_register_broker(cci_broker_if&); + friend cci_broker_handle cci_register_broker(cci_broker_if*); + friend cci_broker_handle cci_get_global_broker(const cci_originator &); + +private: + /// Returns a handle to the broker currently on top of broker + /** + * Returns a handle to a private or the global broker. + * Returns a handle to the global broker if no registered broker. + * + * @return Broker (private or global) handle + */ + static cci_broker_handle get_broker(const cci_originator &originator); + + /// Register a broker handle in the broker hierarchy + /** + * This can be used to register a private broker handle in the current + * hierarchy. + * + * In case a broker is already registered at the current hierarchy, an + * error will be generated. + * + * @param broker Broker handle to register + */ + static cci_broker_handle register_broker(cci_broker_if& broker); + + static cci_broker_handle register_broker(cci_broker_if* broker) + { + sc_assert(broker); + return register_broker(*broker); + } + +private: + /// Public broker hierarchy + static std::map m_brokers; + +}; + +/// Returns a handle to the currently responsible broker +/** + * Returns a handle to a private or the global broker. + * Returns a handle to the global broker if no registered broker. + * + * @return Broker (private or global) handle + */ +cci_broker_handle cci_get_broker(); +/// Register a broker for the current location +/** + * This can be used to register a private broker handle in the current + * location (either within the SystemC object hierarchy or globally). + * + * In case a different broker has already been registered at the current + * location, an error will be generated. + * + * @param broker Broker handle to register + */ +cci_broker_handle cci_register_broker(cci_broker_if& broker); +/// @copydoc cci_register_broker(cci_broker_if& broker); +cci_broker_handle cci_register_broker(cci_broker_if* broker); + +/** + * convenience to get a broker and create a handle from the global scope + * + * @return A handle to the broker registered at the global scope + * This function will throw if there is no broker registered + */ +cci_broker_handle cci_get_global_broker(const cci_originator &originator); + + +CCI_CLOSE_NAMESPACE_ + +#endif diff --git a/third_party/cci-1.0.0/cci_cfg/cci_broker_types.h b/third_party/cci-1.0.0/cci_cfg/cci_broker_types.h new file mode 100644 index 000000000..fbabf8a48 --- /dev/null +++ b/third_party/cci-1.0.0/cci_cfg/cci_broker_types.h @@ -0,0 +1,47 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + ****************************************************************************/ + +#ifndef CCI_CFG_CCI_BROKER_TYPES_H_INCLUDED_ +#define CCI_CFG_CCI_BROKER_TYPES_H_INCLUDED_ + +#include +#include // std::pair +#include "cci_cfg/cci_broker_callbacks.h" +#include "cci_core/cci_filtered_range.h" +#include "cci_core/cci_value.h" + +CCI_OPEN_NAMESPACE_ + +// forward declaration +class cci_param_untyped_handle; + +/// CCI parameter filter iterator type +typedef cci_filtered_range + cci_param_range; + +/// CCI value with parameter name pair type +typedef std::pair cci_name_value_pair; + +/// CCI preset value filter iterator type +typedef cci_filtered_range + cci_preset_value_range; + +CCI_CLOSE_NAMESPACE_ + +#endif // CCI_CFG_CCI_BROKER_TYPES_H_INCLUDED_ diff --git a/third_party/cci-1.0.0/cci_cfg/cci_config_macros.h b/third_party/cci-1.0.0/cci_cfg/cci_config_macros.h new file mode 100644 index 000000000..e00ff7617 --- /dev/null +++ b/third_party/cci-1.0.0/cci_cfg/cci_config_macros.h @@ -0,0 +1,48 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + ****************************************************************************/ + +/** + * @author Christian Schroeder, GreenSocs Ltd. + * @author Mark Burton, GreenSocs Ltd. + */ + +#ifndef CCI_CCI_CONFIG_MACROS_H_INCLUDED_ +#define CCI_CCI_CONFIG_MACROS_H_INCLUDED_ + +// Some default strings - user should define custom ones before including CCI +// (and before building parameter or broker code since they are used beyond +// the client API library) + +#ifndef CCI_OWNER_ORIGINATOR_STRING_ +# define CCI_OWNER_ORIGINATOR_STRING_ "OWNER_ORIGINATOR" +#endif + +#ifndef CCI_UNKNOWN_ORIGINATOR_STRING_ +# define CCI_UNKNOWN_ORIGINATOR_STRING_ "UNKNOWN_ORIGINATOR" +#endif + +#ifndef CCI_SC_REPORT_MSG_TYPE_PREFIX_ +# define CCI_SC_REPORT_MSG_TYPE_PREFIX_ "/Accellera/CCI/" +#endif + +#ifndef CCI_CFG_SC_REPORT_MSG_TYPE_PREFIX_ +# define CCI_CFG_SC_REPORT_MSG_TYPE_PREFIX_ CCI_SC_REPORT_MSG_TYPE_PREFIX_ "Config/" +#endif + +#endif //CCI_CCI_CONFIG_MACROS_H_INCLUDED_ diff --git a/third_party/cci-1.0.0/cci_cfg/cci_macros_undef.h b/third_party/cci-1.0.0/cci_cfg/cci_macros_undef.h new file mode 100644 index 000000000..120aee768 --- /dev/null +++ b/third_party/cci-1.0.0/cci_cfg/cci_macros_undef.h @@ -0,0 +1,47 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + ****************************************************************************/ + +/** + * @author Christian Schroeder, GreenSocs Ltd. + * @author Mark Burton, GreenSocs Ltd. + * @author Thomas Goodfellow, OFFIS + * @brief Undef CCI internal macros (housekeeping) + */ + +// Since this is solely for removing symbols it can be included mulitple times +// safely (which may even be useful, when hunting a symbol's origin) + +/** Define this before including root "cci" to make use of naming and debugging + * macros; nobody beyond API implementors should *need* this + */ +#ifndef CCI_CNF_SHARE_LIBRARY_MACROS + +#undef CCI_OWNER_ORIGINATOR_STRING_ +#undef CCI_DEFAULT_BROKER_STRING_ +#undef CCI_UNKNOWN_ORIGINATOR_STRING_ + +#undef CCI_SC_REPORT_MSG_TYPE_PREFIX_ +#undef CCI_CFG_SC_REPORT_MSG_TYPE_PREFIX_ + +// May need these debugging macros split out to a separate undef header, so +// that the client can remove all macros except the debugging ones +#undef CCI_CNF_DUMP +#undef CCI_PARAM_DUMP + +#endif diff --git a/third_party/cci-1.0.0/cci_cfg/cci_mutable_types.h b/third_party/cci-1.0.0/cci_cfg/cci_mutable_types.h new file mode 100644 index 000000000..a0499dc33 --- /dev/null +++ b/third_party/cci-1.0.0/cci_cfg/cci_mutable_types.h @@ -0,0 +1,42 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + ****************************************************************************/ + +#ifndef CCI_CFG_CCI_MUTABLE_TYPES_H_INCLUDED_ +#define CCI_CFG_CCI_MUTABLE_TYPES_H_INCLUDED_ + +#include "cci_core/cci_cmnhdr.h" + +CCI_OPEN_NAMESPACE_ + +/** + * Enumeration for cci_param_typed template specifying the parameter type + * according the lock behavior + */ +enum cci_param_mutable_type { + /// Mutable Parameter + CCI_MUTABLE_PARAM = 0, + /// Immutable Parameter + CCI_IMMUTABLE_PARAM, + /// Vendor specific/other Parameter type + CCI_OTHER_MUTABILITY +}; + +CCI_CLOSE_NAMESPACE_ + +#endif // CCI_CFG_CCI_MUTABLE_TYPES_H_INCLUDED_ diff --git a/third_party/cci-1.0.0/cci_cfg/cci_originator.cpp b/third_party/cci-1.0.0/cci_cfg/cci_originator.cpp new file mode 100644 index 000000000..c500aaf2a --- /dev/null +++ b/third_party/cci-1.0.0/cci_cfg/cci_originator.cpp @@ -0,0 +1,167 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + ****************************************************************************/ + +#include "cci_cfg/cci_originator.h" + +#include + +#include "cci_cfg/cci_config_macros.h" +#include "cci_cfg/cci_report_handler.h" + +CCI_OPEN_NAMESPACE_ + +cci_originator::cci_originator(const std::string& originator_name) + : m_originator_obj() + , m_originator_str() +{ + if (current_originator_object()) { + m_originator_obj = current_originator_object(); + if (originator_name.length() > 0) { + CCI_REPORT_ERROR("cci_originator/name_inside_hierarchy","Originators must not be named inside the SystemC hierarchy"); + } + } else { + if (originator_name.length() > 0) { + m_originator_str = new std::string(originator_name); + } else { + CCI_REPORT_ERROR("cci_originator/noname_outside_hierarchy","An originator name must be given outside the SystemC hierarchy"); + } + } + check_is_valid(); +} + +cci_originator::cci_originator(const char* originator_name) + : m_originator_obj() + , m_originator_str() +{ + if (current_originator_object()) { + m_originator_obj = current_originator_object(); + if (originator_name && *originator_name) { + CCI_REPORT_ERROR("cci_originator/name_inside_hierarchy","Originators must not be named inside the SystemC hierarchy"); + } + } else { + if (originator_name && *originator_name) { + m_originator_str = new std::string(originator_name); + } else { + CCI_REPORT_ERROR("cci_originator/noname_outside_hierarchy","An originator name must be given outside the SystemC hierarchy"); + } + } + check_is_valid(); +} + +cci_originator::cci_originator(const cci_originator& originator) + : m_originator_obj(originator.m_originator_obj) + , m_originator_str() +{ + if (originator.m_originator_str) + m_originator_str = new std::string(*originator.m_originator_str); +} + +#ifdef CCI_HAS_CXX_RVALUE_REFS +cci_originator::cci_originator(cci_originator&& originator) + : m_originator_obj(CCI_MOVE_(originator.m_originator_obj)) + , m_originator_str(CCI_MOVE_(originator.m_originator_str)) +{ + // invalidate incoming originator + originator.m_originator_obj = NULL; + originator.m_originator_str = NULL; +} +#endif // CCI_HAS_CXX_RVALUE_REFS + +const sc_core::sc_object *cci_originator::get_object() const +{ + return m_originator_obj; +} + +const char* cci_originator::name() const +{ + static const char* default_name = CCI_UNKNOWN_ORIGINATOR_STRING_; + if (m_originator_obj) { + return m_originator_obj->name(); + } else if(m_originator_str) { + return m_originator_str->c_str(); + } + return default_name; +} + +const char* cci_originator::string_name() const { + if(m_originator_str) + return m_originator_str->c_str(); + return NULL; +} + +void cci_originator::swap(cci_originator& that) { + std::swap(m_originator_obj, that.m_originator_obj); + std::swap(m_originator_str, that.m_originator_str); +} + +cci_originator &cci_originator::operator=(const cci_originator& originator) { + cci_originator copy(originator); + copy.swap(*this); + return *this; +} + +#ifdef CCI_HAS_CXX_RVALUE_REFS +cci_originator& cci_originator::operator=(cci_originator&& originator) +{ + // guard delete against self-move, invalidate incoming originator + const sc_core::sc_object* orig_obj = CCI_MOVE_(originator.m_originator_obj); + const std::string* orig_str = CCI_MOVE_(originator.m_originator_str); + originator.m_originator_obj = NULL; + originator.m_originator_str = NULL; + delete m_originator_str; + m_originator_obj = CCI_MOVE_(orig_obj); + m_originator_str = CCI_MOVE_(orig_str); + return *this; +} +#endif // CCI_HAS_CXX_RVALUE_REFS + +bool cci_originator::operator==( const cci_originator& originator ) const { + if(this->get_object() || originator.get_object()) { + return this->get_object() == originator.get_object(); + } + return !std::strcmp(name(), originator.name()); +} + +bool cci_originator::operator<(const cci_originator& originator) const { + return std::strcmp(name(), originator.name()) < 0; +} + +sc_core::sc_object *cci_originator::current_originator_object() { + return sc_core::sc_get_current_object(); +} + +void cci_originator::check_is_valid() const { + if (is_unknown()) { + CCI_REPORT_ERROR("cci_originator/check_is_valid", + "It is forbidden to build an originator without " + "information (no SystemC hierarchy or empty name)!"); + // may continue, if suppressed + } +} + +bool cci_originator::is_unknown() const +{ + return !m_originator_obj && !m_originator_str; +} + +cci_originator::~cci_originator() { + delete m_originator_str; +} + +CCI_CLOSE_NAMESPACE_ diff --git a/third_party/cci-1.0.0/cci_cfg/cci_originator.h b/third_party/cci-1.0.0/cci_cfg/cci_originator.h new file mode 100644 index 000000000..f84adbc40 --- /dev/null +++ b/third_party/cci-1.0.0/cci_cfg/cci_originator.h @@ -0,0 +1,159 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + ****************************************************************************/ + +#ifndef CCI_CFG_CCI_ORIGINATOR_H_INCLUDED_ +#define CCI_CFG_CCI_ORIGINATOR_H_INCLUDED_ + +#include "cci_core/cci_cmnhdr.h" + +CCI_OPEN_NAMESPACE_ + +class cci_broker_if; +class cci_param_if; + +/// Originator class which is used to track owners, handles and value providers +/// of parameters. +/** + * Static setter function is used by the parameter (proxy) to identify + * originator changing parameter's value. + * + * Static getter function is used by the parameter implementation to record + * originator's identity. + */ +class cci_originator +{ + friend class cci_broker_if; + friend class cci_param_if; + + struct unknown_tag {}; + + /// Internal constructor to create an unknown/invalid originator + explicit cci_originator(unknown_tag) + : m_originator_obj(), m_originator_str() {} + +public: + /// Default Constructor assumes current module is the originator + inline cci_originator() + : m_originator_obj(current_originator_object()), + m_originator_str(NULL) { + check_is_valid(); + } + + /// Constructor with an originator name + /** + * Constructor to associate explicitly a string name to an originator. + * The provided name will be used as the default name in case the + * originator is not build in the SystemC hierarchy. + * + * @param originator_name string name of the originator + */ + cci_originator(const std::string& originator_name); + + /// Constructor with an originator (char *) name + /** + * This form (in addition to @see cci_originator(const std::string&)) + * is necessary to avoid ambiguity between the sc_object, + * sc_module and std::string overloads for literal string constant + * arguments. + * + * @param originator_name string name of the originator + */ + explicit cci_originator(const char *originator_name); + + /// Copy constructor + cci_originator(const cci_originator& originator); + +#ifdef CCI_HAS_CXX_RVALUE_REFS + /// Move constructor + cci_originator(cci_originator&& originator); +#endif // CCI_HAS_CXX_RVALUE_REFS + + /// Destructor + ~cci_originator(); + + /// Returns a pointer to the current originator + /** + * Might return NULL if there is no current originator or the current + * originator is only given by name (use get_originator_str() instead). + * + * @return Originator object pointer or NULL + */ + const sc_core::sc_object* get_object() const; + + /// Returns the name of the current originator + /** + * Automatically uses the originator object name if the originator is + * given by object pointer. + * + * @return Originator name or NULL + */ + const char* name() const; + + /// Assignment operator overload + cci_originator& operator=( const cci_originator& originator ); + +#ifdef CCI_HAS_CXX_RVALUE_REFS + /// Assignment operator overload + cci_originator& operator=( cci_originator&& originator ); +#endif // CCI_HAS_CXX_RVALUE_REFS + + /// Compare operator overload + bool operator==( const cci_originator& originator ) const; + + /// Less operator overload + bool operator<(const cci_originator& originator) const; + + /// Swap originator object and string name with the provided originator. + /** + * Assists the assignment operator avoiding code duplication and creating + * an exception safe implementation. + * + * @param that Originator to swap + */ + void swap(cci_originator& that); + + /// Returns the validity of the current originator + /** + * @return true if the originator is unknown, otherwise false. + */ + bool is_unknown() const; + +protected: + /// Return the current originator object pointer + sc_core::sc_object* current_originator_object(); + + /// Check originator is valid (sc_object or not empty string name) + void check_is_valid() const; + + /// Returns the string name of the current originator + const char* string_name() const; + +private: + /// Pointer to the current originator object (priority compared to + /// name m_originator_str) + const sc_core::sc_object* m_originator_obj; + + /// Name of the current originator + const std::string* m_originator_str; +}; + +CCI_CLOSE_NAMESPACE_ + +#endif // CCI_CFG_CCI_ORIGINATOR_H_INCLUDED_ + diff --git a/third_party/cci-1.0.0/cci_cfg/cci_param_callbacks.h b/third_party/cci-1.0.0/cci_cfg/cci_param_callbacks.h new file mode 100644 index 000000000..ed3d73eed --- /dev/null +++ b/third_party/cci-1.0.0/cci_cfg/cci_param_callbacks.h @@ -0,0 +1,365 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + ****************************************************************************/ + +#ifndef CCI_CFG_CCI_PARAM_CALLBACKS_H_INCLUDED_ +#define CCI_CFG_CCI_PARAM_CALLBACKS_H_INCLUDED_ + +#include "cci_core/cci_callback.h" +#include "cci_core/cci_value.h" +#include "cci_core/cci_value_converter.h" + +CCI_OPEN_NAMESPACE_ + +template +struct cci_param_write_event; + +/// Forward declaration +class cci_param_untyped_handle; +class cci_originator; + +/// Payload for type-independent pre write and post write callbacks +template<> +struct cci_param_write_event +{ + typedef cci_param_write_event type; + typedef cci_value value_type; + + cci_param_write_event( const value_type& old_ + , const value_type& new_ + , const cci_originator& orig_ + , const cci_param_untyped_handle& handle_ ); + + /// Old parameter value + const value_type& old_value; + /// New parameter value + const value_type& new_value; + /// Originator of new value + const cci_originator& originator; + /// Parameter handle + const cci_param_untyped_handle& param_handle; +}; + +/// Payload for pre write and post write callbacks +template +struct cci_param_write_event +{ + typedef cci_param_write_event type; + typedef T value_type; + + cci_param_write_event( const value_type& old_ + , const value_type& new_ + , const cci_originator& orig_ + , const cci_param_untyped_handle& handle_ ); + /// Old parameter value + const value_type& old_value; + /// New parameter value + const value_type& new_value; + /// Originator of new value + const cci_originator& originator; + /// Parameter handle + const cci_param_untyped_handle& param_handle; + + /// Type-punned specialization + typedef const cci_param_write_event<>& generic_type; + + /// Conversion to a generic (type independent) event + struct generic_wrap + { + generic_type get() const { return wrapped_value; } + explicit generic_wrap(const type& payload); + + cci_value old_value; + cci_value new_value; + typename cci_impl::remove_reference::type wrapped_value; + }; // struct generic_wrap + +}; // cci_param_write_event + +template +struct cci_param_read_event; + +/// Payload for type-independent read callbacks +template<> +struct cci_param_read_event +{ + typedef cci_param_read_event type; + typedef cci_value value_type; + + cci_param_read_event( const value_type& val_ + , const cci_originator& orig_ + , const cci_param_untyped_handle& handle_ ); + + /// Parameter value + const value_type& value; + /// Originator of new value + const cci_originator& originator; + /// Parameter handle + const cci_param_untyped_handle& param_handle; +}; + +/// Payload for read callbacks +template +struct cci_param_read_event +{ + typedef cci_param_read_event type; + typedef T value_type; + + cci_param_read_event( const value_type& val_ + , const cci_originator& orig_ + , const cci_param_untyped_handle& handle_ ); + + /// Parameter value + const value_type& value; + /// Originator of new value + const cci_originator& originator; + /// Parameter handle + const cci_param_untyped_handle& param_handle; + + /// Type-punned specialization + typedef const cci_param_read_event<>& generic_type; + + /// Conversion to a generic (type independent) event + struct generic_wrap + { + generic_type get() const { return wrapped_value; } + explicit generic_wrap(const type& payload); + + cci_value value; + typename cci_impl::remove_reference::type wrapped_value; + }; // struct generic_wrap + +}; // cci_param_read_event + +/* ------------------------------------------------------------------------ */ + +#if CCI_CPLUSPLUS >= 201103L + +/// Parameter pre write callback +template +using cci_param_pre_write_callback + = cci_callback&, bool>; + +/// Parameter pre write callback handle +template +using cci_param_pre_write_callback_handle + = cci_callback_typed_handle&, bool>; + +/// Parameter post write callback +template +using cci_param_post_write_callback + = cci_callback&>; + +/// Parameter post write callback handle +template +using cci_param_post_write_callback_handle + = cci_callback_typed_handle&>; + +/// Parameter pre read callback +template +using cci_param_pre_read_callback + = cci_callback&>; + +/// Parameter pre read callback handle +template +using cci_param_pre_read_callback_handle + = cci_callback_typed_handle&>; + +/// Parameter post read callback +template +using cci_param_post_read_callback + = cci_callback&>; + +/// Parameter post read callback handle +template +using cci_param_post_read_callback_handle + = cci_callback_typed_handle&>; + +#else // CCI_CPLUSPLUS >= 201103L (no alias templates) + +/// Parameter pre write callback +template +struct cci_param_pre_write_callback + : cci_callback&, bool> {}; + +/// Parameter pre write callback handle +template +struct cci_param_pre_write_callback_handle + : cci_callback_typed_handle&, bool> {}; + +/// Parameter post write callback +template +struct cci_param_post_write_callback + : cci_callback& > {}; + +/// Parameter post write callback handle +template +struct cci_param_post_write_callback_handle + : cci_callback_typed_handle&> {}; + +/// Parameter pre read callback +template +struct cci_param_pre_read_callback + : cci_callback& > {}; + +/// Parameter pre read callback handle +template +struct cci_param_pre_read_callback_handle + : cci_callback_typed_handle&> {}; + +/// Parameter post read callback +template +struct cci_param_post_read_callback + : cci_callback& > {}; + +/// Parameter post read callback handle +template +struct cci_param_post_read_callback_handle + : cci_callback_typed_handle&> {}; + +#endif // CCI_CPLUSPLUS >= 201103L + +/// Untyped parameter write event +typedef cci_param_write_event<>::type + cci_param_write_event_untyped; + +/// Untyped parameter pre write callback +typedef cci_param_pre_write_callback<>::type + cci_param_pre_write_callback_untyped; + +/// Untyped parameter post write callback +typedef cci_param_post_write_callback<>::type + cci_param_post_write_callback_untyped; + +/// Untyped parameter read event +typedef cci_param_read_event<>::type + cci_param_read_event_untyped; + +/// Untyped parameter pre read callback +typedef cci_param_pre_read_callback<>::type + cci_param_pre_read_callback_untyped; + +/// Untyped parameter post read callback +typedef cci_param_post_read_callback<>::type + cci_param_post_read_callback_untyped; + +/* ------------------------------------------------------------------------ */ + +/// Callback API of CCI parameter implementations +struct cci_param_callback_if +{ + friend class cci_param_untyped_handle; + + virtual bool has_callbacks() const = 0; + +protected: + virtual cci_callback_untyped_handle + register_pre_write_callback( const cci_callback_untyped_handle& cb + , const cci_originator& orig ) = 0; + virtual bool + unregister_pre_write_callback( const cci_callback_untyped_handle& cb + , const cci_originator& orig ) = 0; + + virtual cci_callback_untyped_handle + register_post_write_callback( const cci_callback_untyped_handle& cb + , const cci_originator& orig ) = 0; + virtual bool + unregister_post_write_callback( const cci_callback_untyped_handle& cb + , const cci_originator& orig ) = 0; + + virtual cci_callback_untyped_handle + register_pre_read_callback( const cci_callback_untyped_handle& cb + , const cci_originator& orig ) = 0; + virtual bool + unregister_pre_read_callback( const cci_callback_untyped_handle& cb + , const cci_originator& orig ) = 0; + + virtual cci_callback_untyped_handle + register_post_read_callback( const cci_callback_untyped_handle& cb + , const cci_originator& orig ) = 0; + virtual bool + unregister_post_read_callback( const cci_callback_untyped_handle& cb + , const cci_originator& orig ) = 0; + + virtual bool unregister_all_callbacks(const cci_originator& orig) = 0; +}; + +/* ------------------------------------------------------------------------ */ + +inline +cci_param_write_event:: + cci_param_write_event( const value_type& old_ + , const value_type& new_ + , const cci_originator& orig_ + , const cci_param_untyped_handle& handle_ ) + : old_value(old_) + , new_value(new_) + , originator(orig_) + , param_handle(handle_) +{} + +template +cci_param_write_event:: + cci_param_write_event( const value_type& old_ + , const value_type& new_ + , const cci_originator& orig_ + , const cci_param_untyped_handle& handle_ ) + : old_value(old_) + , new_value(new_) + , originator(orig_) + , param_handle(handle_) +{} + +template +cci_param_write_event:: + generic_wrap::generic_wrap( const type& payload ) + : old_value( payload.old_value ) + , new_value( payload.new_value ) + , wrapped_value(old_value, new_value, payload.originator, payload.param_handle) +{} + +inline +cci_param_read_event:: + cci_param_read_event( const value_type& val_ + , const cci_originator& orig_ + , const cci_param_untyped_handle& handle_ ) + : value(val_) + , originator(orig_) + , param_handle(handle_) +{} + +template +cci_param_read_event:: + cci_param_read_event( const value_type& val_ + , const cci_originator& orig_ + , const cci_param_untyped_handle& handle_ ) + : value(val_) + , originator(orig_) + , param_handle(handle_) +{} + +template +cci_param_read_event:: + generic_wrap::generic_wrap( const type& payload ) + : value( payload.value ) + , wrapped_value(value, payload.originator, payload.param_handle) +{} + +CCI_CLOSE_NAMESPACE_ + +#endif // CCI_CFG_CCI_PARAM_CALLBACKS_H_INCLUDED_ diff --git a/third_party/cci-1.0.0/cci_cfg/cci_param_if.cpp b/third_party/cci-1.0.0/cci_cfg/cci_param_if.cpp new file mode 100644 index 000000000..71e039181 --- /dev/null +++ b/third_party/cci-1.0.0/cci_cfg/cci_param_if.cpp @@ -0,0 +1,71 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + ****************************************************************************/ +/** + * @file cci_param_if.cpp + * @author Philipp A Hartmann, Intel + */ + +#include "cci_cfg/cci_param_if.h" + +#include "cci_cfg/cci_broker_if.h" +#include "cci_cfg/cci_param_untyped_handle.h" +#include "cci_cfg/cci_report_handler.h" + +CCI_OPEN_NAMESPACE_ + +void cci_param_if::init( cci_broker_handle broker_handle ) +{ + cci_broker_if& broker = broker_handle.ref(); + const std::string& nm = name(); + if( broker.has_preset_value(nm) ) { + preset_cci_value( broker.get_preset_cci_value(nm) + , broker.get_value_origin(nm) ); + } + broker.add_param(this); +} + +void cci_param_if::destroy( cci_broker_handle broker_handle ) +{ + broker_handle.ref().remove_param( this ); + invalidate_all_param_handles(); +} + +void cci_param_if::preset_cci_value( const cci_value& value + , const cci_originator& originator ) +{ + // forwards to a regular value update by default + set_cci_value(value, originator); +} + +void cci_param_if::invalidate_all_param_handles() +{ + CCI_REPORT_FATAL( "DESTROY_PARAM" + , "Failed to invalidate parameter handles! " + "(pure virtual function called)" ); +} + +cci_param_untyped_handle +cci_param_if::create_param_handle(const cci_originator& originator) const +{ + // need to keep this function const, as it is used inside the callback handling, + // still need to create the handle from a non-const pointer + return cci_param_untyped_handle(*const_cast(this), originator); +} + +CCI_CLOSE_NAMESPACE_ diff --git a/third_party/cci-1.0.0/cci_cfg/cci_param_if.h b/third_party/cci-1.0.0/cci_cfg/cci_param_if.h new file mode 100644 index 000000000..2eab6cdb3 --- /dev/null +++ b/third_party/cci-1.0.0/cci_cfg/cci_param_if.h @@ -0,0 +1,368 @@ + +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + ****************************************************************************/ + +#ifndef CCI_CFG_CCI_PARAM_IF_H_INCLUDED_ +#define CCI_CFG_CCI_PARAM_IF_H_INCLUDED_ + +#include + +#include "cci_cfg/cci_broker_handle.h" +#include "cci_cfg/cci_mutable_types.h" +#include "cci_cfg/cci_param_callbacks.h" + +/** + * @author Enrico Galli, Intel + * @author Philipp A. Hartmann, Intel + */ + +CCI_OPEN_NAMESPACE_ + +class cci_param_untyped_handle; +class cci_originator; + +/** + * @brief CCI configuration parameter interface + * + * This class provides the core interfaces between parameter implementations + * and the broker(s). All interactions between the broker and the parameters + * are routed through this interface, most commonly by using explicit + * parameter handles, which include an additional cci_originator for access + * tracking. + * + * The functions of this interface can be grouped as follows: + * @li Basic information (name, documentation, metadata, type information) + * @li Generic untyped access via cci_value + * @li Generic callback handling + * @li Access control (aka locking) + * + * The type-punned access functions are only needed for parameter + * implementations (@c *_raw_value) and are marked @c private. + * + * @see cci_param_untyped_handle, cci_param_typed_handle + */ +class cci_param_if : public cci_param_callback_if +{ + friend class cci_param_untyped_handle; +public: + + /// @name (Untyped) parameter value access + //@{ + + /** + * @brief Set the parameter value from a given cci_value + * @param val new value passed to the parameter + * @exception cci_report_handler::cci_value_failure + * in case the conversion from the supplied cci_value to + * the parameter's underlying data type fails. + * @exception cci_report_handler::set_param_failed + * in case of mutability, locked state or other failures + * + * This overload uses the parameter's own originator for access tracking. + * @see get_originator() + */ + void set_cci_value(const cci_value& val) + { set_cci_value(val, NULL); } + + /** + * @brief Set the parameter value from a given cci_value + * @param val new value passed to the parameter + * @param pwd the password, with which the parameter is currently locked + * (or NULL, if the parameter is not locked) + * @exception cci_report_handler::cci_value_failure + * in case the conversion from the supplied cci_value to + * the parameter's underlying data type fails. + * @exception cci_report_handler::set_param_failed + * in case of mutability, locked state or other failures + * + * This overload uses the parameter's own originator for access tracking. + * @see get_originator() + */ + void set_cci_value(const cci_value& val, const void* pwd) + { set_cci_value(val, pwd, get_originator()); } + + /** + * @brief Set the parameter value from a given cci_value + * @param val new value passed to the parameter + * @param originator the accessing originator + * @exception cci_report_handler::cci_value_failure + * in case the conversion from the supplied cci_value to + * the parameter's underlying data type fails. + * @exception cci_report_handler::set_param_failed + * in case of mutability, locked state or other failures + */ + void set_cci_value(const cci_value &val, const cci_originator &originator) + { set_cci_value(val, NULL, originator); } + + /** + * @brief Set the parameter value from a given cci_value + * @param val new value passed to the parameter + * @param pwd the password, with which the parameter is currently locked + * (or NULL, if the parameter is not locked) + * @param originator the accessing originator + * @exception cci_report_handler::cci_value_failure + * in case the conversion from the supplied cci_value to + * the parameter's underlying data type fails. + * @exception cci_report_handler::set_param_failed + * in case of mutability, locked state or other failures + * @note This is the only overload that needs to be provided + * by parameter implementations. + * + * @see set_cci_value(const cci_value&), + * set_cci_value(const cci_value&, const void*), + * set_cci_value(const cci_value&, const cci_originator&) + */ + virtual void set_cci_value(const cci_value &val, const void* pwd, + const cci_originator &originator) = 0; + + /** + * @brief Get the parameter's value converted to cci_value + * @return The current value of the parameter's underlying type + * converted to cci_value + * @exception cci_report_handler::cci_value_failure + * in case the conversion to a cci_value fails + * + * This overload uses the parameter's own originator for access tracking. + * @see get_originator() + */ + cci_value get_cci_value() const + { return get_cci_value(get_originator()); } + + /** + * @brief Get the parameter's value converted to cci_value. + * @param originator the accessing originator + * @return The current value of the parameter's underlying type + * converted to cci_value + * @exception cci_report_handler::cci_value_failure + * in case the conversion to a cci_value fails + * @see get_cci_value() + */ + virtual cci_value get_cci_value(const cci_originator& originator) const = 0; + + /** + * @brief Get the parameter's default value converted to cci_value + * @return The value of the parameter's underlying type + * as given to the constructor, converted to cci_value + * @exception cci_report_handler::cci_value_failure + * in case the conversion to a cci_value fails + */ + virtual cci_value get_default_cci_value() const = 0; + //@} + + + ///@name Description and metadata + //@{ + + /// @copydoc cci_param_untyped::get_description + virtual std::string get_description() const = 0; + + /// @copydoc cci_param_untyped::set_description + virtual void set_description(const std::string &desc) = 0; + + /// @copydoc cci_param_untyped::add_metadata + virtual void add_metadata(const std::string &name, const cci_value &value, + const std::string &desc = "") = 0; + + /// @copydoc cci_param_untyped::get_metadata + virtual cci_value_map get_metadata() const = 0; + ///@} + + ///@name Parameter Value Status + //@{ + + /// @copydoc cci_param_untyped::is_default_value + virtual bool is_default_value() const = 0; + + /// @copydoc cci_param_untyped::is_preset_value + virtual bool is_preset_value() const = 0; + + ///@} + + ///@name Originator queries + //@{ + + /// @copydoc cci_param_untyped::get_originator + virtual cci_originator get_originator() const = 0; + + /// @copydoc cci_param_untyped::get_value_origin + virtual cci_originator get_value_origin() const = 0; + + //@} + + ///@name Write-access control + //@{ + + /// @copydoc cci_param_untyped::lock + virtual bool lock(const void *pwd = NULL) = 0; + + /// @copydoc cci_param_untyped::unlock + virtual bool unlock(const void *pwd = NULL) = 0; + + /// @copydoc cci_param_untyped::is_locked + virtual bool is_locked() const = 0; + + //@} + + ///@name Query parameter type and name + //@{ + + /// @copydoc cci_param_untyped::name + virtual const char* name() const = 0; + + /// @copydoc cci_param_typed::get_mutable_type + virtual cci_param_mutable_type get_mutable_type() const = 0; + + /// @copydoc cci_param_typed::get_type_info + virtual const std::type_info& get_type_info() const = 0; + + /// @copydoc cci_param_typed::get_data_category + virtual cci_param_data_category get_data_category() const = 0; + + //@} + + /** + * @brief Convenience function to create a new parameter handle + * @param originator Originator for access tracking + * @return parameter handle for the given (or current) originator + * @note The default argument can only be reliably used from within the + * SystemC hierarchy during elaboration. + * @see cci_originator + */ + cci_param_untyped_handle + create_param_handle(const cci_originator& originator = cci_originator()) const; + + /** + * @brief Convenience function to restore parameter's initial value + * @return true if successful; false if unsuccessful due to parameter being locked + * @note Upon success, the value originator will be updated to reflect the + * origin of the initial value. + */ + virtual bool reset() = 0; + +protected: + /// helper function, returning an unknown/invalid originator + cci_originator unknown_originator() const + { return cci_originator( cci_originator::unknown_tag() ); } + + /** Extract typed value from a parameter. + * @param rhs parameter to read value from + * @pre rhs.get_type_info() == typeid(T) + * @return rhs.get_raw_value() - converted back to reference of type T + */ + template + const T& get_typed_value(const cci_param_if& rhs) const + { return *static_cast( rhs.get_raw_value(get_originator()) ); } + + ///@name Initialization and destruction of parameter object + //@{ + /** + * Initialize parameter object. + * @param broker Broker to register this parameter with. + * + * This function shall be called from the constructor of the final + * parameter object where @b all virtual functions are available. + * + * This function will register the parameter with the supplied broker + * and will afterwards apply the any preset value available from the + * broker. + * + * @see preset_cci_value, cci_broker_handle::add_param + */ + void init(cci_broker_handle broker); + + /** + * Destroy parameter object. + * @param broker Broker to unregister this parameter from. + * + * This function shall be called from the destructor of the final + * parameter object where @b all virtual functions are still available. + * + * This function will unregister the parameter from the supplied broker + * and will afterwards invalidate all parameter handles. + * + * @see invalidate_all_param_handles, cci_broker_handle::remove_param + */ + void destroy(cci_broker_handle broker); + + /// Default Constructor + cci_param_if() {} + + /// Destruction from base pointer is disallowed + virtual ~cci_param_if() {} + +private: + /** + * Initialize value of parameter from broker preset, if present. + * @param preset Preset value supplied by broker + * @param originator Originator of preset value + * + * The default implementation if simply calls @ref set_cci_value, + * parameter implementations may choose to customize the behavior + * when applying a preset value. + * + * Called from @ref init. + */ + virtual void + preset_cci_value(const cci_value& preset, const cci_originator& originator); + + /** + * Invalidate all parameter handles. + * + * This function shall call @ref cci_param_untyped_handle::invalidate + * on all currently registered handles of this parameter. + * + * Called from @ref destroy. + */ + virtual void + invalidate_all_param_handles() = 0; + //@} + + ///@name Type-punned value operations + //@{ + + /// @copydoc cci_param_typed::set_raw_value(const void*, const void*, const cci_originator&) + virtual void set_raw_value(const void *vp, const void *pwd, + const cci_originator &originator) = 0; + + /// @copydoc cci_param_typed::get_raw_value + virtual const void *get_raw_value(const cci_originator &originator) const = 0; + + /// @copydoc cci_param_typed::get_raw_default_value + virtual const void *get_raw_default_value() const = 0; + + /// @copydoc cci_param_untyped::add_param_handle + virtual void add_param_handle(cci_param_untyped_handle* param_handle) = 0; + + /// @copydoc cci_param_untyped::remove_param_handle + virtual void remove_param_handle(cci_param_untyped_handle* param_handle) = 0; + + //@} + + // Disabled + cci_param_if(const cci_param_if&); + cci_param_if& operator=(const cci_param_if&); +#ifdef CCI_HAS_CXX_RVALUE_REFS + cci_param_if(cci_param_if&&); + cci_param_if& operator=(cci_param_if&&); +#endif + +}; // class cci_param_if + +CCI_CLOSE_NAMESPACE_ +#endif // CCI_CFG_CCI_PARAM_IF_H_INCLUDED_ diff --git a/third_party/cci-1.0.0/cci_cfg/cci_param_typed.h b/third_party/cci-1.0.0/cci_cfg/cci_param_typed.h new file mode 100644 index 000000000..de7f04c42 --- /dev/null +++ b/third_party/cci-1.0.0/cci_cfg/cci_param_typed.h @@ -0,0 +1,986 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + ****************************************************************************/ + +#ifndef CCI_CFG_CCI_PARAM_TYPED_H_INCLUDED_ +#define CCI_CFG_CCI_PARAM_TYPED_H_INCLUDED_ + +#include //std::stringstream +#include "cci_cfg/cci_broker_manager.h" +#include "cci_cfg/cci_param_untyped.h" +#include "cci_cfg/cci_param_untyped_handle.h" +#include "cci_cfg/cci_report_handler.h" + +/** + * @author Enrico Galli, Intel + * @author Guillaume Delbergue, GreenSocs / Ericsson + */ +CCI_OPEN_NAMESPACE_ + +// Forward declaration +template +class cci_param_typed_handle; + +///@cond CCI_HIDDEN_FROM_DOXYGEN +namespace cci_impl { +/// implementation defined helper to set/reset a boolean flag +struct scoped_true { + explicit scoped_true(bool& ref) : ref_(ref) { ref_ = true; } + ~scoped_true() { ref_ = false; } +private: + bool& ref_; +}; // class scoped_true +} // namespace cci_impl +///@endcond + +/// Parameter class, internally forwarding calls to the implementation +/** + * The implementation is in file cci_param_typed.hpp, which has to be included + * in the headers as well because the class is a template class. + * + * Documentation for the undocumented functions can be found in + * cci_param_if + */ +template +class cci_param_typed : public cci_param_untyped +{ +public: + ///@name Typed parameter value access + //@{ + + /// The parameter's value type. + typedef T value_type; + + ///Assigns parameter a new value from another parameter + /** + * @param rhs New value to assign + * @return reference to this object + */ + cci_param_typed& operator= (const cci_param_typed & rhs); + + ///Assigns parameter a new value + /** + * @param rhs New value to assign + * @return reference to this object + */ + cci_param_typed& operator= (const value_type & rhs); + + ///Conversion operator to be able use cci_param_typed as a regular object + operator const value_type& () const; + + ///Sets the stored value to a new value + /** + * @param value new value to assign + */ + void set_value(const value_type& value); + ///Sets the stored value to a new value + /** + * @param value new value to assign + * @param pwd Password needed to unlock the param, ideally any pointer + * address known only by the locking entity, default = NULL + */ + void set_value(const value_type & value, const void * pwd); + + ///Get the value passed in via constructor + const value_type & get_default_value() const; + + /// Get the current value + const value_type& get_value() const; + + /// Get the current value (for an explicit originator) + const value_type& get_value(const cci_originator& originator) const; + + //@} + + ///@name Type-punned value operations + ///@{ + + /// Returns a basic type this parameter can be converted to or from + /// (which is not necessarily the actual parameter type). + /** + * @return Type + */ + cci_param_data_category get_data_category() const; + + /// Returns the type information of the parameter + /** + * @return Type information + */ + const std::type_info& get_type_info() const; + + /// Get the parameter's mutable type + /** + * @return Parameter mutable type + */ + cci_param_mutable_type get_mutable_type() const; + + ///@} + + ///@name (Untyped) parameter value access + ///@{ + + using cci_param_if::set_cci_value; + /// @copydoc cci_param_if::set_cci_value(const cci_value&, const void*, const cci_originator&) + void set_cci_value(const cci_value& val, const void *pwd, const cci_originator& originator); + + using cci_param_if::get_cci_value; + /// @copydoc cci_param_if::get_cci_value(const cci_originator&) const + cci_value get_cci_value(const cci_originator& originator) const; + + /// @copydoc cci_param_if::get_default_cci_value() const + cci_value get_default_cci_value() const; + + ///@} + + ///@name Parameter Value Status + //@{ + + /// @copydoc cci_param_untyped::is_default_value() + bool is_default_value() const; + + /// @copydoc cci_param_untyped::is_preset_value() + bool is_preset_value() const; + + ///@} + + /// @copydoc cci_param_untyped::lock + bool lock(const void* pwd = NULL); + + /// @name Post write callback handling + /// @{ + + // Untyped callbacks + + /// @copydoc cci_param_untyped::register_post_write_callback(const cci_param_post_write_callback_untyped, cci_untyped_tag) + cci_callback_untyped_handle register_post_write_callback( + const cci_param_post_write_callback_untyped &cb, + cci_untyped_tag); + + /// @copydoc cci_param_untyped::register_post_write_callback(cci_param_post_write_callback_untyped::signature, C*, cci_untyped_tag) + template + cci_callback_untyped_handle register_post_write_callback( + cci_param_post_write_callback_untyped::signature (C::*cb), C* obj, + cci_untyped_tag); + + // Typed callbacks + + /// Typed write callback type + typedef typename cci_param_post_write_callback::type + cci_param_post_write_callback_typed; + + /// Register a typed write callback. + /** + * @param cb Typed write callback + * @param cci_typed_tag Typed tag to avoid compiler ambiguity + * + * @return Untyped callback handle + */ + cci_callback_untyped_handle register_post_write_callback( + const cci_param_post_write_callback_typed &cb, + cci_typed_tag = cci_typed_tag()); + + /// Register a typed write callback with a method as callback + /** + * @param cb Typed write callback method + * @param obj Associated object instance pointer + * @param cci_typed_tag Typed tag to avoid compiler ambiguity + * + * @return Untyped callback handle + */ + template + cci_callback_untyped_handle register_post_write_callback( + typename cci_param_post_write_callback_typed::signature (C::*cb), + C* obj, cci_typed_tag = cci_typed_tag()); + + /// @} + + /// @name Pre write callback handling + /// @{ + + // Untyped callbacks + + /// @copydoc cci_param_untyped::register_pre_write_callback(const cci_param_pre_write_callback_untyped, cci_untyped_tag) + cci_callback_untyped_handle register_pre_write_callback( + const cci_param_pre_write_callback_untyped &cb, + cci_untyped_tag); + + /// @copydoc cci_param_untyped::register_pre_write_callback(cci_param_pre_write_callback_untyped::signature, C*, cci_untyped_tag) + template + cci_callback_untyped_handle register_pre_write_callback( + cci_param_pre_write_callback_untyped::signature (C::*cb), + C* obj, cci_untyped_tag); + + // Typed callbacks + + /// Typed pre write callback type + typedef typename cci_param_pre_write_callback::type + cci_param_pre_write_callback_typed; + + /// Register a typed pre write callback. + /** + * @param cb Typed pre write callback + * @param cci_typed_tag Typed tag to avoid compiler ambiguity + * + * @return Untyped callback handle + */ + cci_callback_untyped_handle register_pre_write_callback( + const cci_param_pre_write_callback_typed &cb, + cci_typed_tag = cci_typed_tag()); + + /// Register a typed pre write callback with a method as callback + /** + * @param cb Typed pre write callback method + * @param obj Associated object instance pointer + * @param cci_typed_tag Typed tag to avoid compiler ambiguity + * + * @return Untyped callback handle + */ + template + cci_callback_untyped_handle register_pre_write_callback( + typename cci_param_pre_write_callback_typed::signature + (C::*cb), C* obj, + cci_typed_tag = cci_typed_tag()); + + /// @} + + /// @name Pre read callback handling + /// @{ + + // Untyped callbacks + + /// @copydoc cci_param_untyped::register_pre_read_callback(const cci_param_pre_read_callback_untyped, cci_untyped_tag) + cci_callback_untyped_handle register_pre_read_callback( + const cci_param_pre_read_callback_untyped &cb, + cci_untyped_tag); + + /// @copydoc cci_param_untyped::register_pre_read_callback(cci_param_pre_read_callback_untyped::signature, C*, cci_untyped_tag) + template + cci_callback_untyped_handle register_pre_read_callback( + cci_param_pre_read_callback_untyped::signature (C::*cb), C* obj, + cci_untyped_tag); + + // Typed callbacks + + /// Typed read callback type + typedef typename cci_param_pre_read_callback::type + cci_param_pre_read_callback_typed; + + /// Register a typed read callback. + /** + * @param cb Typed read callback + * @param cci_typed_tag Typed tag to avoid compiler ambiguity + * + * @return Untyped callback handle + */ + cci_callback_untyped_handle register_pre_read_callback( + const cci_param_pre_read_callback_typed &cb, + cci_typed_tag = cci_typed_tag()); + + /// Register a typed read callback with a method as callback + /** + * @param cb Typed read callback method + * @param obj Associated object instance pointer + * @param cci_typed_tag Typed tag to avoid compiler ambiguity + * + * @return Untyped callback handle + */ + template + cci_callback_untyped_handle register_pre_read_callback( + typename cci_param_pre_read_callback_typed::signature (C::*cb), + C* obj, cci_typed_tag = cci_typed_tag()); + + /// @} + + /// @name Post read callback handling + /// @{ + + // Untyped callbacks + + /// @copydoc cci_param_untyped::register_post_read_callback(const cci_param_post_read_callback_untyped, cci_untyped_tag) + cci_callback_untyped_handle register_post_read_callback( + const cci_param_post_read_callback_untyped &cb, + cci_untyped_tag); + + /// @copydoc cci_param_untyped::register_post_read_callback(cci_param_post_read_callback_untyped::signature, C*, cci_untyped_tag) + template + cci_callback_untyped_handle register_post_read_callback( + cci_param_post_read_callback_untyped::signature (C::*cb), C* obj, + cci_untyped_tag); + + // Typed callbacks + + /// Typed read callback type + typedef typename cci_param_post_read_callback::type + cci_param_post_read_callback_typed; + + /// Register a typed post read callback. + /** + * @param cb Typed post read callback + * @param cci_typed_tag Typed tag to avoid compiler ambiguity + * + * @return Untyped callback handle + */ + cci_callback_untyped_handle register_post_read_callback( + const cci_param_post_read_callback_typed &cb, + cci_typed_tag = cci_typed_tag()); + + /// Register a typed post read callback with a method as callback + /** + * @param cb Typed post read callback method + * @param obj Associated object instance pointer + * @param cci_typed_tag Typed tag to avoid compiler ambiguity + * + * @return Untyped callback handle + */ + template + cci_callback_untyped_handle register_post_read_callback( + typename cci_param_post_read_callback_typed::signature (C::*cb), + C* obj, cci_typed_tag = cci_typed_tag()); + + /// @} + + /** @name Constructors */ + //@{ + /** + * Constructor with (local/hierarchical) name, default value, + * description and originator. + * + * @param name Name of the parameter + * @param default_value Default value of the parameter (Typed value) + * @param desc Description of the parameter + * @param name_type Either the name should be absolute or relative + * @param originator Originator of the parameter + */ + cci_param_typed(const std::string& name, const value_type& default_value, + const std::string& desc = "", + cci_name_type name_type = CCI_RELATIVE_NAME, + const cci_originator& originator = cci_originator()); + + /** + * Constructor with (local/hierarchical) name, default value, + * description and originator. + * + * @param name Name of the parameter + * @param default_value Default value of the parameter (CCI value) + * @param desc Description of the parameter + * @param name_type Either the name should be absolute or relative + * @param originator Originator of the parameter + */ + cci_param_typed(const std::string& name, const cci_value& default_value, + const std::string& desc = "", + cci_name_type name_type = CCI_RELATIVE_NAME, + const cci_originator& originator = cci_originator()); + + /** + * Constructor with (local/hierarchical) name, default value, + * private broker, description, name type and originator. + * + * @param name Name of the parameter + * @param default_value Default value of the parameter (Typed value) + * @param private_broker Associated private broker + * @param desc Description of the parameter + * @param name_type Either the name should be absolute or relative + * @param originator Originator of the parameter + */ + cci_param_typed(const std::string& name, const value_type& default_value, + cci_broker_handle private_broker, + const std::string& desc = "", + cci_name_type name_type = CCI_RELATIVE_NAME, + const cci_originator& originator = cci_originator()); + + /** + * Constructor with (local/hierarchical) name, default value, + * private broker, description, name type and originator. + * + * @param name Name of the parameter + * @param default_value Default value of the parameter (CCI value) + * @param private_broker Associated private broker + * @param desc Description of the parameter + * @param name_type Either the name should be absolute or relative + * @param originator Originator of the parameter + */ + cci_param_typed(const std::string& name, const cci_value& default_value, + cci_broker_handle private_broker, + const std::string& desc = "", + cci_name_type name_type = CCI_RELATIVE_NAME, + const cci_originator& originator = cci_originator()); + //@} + + ///@copydoc cci_param_if::reset + virtual bool reset(); + + ~cci_param_typed() + { destroy(m_broker_handle); } + +protected: + /// Value + value_type m_value; + + /// Default value + value_type m_default_value; + +private: + ///@copydoc cci_param_if::preset_cci_value + virtual void preset_cci_value(const cci_value&, const cci_originator&); + + /// @copydoc cci_param_if::set_raw_value + virtual void set_raw_value(const void *vp, const void *pwd, + const cci_originator &originator); + + /// @copydoc cci_param_if::get_raw_value + virtual const void *get_raw_value(const cci_originator &originator) const; + + /// @copydoc cci_param_if::get_raw_default_value + virtual const void *get_raw_default_value() const; + + /// Pre write callback + bool + pre_write_callback(value_type value, + const cci_originator &originator) const + { + // Already locked, skip nested invocation + if (m_pre_write_callbacks.oncall) + return false; + + // Lock the tag to prevent nested callback + cci_impl::scoped_true oncall( m_pre_write_callbacks.oncall ); + + bool result = true; + // Validate write callbacks + for (unsigned i = 0; i < m_pre_write_callbacks.vec.size(); ++i) { + typename cci_param_pre_write_callback_handle::type + typed_pre_write_cb( + m_pre_write_callbacks.vec[i].callback); + + // Prepare parameter handle for callback event + cci_param_untyped_handle param_handle = + create_param_handle(m_pre_write_callbacks.vec[i].originator); + + // Write callback payload + const cci_param_write_event + ev(m_value, value, originator, param_handle); + + if (!typed_pre_write_cb.invoke(ev)) { + // Write denied + cci_report_handler::set_param_failed( + "Value rejected by callback.", __FILE__, __LINE__); + result = false; + } + } + + return result; + } + + /// Post write callback + void post_write_callback(const value_type& old_value, + const value_type& new_value, + const cci_originator &originator) const + { + // Already locked, skip nested invocation + if (m_post_write_callbacks.oncall) + return; + + // Lock the tag to prevent nested callback + cci_impl::scoped_true oncall( m_post_write_callbacks.oncall ); + + // Write callbacks + for (unsigned i = 0; i < m_post_write_callbacks.vec.size(); ++i) { + typename cci_param_post_write_callback_handle::type + typed_post_write_cb(m_post_write_callbacks.vec[i].callback); + if (typed_post_write_cb.valid()) { + + // Prepare parameter handle for callback event + cci_param_untyped_handle param_handle = create_param_handle( + m_post_write_callbacks.vec[i].originator); + + // Write callback payload + const cci_param_write_event + ev(old_value, new_value, originator, param_handle); + + typed_post_write_cb.invoke(ev); + } + } + } + + /// Pre read callback + void pre_read_callback(const value_type& value, + const cci_originator &originator) const + { + // Already locked, skip nested invocation + if(m_pre_read_callbacks.oncall) + return; + + // Lock the tag to prevent nested callback + cci_impl::scoped_true oncall( m_pre_read_callbacks.oncall ); + + // Read callbacks + for (unsigned i = 0; i < m_pre_read_callbacks.vec.size(); ++i) { + typename cci_param_pre_read_callback_handle::type + typed_pre_read_cb(m_pre_read_callbacks.vec[i].callback); + if (typed_pre_read_cb.valid()) { + + // Prepare parameter handle for callback event + cci_param_untyped_handle param_handle = create_param_handle( + m_pre_read_callbacks.vec[i].originator); + + // Read callback payload + const cci_param_read_event + ev(value, originator, param_handle); + + typed_pre_read_cb.invoke(ev); + } + } + } + + /// Post read callback + void post_read_callback(const value_type& value, + const cci_originator &originator) const + { + // Already locked, skip nested invocation + if(m_post_read_callbacks.oncall) + return; + + // Lock the tag to prevent nested callback + cci_impl::scoped_true oncall( m_post_read_callbacks.oncall ); + + // Read callbacks + for (unsigned i = 0; i < m_post_read_callbacks.vec.size(); ++i) { + typename cci_param_post_read_callback_handle::type + typed_pre_read_cb(m_post_read_callbacks.vec[i].callback); + if (typed_pre_read_cb.valid()) { + + // Prepare parameter handle for callback event + cci_param_untyped_handle param_handle = create_param_handle( + m_post_read_callbacks.vec[i].originator); + + // Read callback payload + const cci_param_read_event + ev(value, originator, param_handle); + + typed_pre_read_cb.invoke(ev); + } + } + } + +cci_broker_handle find_broker_convenience(const cci_originator &originator) + { + if (!sc_core::sc_get_current_object()) { + return cci_get_global_broker(originator); + } else { + return cci_get_broker(); + } + } + +}; + +template +cci_param_typed& +cci_param_typed::operator=(const cci_param_typed& rhs) +{ + set_value(rhs.get_value()); + return *this; +} + +template +cci_param_typed& +cci_param_typed::operator=(const T& rhs) +{ + set_value(rhs); + return *this; +} + +template +cci_param_typed::operator const T&() const +{ + return get_value(); +} + +template +const T& cci_param_typed::get_value() const +{ + if (cci_param_untyped::fast_read) { + // this is totally safe, there are no callbacks, and the originator is only + // used by the callbacks + return m_value; + } + return get_value(get_originator()); +} + +template +const T& cci_param_typed::get_value(const cci_originator& originator) const +{ + return *static_cast(get_raw_value(originator)); +} + +template +void cci_param_typed::set_raw_value(const void* value, + const void *pwd, + const cci_originator& originator) +{ + const value_type& new_value = *static_cast(value); + + if (!this->set_cci_value_allowed(TM)) + return; + + if(!pwd) { + if (cci_param_untyped::is_locked()) { + cci_report_handler::set_param_failed("Parameter locked.", __FILE__, __LINE__); + return; + } + } else { + if (pwd != m_lock_pwd) { + cci_report_handler::set_param_failed("Wrong key.", __FILE__, __LINE__); + return; + } + } + + if (!pre_write_callback(new_value, originator)) + return; + + // Actual write + value_type old_value = m_value; + m_value = new_value; + + // Update value's origin + m_value_origin = originator; + + // Write callback(s) + post_write_callback(old_value, new_value, originator); + + cci_param_untyped::fast_write = + TM == CCI_MUTABLE_PARAM && + !cci_param_untyped::is_locked() && + m_pre_write_callbacks.vec.size()==0 && + m_post_write_callbacks.vec.size()==0 && + originator==m_originator; +} + +template +void cci_param_typed::set_value(const T& value) +{ + // fast_write tracks whether, we have no callbacks, no lock, we're allowed to + // do the write (it's not immutable) AND the originator (last time) was, + // indeed, the original m_originator. The _only_ way of getting here is from + // the owner of the param, hence the originator must be m_originator. + if (cci_param_untyped::fast_write) { + m_value = value; + } else { + set_raw_value(&value, NULL, get_originator()); + } +} + +template +void cci_param_typed::set_value(const T& value, const void *pwd) +{ + set_raw_value(&value, pwd, get_originator()); +} + +template +const void* cci_param_typed::get_raw_value( + const cci_originator &originator) const +{ + pre_read_callback(m_value, originator); + const void *v = &m_value; + post_read_callback(m_value, originator); + + const_cast* >(this)->cci_param_untyped::fast_read = + m_pre_read_callbacks.vec.size()==0 && + m_post_read_callbacks.vec.size()==0; + + return v; +} + +template +cci_param_data_category cci_param_typed::get_data_category() const +{ + switch (get_cci_value().category()) + { + case CCI_BOOL_VALUE: + return CCI_BOOL_PARAM; + case CCI_INTEGRAL_VALUE: + return CCI_INTEGRAL_PARAM; + case CCI_REAL_VALUE: + return CCI_REAL_PARAM; + case CCI_STRING_VALUE: + return CCI_STRING_PARAM; + case CCI_LIST_VALUE: + return CCI_LIST_PARAM; + case CCI_NULL_VALUE: + case CCI_OTHER_VALUE: + default: + return CCI_OTHER_PARAM; + } +} + +template +const std::type_info& cci_param_typed::get_type_info() const +{ + return typeid(value_type); +} + +template +const void* cci_param_typed::get_raw_default_value() const { + return &get_default_value(); +} + +template +const typename cci_param_typed::value_type& +cci_param_typed::get_default_value() const +{ + return this->m_default_value; +} + +template +cci_param_mutable_type cci_param_typed::get_mutable_type() const +{ + return TM; +} + +template +void cci_param_typed::set_cci_value(const cci_value& val, + const void *pwd, + const cci_originator& originator) +{ + value_type v = val.get(); + set_raw_value(&v, pwd, originator); +} + +template +void cci_param_typed::preset_cci_value(const cci_value& val, + const cci_originator& originator) +{ + value_type old_value = m_value; + value_type new_value = val.get(); + + if (!pre_write_callback(new_value, originator)) + return; + + // Actual write + m_value = new_value; + + // Update value's origin + m_value_origin = originator; + + // Write callback(s) + post_write_callback(old_value, new_value, originator); +} + +template +cci_value +cci_param_typed::get_cci_value(const cci_originator& originator) const +{ + return cci_value( get_value(originator) ); +} + +template +cci_value cci_param_typed::get_default_cci_value() const { + return cci_value(m_default_value); +} + +template +bool cci_param_typed::is_default_value() const +{ + return m_default_value == m_value; +} + +template +bool cci_param_typed::is_preset_value() const +{ + if (m_broker_handle.has_preset_value(name())) + { + cci_value init_value = m_broker_handle.get_preset_cci_value(name()); + T i; + if (init_value.try_get(i)) { + return i == m_value; + } + } + return false; +} + +template +bool cci_param_typed::lock(const void* pwd) +{ + cci_param_untyped::fast_write=false; + return cci_param_untyped::lock(pwd); +} + +// Callbacks + +#define CCI_PARAM_TYPED_CALLBACK_IMPL_(name) \ +template \ +cci_callback_untyped_handle \ +cci_param_typed::register_##name##_callback( \ + const cci_param_##name##_callback_untyped &cb, \ + cci_untyped_tag) \ +{ \ + cci_param_untyped::fast_read=false; \ + cci_param_untyped::fast_write=false; \ + return cci_param_untyped::register_##name##_callback(cb); \ +} \ + \ +template \ +template \ +cci_callback_untyped_handle \ +cci_param_typed::register_##name##_callback( \ + cci_param_##name##_callback_untyped::signature (C::*cb), C* obj, \ + cci_untyped_tag) \ +{ \ + cci_param_untyped::fast_read=false; \ + cci_param_untyped::fast_write=false; \ + return cci_param_untyped::register_##name##_callback(cb, obj); \ +} \ + \ +template \ +cci_callback_untyped_handle \ +cci_param_typed::register_##name##_callback( \ + const cci_param_##name##_callback_typed &cb, cci_typed_tag) \ +{ \ + cci_param_untyped::fast_read=false; \ + cci_param_untyped::fast_write=false; \ + return cci_param_untyped::register_##name##_callback(cb, get_originator());\ +} \ + \ +template \ +template \ +cci_callback_untyped_handle \ +cci_param_typed::register_##name##_callback( \ + typename cci_param_##name##_callback_typed::signature (C::*cb), \ + C* obj, cci_typed_tag) \ +{ \ + cci_param_untyped::fast_read=false; \ + cci_param_untyped::fast_write=false; \ + return register_##name##_callback(sc_bind(cb, obj, sc_unnamed::_1)); \ +} + +// Pre write callback +CCI_PARAM_TYPED_CALLBACK_IMPL_(pre_write) + +// Post write callback +CCI_PARAM_TYPED_CALLBACK_IMPL_(post_write) + +// Pre read callback +CCI_PARAM_TYPED_CALLBACK_IMPL_(pre_read) + +// Post read callback +CCI_PARAM_TYPED_CALLBACK_IMPL_(post_read) + +/// Constructors + +#define CCI_PARAM_CONSTRUCTOR_CCI_VALUE_IMPL(signature, broker) \ +template \ +cci_param_typed::cci_param_typed signature \ +: cci_param_untyped(name, name_type, broker, desc, originator), \ + m_value(default_value.get()), \ + m_default_value(default_value.get()) \ +{ \ + this->init(m_broker_handle); \ +} + +#define CCI_PARAM_CONSTRUCTOR_IMPL(signature, broker) \ +template \ +cci_param_typed::cci_param_typed signature \ +: cci_param_untyped(name, name_type, broker, desc, originator), \ + m_value(default_value), \ + m_default_value(default_value) \ +{ \ + this->init(m_broker_handle); \ +} + + +/// Constructor with (local/hierarchical) name, default value, description, +/// name type and originator. +CCI_PARAM_CONSTRUCTOR_IMPL((const std::string& name, + const value_type& default_value, + const std::string& desc, + cci_name_type name_type, + const cci_originator& originator), + find_broker_convenience(originator)) + +/// Constructor with (local/hierarchical) name, default value, description, +/// name type and originator. +CCI_PARAM_CONSTRUCTOR_CCI_VALUE_IMPL((const std::string& name, + const cci_value& default_value, + const std::string& desc, + cci_name_type name_type, + const cci_originator& originator), + find_broker_convenience(originator)) + +/// Constructor with (local/hierarchical) name, default value, private broker, +/// description, name type and originator. +CCI_PARAM_CONSTRUCTOR_IMPL((const std::string& name, + const value_type& default_value, + cci_broker_handle private_broker, + const std::string& desc, + cci_name_type name_type, + const cci_originator& originator), + private_broker) + +/// Constructor with (local/hierarchical) name, default value, private broker, +/// description, name type and originator. +CCI_PARAM_CONSTRUCTOR_CCI_VALUE_IMPL((const std::string& name, + const cci_value& default_value, + cci_broker_handle private_broker, + const std::string& desc, + cci_name_type name_type, + const cci_originator& originator), + private_broker) + +#undef CCI_PARAM_CONSTRUCTOR_IMPL +#undef CCI_PARAM_CONSTRUCTOR_CCI_VALUE_IMPL +#undef CCI_PARAM_TYPED_CALLBACK_IMPL_ + +template +bool cci_param_typed::reset() +{ + if (is_locked()) + return false; + const std::string& nm = name(); + if (m_broker_handle.has_preset_value(nm)) { + // Apply preset value if it exists + cci_value preset = m_broker_handle.get_preset_cci_value(nm); + preset_cci_value(preset, m_broker_handle.get_preset_value_origin(nm)); + } else { + // Otherwise apply the default value + // Can't just call set_raw_value(); won't work for IMMUTABLE params. + if (!pre_write_callback(get_default_value(), m_originator)) + return false; + + // Actual write + value_type old_value = m_value; + m_value = get_default_value(); + + // Update value's origin + m_value_origin = m_originator; + + // Write callback(s) + post_write_callback(old_value, get_default_value(), m_originator); + } + return true; +} + +#if CCI_CPLUSPLUS >= 201103L +/// Convenience shortcut for typed parameters +template +using cci_param = cci_param_typed; +#else +/// Convenience macro for typed parameters (on C++03) +# define cci_param cci_param_typed +#endif + +CCI_CLOSE_NAMESPACE_ +#endif //CCI_CFG_CCI_PARAM_TYPED_H_INCLUDED_ diff --git a/third_party/cci-1.0.0/cci_cfg/cci_param_typed_handle.h b/third_party/cci-1.0.0/cci_cfg/cci_param_typed_handle.h new file mode 100644 index 000000000..60026d000 --- /dev/null +++ b/third_party/cci-1.0.0/cci_cfg/cci_param_typed_handle.h @@ -0,0 +1,266 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + ****************************************************************************/ + +#ifndef CCI_CFG_CCI_PARAM_TYPED_HANDLE_H_INCLUDED_ +#define CCI_CFG_CCI_PARAM_TYPED_HANDLE_H_INCLUDED_ + +#include "cci_cfg/cci_mutable_types.h" +#include "cci_cfg/cci_param_untyped_handle.h" + +/** + * @author Guillaume Delbergue, Ericsson / GreenSocs + */ + +CCI_OPEN_NAMESPACE_ + +template class cci_param_typed; + +/** + * @brief Type-safe parameter handle + * @tparam T underlying type of given parameter + * + * This class provides a typed handle to access a CCI parameter. + * In addition to the untyped capabilities, it provides type-safe + * access to the parameter value and allows registering typed + * callbacks. + * + * @see cci_param_untyped_handle, cci_param_if + */ +template +class cci_param_typed_handle : public cci_param_untyped_handle +{ +public: + /// The parameter's value type. + typedef T value_type; + + /** + * @brief Constructor to create a typed parameter handle + * @param untyped Untyped parameter handle to restore type information on + * @pre untyped.get_type_info() == typedif(T) + * + * If the destination type T does not match the underlying type of + * the referenced parameter, the resulting handle is invalidated. + * + * @see cci_param_cast + */ + explicit cci_param_typed_handle(cci_param_untyped_handle untyped); + +#if CCI_CPLUSPLUS >= 201103L + cci_param_typed_handle(const cci_param_typed_handle&) = default; + cci_param_typed_handle& operator=(const cci_param_typed_handle&) = default; + + cci_param_typed_handle(cci_param_typed_handle&& that) + : cci_param_untyped_handle(CCI_MOVE_(that)) {} + + cci_param_typed_handle& operator=(cci_param_typed_handle&& that) + { + cci_param_untyped_handle::operator=(CCI_MOVE_(that)); + return *this; + } + ~cci_param_typed_handle() = default; +#endif // C++11 + + ///Sets the stored value to a new value + /** + * @param value new value to assign + */ + void set_value(const value_type& value); + + ///Sets the stored value to a new value + /** + * @param value new value to assign + * @param pwd Password needed to unlock the param, ideally any pointer address known only by the locking entity, default = NULL + */ + void set_value(const value_type & value, const void * pwd); + + /// Convenience shortcut to read the stored value + const value_type& operator*() const; + + ///Gets the stored value + const value_type& get_value() const; + + ///Get the value passed in via constructor + const value_type & get_default_value() const; + +#define CCI_PARAM_TYPED_HANDLE_CALLBACK_DECL_(name) \ + /** @copydoc cci_param_untyped::register_##name##_callback(const cci_param_##name##_callback_untyped, cci_untyped_tag) */ \ + cci_callback_untyped_handle register_##name##_callback( \ + const cci_param_##name##_callback_untyped &cb, \ + cci_untyped_tag); \ + \ + /** @copydoc cci_param_untyped::register_##name##_callback(cci_param_##name##_callback_untyped::signature, C*, cci_untyped_tag) */ \ + template \ + cci_callback_untyped_handle register_##name##_callback( \ + cci_param_##name##_callback_untyped::signature (C::*cb), C* obj, \ + cci_untyped_tag); \ + \ + /** @brief Typed name callback type */ \ + typedef typename cci_param_##name##_callback::type \ + cci_param_##name##_callback_typed; \ + \ + /** @copydoc cci_param_typed::register_##name##_callback(const cci_param_##name##_callback_typed&, cci_typed_tag) */ \ + cci_callback_untyped_handle register_##name##_callback( \ + const cci_param_##name##_callback_typed& cb, \ + cci_typed_tag = cci_typed_tag()); \ + \ + /** @copydoc cci_param_typed::register_##name##_callback(typename cci_param_##name##_callback_typed::signature, C*, cci_typed_tag) */ \ + template \ + cci_callback_untyped_handle register_##name##_callback( \ + typename cci_param_##name##_callback_typed::signature (C::*cb), \ + C* obj, cci_typed_tag = cci_typed_tag()) + + /// @name Pre write callback handling + /// @{ + + CCI_PARAM_TYPED_HANDLE_CALLBACK_DECL_(pre_write); + + /// @} + + /// @name Post write callback handling + /// @{ + + CCI_PARAM_TYPED_HANDLE_CALLBACK_DECL_(post_write); + + /// @} + + /// @name Pre read callback handling + /// @{ + + CCI_PARAM_TYPED_HANDLE_CALLBACK_DECL_(pre_read); + + /// @} + + /// @name Post read callback handling + /// @{ + + CCI_PARAM_TYPED_HANDLE_CALLBACK_DECL_(post_read); + + /// @} + +#undef CCI_PARAM_TYPED_HANDLE_CALLBACK_DECL_ + +private: + const value_type& typed_cast(const void* val) const + { return *static_cast(val); } +}; + +template +const T& cci_param_typed_handle::operator *() const +{ + return get_value(); +} + +template +void cci_param_typed_handle::set_value(const value_type& value) +{ + cci_param_untyped_handle::set_raw_value(&value); +} + +template +void cci_param_typed_handle::set_value(const value_type& value, const void *pwd) +{ + cci_param_untyped_handle::set_raw_value(&value, pwd); +} + +template +const T& cci_param_typed_handle::get_value() const +{ + return typed_cast(cci_param_untyped_handle::get_raw_value()); +} + +template +const typename cci_param_typed_handle::value_type& +cci_param_typed_handle::get_default_value() const +{ + return typed_cast(cci_param_untyped_handle::get_raw_default_value()); +} + +#define CCI_PARAM_TYPED_HANDLE_CALLBACK_IMPL_(name) \ +template \ +cci_callback_untyped_handle \ +cci_param_typed_handle::register_##name##_callback( \ + const cci_param_##name##_callback_untyped &cb, \ + cci_untyped_tag) \ +{ \ + return cci_param_untyped_handle::register_##name##_callback(cb); \ +} \ + \ +template \ +template \ +cci_callback_untyped_handle \ +cci_param_typed_handle::register_##name##_callback( \ + cci_param_##name##_callback_untyped::signature (C::*cb), C* obj, \ + cci_untyped_tag) \ +{ \ + return cci_param_untyped_handle::register_##name##_callback(cb, obj); \ +} \ + \ +template \ +cci_callback_untyped_handle \ +cci_param_typed_handle::register_##name##_callback( \ + const cci_param_##name##_callback_typed &cb, cci_typed_tag) \ +{ \ + return cci_param_untyped_handle::register_##name##_callback(cb, \ + cci_typed_tag()); \ +} \ + \ +template \ +template \ +cci_callback_untyped_handle \ +cci_param_typed_handle::register_##name##_callback( \ + typename cci_param_##name##_callback_typed::signature (C::*cb), \ + C* obj, cci_typed_tag) \ +{ \ + return register_##name##_callback(sc_bind(cb, obj, sc_unnamed::_1)); \ +} + +CCI_PARAM_TYPED_HANDLE_CALLBACK_IMPL_(pre_write) + +CCI_PARAM_TYPED_HANDLE_CALLBACK_IMPL_(post_write) + +CCI_PARAM_TYPED_HANDLE_CALLBACK_IMPL_(pre_read) + +CCI_PARAM_TYPED_HANDLE_CALLBACK_IMPL_(post_read) + +template +cci_param_typed_handle::cci_param_typed_handle(cci_param_untyped_handle untyped) + : cci_param_untyped_handle(CCI_MOVE_(untyped)) +{ + if(is_valid() && typeid(T) != get_type_info()) { + invalidate(); + } +} + +/** + * @brief Recover type information on a parameter handle + * @tparam T Assumed underlying type of given parameter + * @param untyped Untyped handle to convert to a typed handle + * @return typed parameter handle, if types match; an invalid handle otherwise + * @see cci_param_typed_handle::cci_param_typed_handle(cci_param_untyped_handle) + */ +template +cci_param_typed_handle +cci_param_cast(const cci_param_untyped_handle& untyped) + { return cci_param_typed_handle(untyped); } + +#undef CCI_PARAM_TYPED_HANDLE_CALLBACK_IMPL_ + +CCI_CLOSE_NAMESPACE_ + +#endif //CCI_CFG_CCI_BASE_PARAM_HANDLE_H_INCLUDED_ diff --git a/third_party/cci-1.0.0/cci_cfg/cci_param_untyped.cpp b/third_party/cci-1.0.0/cci_cfg/cci_param_untyped.cpp new file mode 100644 index 000000000..b0a1132ea --- /dev/null +++ b/third_party/cci-1.0.0/cci_cfg/cci_param_untyped.cpp @@ -0,0 +1,291 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + ****************************************************************************/ +/** + * @author Enrico Galli, Intel + * @author Guillaume Delbergue, GreenSocs / Ericsson + */ + +#include "cci_cfg/cci_param_untyped.h" + +#include +#include "cci_cfg/cci_broker_handle.h" +#include "cci_cfg/cci_param_if.h" +#include "cci_cfg/cci_param_untyped_handle.h" +#include "cci_cfg/cci_report_handler.h" +#include "cci_core/cci_name_gen.h" + +CCI_OPEN_NAMESPACE_ + +cci_param_untyped::cci_param_untyped(const std::string& name, + cci_name_type name_type, + cci_broker_handle broker_handle, + const std::string& desc, + const cci_originator& originator) + : m_description(desc), m_lock_pwd(NULL), + m_broker_handle(broker_handle), m_value_origin(originator), + m_originator(originator), fast_read(false),fast_write(false) +{ + if(name_type == CCI_ABSOLUTE_NAME) { + m_name = name; + } else { + sc_core::sc_object* current_obj = sc_core::sc_get_current_object(); + for (sc_core::sc_process_handle current_proc(current_obj); + current_proc.valid(); + current_proc = sc_core::sc_process_handle(current_obj)) { + current_obj = current_proc.get_parent_object(); + } + if(current_obj) { + m_name = std::string(current_obj->name()) + + sc_core::SC_HIERARCHY_CHAR + name; + } else { + m_name = name; + } + } + + // Handle name collision and destruction / resurrection + std::string unique_name = std::string(cci_gen_unique_name(m_name.c_str())); + if (unique_name != m_name + && (sc_core::sc_hierarchical_name_exists(m_name.c_str()) + || broker_handle.has_preset_value(m_name))) { + m_name = unique_name; + } +} + +cci_param_untyped::~cci_param_untyped() +{ + // should have been invalidated from within typed implementation + // (through call to cci_param_if::destroy) + sc_assert( m_param_handles.empty() ); + + if(!m_name.empty()) { + cci_unregister_name(name()); + } +} + +void cci_param_untyped::set_description(const std::string& desc) +{ + m_description = desc; +} + +std::string cci_param_untyped::get_description() const +{ + return m_description; +} + +void cci_param_untyped::add_metadata(const std::string &name, + const cci_value &value, + const std::string &desc) +{ + metadata.push_entry(name, cci_value_list().push_back(value) + .push_back(desc)); +} + +cci_value_map cci_param_untyped::get_metadata() const +{ + return metadata; +} + +bool cci_param_untyped::is_preset_value() const +{ + if (!m_broker_handle.has_preset_value(name())) return false; + cci_value init_value = m_broker_handle.get_preset_cci_value(name()); + return init_value == get_cci_value(m_originator); +} + +cci_originator cci_param_untyped::get_value_origin() const +{ + return m_value_origin; +} + +bool +cci_param_untyped::set_cci_value_allowed(cci_param_mutable_type mutability) +{ + if (mutability==CCI_IMMUTABLE_PARAM) { + std::stringstream ss; + ss << "Parameter (" << name() << ") is immutable."; + cci_report_handler::set_param_failed(ss.str().c_str(), __FILE__, __LINE__); + return false; + } + return true; +} + +#define CCI_PARAM_UNTYPED_CALLBACK_IMPL_(name) \ +cci_callback_untyped_handle \ +cci_param_untyped::register_##name##_callback( \ + const cci_callback_untyped_handle &cb, \ + const cci_originator &orig) \ +{ \ + fast_read=false; \ + fast_write=false; \ + m_##name##_callbacks.vec.push_back(name##_callback_obj_t(cb, orig)); \ + return cb; \ +} \ + \ +cci_callback_untyped_handle \ +cci_param_untyped::register_##name##_callback( \ + const cci_param_##name##_callback_untyped& cb, \ + cci_untyped_tag) \ +{ \ + return cci_param_untyped::register_##name##_callback(cb, m_originator); \ +} \ + \ +bool \ +cci_param_untyped::unregister_##name##_callback( \ + const cci_callback_untyped_handle &cb, \ + const cci_originator &orig) \ +{ \ + std::vector::iterator it; \ + for(it=m_##name##_callbacks.vec.begin() ; \ + it < m_##name##_callbacks.vec.end(); \ + it++) \ + { \ + if(it->callback == cb && it->originator == orig) { \ + m_##name##_callbacks.vec.erase(it); \ + return true; \ + } \ + } \ + return false; \ +} \ + \ +bool \ +cci_param_untyped::unregister_##name##_callback( \ + const cci_callback_untyped_handle &cb) \ +{ \ + return unregister_##name##_callback(cb, m_originator); \ +} + +CCI_PARAM_UNTYPED_CALLBACK_IMPL_(pre_write) + +CCI_PARAM_UNTYPED_CALLBACK_IMPL_(post_write) + +CCI_PARAM_UNTYPED_CALLBACK_IMPL_(pre_read) + +CCI_PARAM_UNTYPED_CALLBACK_IMPL_(post_read) + +bool cci_param_untyped::unregister_all_callbacks(const cci_originator &orig) +{ + bool result = false; + for (std::vector::iterator it = + m_pre_write_callbacks.vec.begin(); + it < m_pre_write_callbacks.vec.end(); it++) + { + if(it->originator == orig) { + m_pre_write_callbacks.vec.erase(it); + result = true; + } + } + for(std::vector::iterator it = + m_post_write_callbacks.vec.begin(); + it < m_post_write_callbacks.vec.end(); it++) + { + if(it->originator == orig) { + m_post_write_callbacks.vec.erase(it); + result = true; + } + } + for(std::vector::iterator it = + m_pre_read_callbacks.vec.begin(); + it < m_pre_read_callbacks.vec.end(); it++) + { + if(it->originator == orig) { + m_pre_read_callbacks.vec.erase(it); + result = true; + } + } + for(std::vector::iterator it = + m_post_read_callbacks.vec.begin(); + it < m_post_read_callbacks.vec.end(); it++) + { + if(it->originator == orig) { + m_post_read_callbacks.vec.erase(it); + result = true; + } + } + return result; +} + +bool cci_param_untyped::unregister_all_callbacks() +{ + return unregister_all_callbacks(m_originator); +} + +bool cci_param_untyped::has_callbacks() const +{ + return (!m_post_write_callbacks.vec.empty() || + !m_pre_write_callbacks.vec.empty()); +} + +bool cci_param_untyped::lock(const void* pwd) +{ + if (!pwd) pwd=this; + if(pwd != m_lock_pwd && m_lock_pwd != NULL) { + return false; + } else { + m_lock_pwd = pwd; + return true; + } +} + +bool cci_param_untyped::unlock(const void* pwd) +{ + if (!pwd) pwd=this; + if(pwd == m_lock_pwd) { + m_lock_pwd = NULL; + return true; + } + return false; +} + +bool cci_param_untyped::is_locked() const +{ + return m_lock_pwd != NULL; +} + +const char* cci_param_untyped::name() const +{ + return m_name.c_str(); +} + +cci_originator cci_param_untyped::get_originator() const +{ + return m_originator; +} + +void cci_param_untyped::add_param_handle(cci_param_untyped_handle* param_handle) +{ + m_param_handles.push_back(param_handle); +} + +void cci_param_untyped::remove_param_handle( + cci_param_untyped_handle* param_handle) +{ + m_param_handles.erase(std::remove(m_param_handles.begin(), + m_param_handles.end(), + param_handle), + m_param_handles.end()); +} + +void +cci_param_untyped::invalidate_all_param_handles() +{ + while( !m_param_handles.empty() ) + m_param_handles.front()->invalidate(); // removes itself from the list +} + +CCI_CLOSE_NAMESPACE_ diff --git a/third_party/cci-1.0.0/cci_cfg/cci_param_untyped.h b/third_party/cci-1.0.0/cci_cfg/cci_param_untyped.h new file mode 100644 index 000000000..5e6b0d524 --- /dev/null +++ b/third_party/cci-1.0.0/cci_cfg/cci_param_untyped.h @@ -0,0 +1,624 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + ****************************************************************************/ + +/** + * @author Enrico Galli, Intel + */ +#ifndef CCI_CFG_CCI_PARAM_UNTYPED_H_INCLUDED_ +#define CCI_CFG_CCI_PARAM_UNTYPED_H_INCLUDED_ + +#include +#include + +#include "cci_cfg/cci_broker_handle.h" +#include "cci_cfg/cci_originator.h" +#include "cci_cfg/cci_param_if.h" +#include "cci_core/cci_core_types.h" +#include "cci_core/cci_value.h" + +CCI_OPEN_NAMESPACE_ + +// CCI Configuration parameter base class +/** +* Type independent base class all cci parameters derive from. +* This class gives some easier access to type independent functions. +*/ +class cci_param_untyped : public cci_param_if +{ + +public: + + /// Destructor. + virtual ~cci_param_untyped(); + + ///@name Description + ///@{ + + /// Set parameter description. + /** + * Set the parameter's description describing purpose and + * intended use, allowed value range etc. in a human readable way. + * + * @param desc Human readable description + */ + virtual void set_description(const std::string& desc); + + /// Get the parameter's description. + /** + * @return Description + */ + virtual std::string get_description() const; + + ///@} + + ///@name Metadata + ///@{ + + /// Add metadata + /** + * Add metadata to the parameter identified by its name, value + * and a human readable description. + * + * @param name Name of the metadata + * @param value Value of the metadata + * @param desc Human readable description + */ + void add_metadata(const std::string &name, const cci_value &value, + const std::string &desc = ""); + + /// Return the metadata value + /** + * Return value of the metadata by its given name. + * + * @return name Name of the metadata + * @return Metadata value + */ + cci_value_map get_metadata() const; + + ///@} + + ///@name Parameter Value Status + ///@{ + + /// Indicates whether the value provided at parameter construction persists. + /** + * True if the value was supplied as a constructor argument and not + * subsequently changed. + * + * Note: false is returned even if the current value matches the constructor + * supplied default but has undergone intermediate changes. + * + * @return false if the parameter received a preset value or its value has + * changed; otherwise, true + */ + virtual bool is_default_value() const =0; // note this is pure virtual here, + // as the function isn't possible + // without a typed instance (to + // have a defualt value). + + + /// Indicates that the parameter received a preset value that has not since been modified. + /** + * True if the value was supplied using the broker's + * set_preset_cci_value function and not subsequently changed. + * + * Note: false is returned even if the current value matches the preset + * value but has undergone intermediate changes. + * + * @return fase if no preset value was supplied or the parameter's value has + * changed; otherwise, true + */ + virtual bool is_preset_value() const; + + ///@} + + + ///@name Miscellaneous + ///@{ + + /// Returns the originator of the parameter's current value. + /** + * This initially reflects originator of the parameter's starting value, + * e.g. the owning module or startup configuration file. It is + * subsequently updated to reflect the originator of any value changes. + * + * The originator is updated on successful calls to the following functions: + * set_cci_value(), cci_param_typed::set_value(), cci_param_typed::operator=() + */ + cci_originator get_value_origin() const; + + ///@} + + /// @name Post write callback handling + /// @{ + + /// Register an untyped write callback. + /** + * @param cb Untyped post write callback + * @param cci_untyped_tag Untyped tag to avoid compiler ambiguity + * + * @return Untyped callback handle + */ + cci_callback_untyped_handle + register_post_write_callback( + const cci_param_post_write_callback_untyped& cb, + cci_untyped_tag = cci_untyped_tag()); + + /// Register an untyped post write callback with a method as callback + /** + * @param cb Untyped post write callback method + * @param obj Associated object instance pointer + * @param cci_untyped_tag Untyped tag to avoid compiler ambiguity + * + * @return Untyped callback handle + */ + template + cci_callback_untyped_handle + register_post_write_callback( + cci_param_post_write_callback_untyped::signature (C::*cb), C* obj, + cci_untyped_tag = cci_untyped_tag()) + { + return register_post_write_callback(sc_bind(cb, obj, sc_unnamed::_1)); + } + + /// Unregister a post write callback handle + /** + * @param cb Untyped post write callback handle + * + * @return True if unregister is a success. Otherwise False. + */ + bool + unregister_post_write_callback(const cci_callback_untyped_handle &cb); + + /// @} + + /// @name Pre write callback handling + /// @{ + + /// Register an untyped pre write callback. + /** + * @param cb Untyped pre write callback + * @param cci_untyped_tag Untyped tag to avoid compiler ambiguity + * + * @return Untyped callback handle + */ + cci_callback_untyped_handle + register_pre_write_callback( + const cci_param_pre_write_callback_untyped& cb, + cci_untyped_tag = cci_untyped_tag()); + + /// Register an untyped pre write callback with a method as callback + /** + * @param cb Untyped validate write callback method + * @param obj Associated object instance pointer + * @param cci_untyped_tag Untyped tag to avoid compiler ambiguity + * + * @return Untyped callback handle + */ + template + cci_callback_untyped_handle + register_pre_write_callback( + cci_param_pre_write_callback_untyped::signature(C::*cb), + C* obj, cci_untyped_tag = cci_untyped_tag()) + { + return register_pre_write_callback( + sc_bind(cb, obj, sc_unnamed::_1)); + } + + /// Unregister a pre write callback handle + /** + * @param cb Untyped pre write callback handle + * + * @return True if unregister is a success. Otherwise False. + */ + bool + unregister_pre_write_callback(const cci_callback_untyped_handle &cb); + + /// @} + + /// @name Pre read callback handling + /// @{ + + /// Register an untyped pre read callback. + /** + * @param cb Untyped pre read callback + * @param cci_untyped_tag Untyped tag to avoid compiler ambiguity + * + * @return Untyped callback handle + */ + cci_callback_untyped_handle + register_pre_read_callback(const cci_param_pre_read_callback_untyped& cb, + cci_untyped_tag = cci_untyped_tag()); + + /// Register an untyped pre read callback with a method as callback + /** + * @param cb Untyped pre read callback method + * @param obj Associated object instance pointer + * @param cci_untyped_tag Untyped tag to avoid compiler ambiguity + * + * @return Untyped callback handle + */ + template + cci_callback_untyped_handle + register_pre_read_callback(cci_param_pre_read_callback_untyped::signature + (C::*cb), C* obj, + cci_untyped_tag = cci_untyped_tag()) + { + return register_pre_read_callback(sc_bind(cb, obj, sc_unnamed::_1)); + } + + /// Unregister a pre read callback handle + /** + * @param cb Untyped pre read callback handle + * + * @return True if unregister is a success. Otherwise False. + */ + bool + unregister_pre_read_callback(const cci_callback_untyped_handle &cb); + + /// @} + + /// @name Post read callback handling + /// @{ + + /// Register an untyped post read callback. + /** + * @param cb Untyped post read callback + * @param cci_untyped_tag Untyped tag to avoid compiler ambiguity + * + * @return Untyped callback handle + */ + cci_callback_untyped_handle + register_post_read_callback(const cci_param_post_read_callback_untyped& cb, + cci_untyped_tag = cci_untyped_tag()); + + /// Register an untyped post read callback with a method as callback + /** + * @param cb Untyped post read callback method + * @param obj Associated object instance pointer + * @param cci_untyped_tag Untyped tag to avoid compiler ambiguity + * + * @return Untyped callback handle + */ + template + cci_callback_untyped_handle + register_post_read_callback(cci_param_post_read_callback_untyped::signature + (C::*cb), C* obj, + cci_untyped_tag = cci_untyped_tag()) + { + return register_post_read_callback(sc_bind(cb, obj, sc_unnamed::_1)); + } + + /// Unregister a post read callback handle + /** + * @param cb Untyped post read callback handle + * + * @return True if unregister is a success. Otherwise False. + */ + bool + unregister_post_read_callback(const cci_callback_untyped_handle &cb); + + /// @} + + /// @name Callback handling + /// @{ + + /// Unregister all callbacks + /** + * @return True if success, otherwise False + */ + bool unregister_all_callbacks(); + + /// Returns if the parameter has registered callbacks. + /** + * @return True if the parameter has registered callbacks, otherwise False + */ + bool has_callbacks() const; + + /// @} + + /// Add parameter handle + /** + * Add a parameter handle associated with this parameter. + * + * @param param_handle Parameter handle to add. + */ + void add_param_handle(cci_param_untyped_handle* param_handle); + + /// Remove parameter handle + /** + * Remove a parameter handle associated with this parameter. + * + * @param param_handle Parameter handle to remove. + */ + void remove_param_handle(cci_param_untyped_handle* param_handle); + + +protected: + /// @name Post callback handling implementation + /// @{ + + /// Register a post write callback handle + /** + * @param cb Untyped post write callback handle + * @param cci_originator Originator + * + * @return Untyped callback handle + */ + cci_callback_untyped_handle + register_post_write_callback(const cci_callback_untyped_handle &cb, + const cci_originator &orig); + + /// Unregister a post write callback handle + /** + * @param cb Untyped post write callback handle + * @param cci_originator Originator + * + * @return True if unregister is a success. Otherwise False. + */ + bool + unregister_post_write_callback(const cci_callback_untyped_handle &cb, + const cci_originator &orig); + + /// @} + + /// @name Pre write callback handling implementation + /// @{ + + /// Register a pre write callback handle + /** + * @param cb Untyped pre write callback handle + * @param cci_originator Originator + * + * @return Untyped callback handle + */ + cci_callback_untyped_handle + register_pre_write_callback(const cci_callback_untyped_handle &cb, + const cci_originator &orig); + + /// Unregister a pre write callback handle + /** + * @param cb Untyped pre write callback handle + * @param cci_originator Originator + * + * @return True if unregister is a success. Otherwise False. + */ + bool + unregister_pre_write_callback(const cci_callback_untyped_handle &cb, + const cci_originator &orig); + + /// @} + + /// @name Pre read callback handling implementation + /// @{ + + /// Register a pre read callback handle + /** + * @param cb Untyped pre read callback handle + * @param cci_originator Originator + * + * @return Untyped callback handle + */ + cci_callback_untyped_handle + register_pre_read_callback(const cci_callback_untyped_handle &cb, + const cci_originator &orig); + + /// Unregister a pre read callback handle + /** + * @param cb Untyped pre read callback handle + * @param cci_originator Originator + * + * @return True if unregister is a success. Otherwise False. + */ + bool + unregister_pre_read_callback(const cci_callback_untyped_handle &cb, + const cci_originator &orig); + + /// @} + + /// @name Post read callback handling implementation + /// @{ + + /// Register a post read callback handle + /** + * @param cb Untyped post read callback handle + * @param cci_originator Originator + * + * @return Untyped callback handle + */ + cci_callback_untyped_handle + register_post_read_callback(const cci_callback_untyped_handle &cb, + const cci_originator &orig); + + /// Unregister a post read callback handle + /** + * @param cb Untyped post read callback handle + * @param cci_originator Originator + * + * @return True if unregister is a success. Otherwise False. + */ + bool + unregister_post_read_callback(const cci_callback_untyped_handle &cb, + const cci_originator &orig); + + /// @} + + /// @name Callback handling implementation + /// @{ + + /// Unregister all callbacks (write, validate write and read callbacks). + /** + * @param cci_originator Originator + * + * @return True if unregister is a success. Otherwise False. + */ + bool unregister_all_callbacks(const cci_originator &orig); + + ///@} + +public: + + ///@name Write-access control + ///@{ + + /// Locking this parameter, optionally with a password. + /** + * Makes a parameter read-only. + * + * Returns false + * - if this parameter was already locked with a different password (this call has no effect) + * + * Returns true + * - if the parameter was not locked (and is locked now) or + * - if the parameter was locked without a password. Then it is locked now with the given password + * - if the parameter was locked with the given password pwd. Then it is still locked now with the given password. + * + * @param pwd Password needed to unlock the param, ideally any pointer + * address known only by the locking entity. If no key is given + * an internal 'key' (unique to the parameter) will be used. + * @return If the lock was successful. + */ + bool lock(const void* pwd = NULL); + + /// Unlocking this parameter, optionally with a password if needed. + /** + * @param pwd Password to unlock the param (if needed), + * If no key is given an internal 'key' will be used. + * @return If the parameter is unlocked now. + */ + bool unlock(const void* pwd = NULL); + + /// If this parameter is locked. + /** + * @return If this parameter is locked + */ + bool is_locked() const; + + ///@} + + ///@name Query parameter type and name + ///@{ + + /// Get the name of this parameter. + /** + * @return Name of the parameter. + */ + const char* name() const; + + ///@} + + ///@name Originator query + ///@{ + + /// Gets cci_originator of the parameter. + /** + * The originator reflects ownership of the parameter proxy, which points + * to an implementation. For a handle, the originator identifies the + * entity accessing the parameter. Otherwise, the originator reflects + * the parameter's creator. + */ + cci_originator get_originator() const; + + ///@} + +protected: + /// Constructor to create new parameter with given originator. + cci_param_untyped(const std::string& name, cci_name_type name_type, + cci_broker_handle broker_handle, const std::string& desc, + const cci_originator& originator); + + /// check mutability + bool set_cci_value_allowed(cci_param_mutable_type mutability); + +protected: + /// Name + std::string m_name; + + /// Description + std::string m_description; + + /// Metadata + cci_value_map metadata; + + /// Passwort needed to unlock the parameter or override the lock + const void* m_lock_pwd; + + /// Broker handle + cci_broker_handle m_broker_handle; + + /// Stores the originator of the latest successful write access + mutable cci_originator m_value_origin; + + /// Callback object + template + struct callback_obj { + callback_obj(T cb, const cci_originator& orig): + callback(cb), originator(orig) {} + T callback; + cci_originator originator; + }; + + /// Callback object vector with tag to avoid nested callback + template + struct callback_obj_vector { + callback_obj_vector():oncall(false){}; + std::vector vec; + mutable bool oncall; + }; + + /// Pre write callbacks + typedef callback_obj + pre_write_callback_obj_t; + + callback_obj_vector m_pre_write_callbacks; + + /// Post write callbacks + typedef callback_obj + post_write_callback_obj_t; + + callback_obj_vector m_post_write_callbacks; + + /// Pre read callbacks + typedef callback_obj + pre_read_callback_obj_t; + + callback_obj_vector m_pre_read_callbacks; + + /// Post read callbacks + typedef callback_obj + post_read_callback_obj_t; + + callback_obj_vector m_post_read_callbacks; + + /// Originator of the parameter + const cci_originator m_originator; + +private: + /// @copydoc cci_param_if::invalidate_all_param_handles + virtual void invalidate_all_param_handles(); + + /// Parameter handles + std::vector m_param_handles; + +protected: + bool fast_read, fast_write; +}; + +CCI_CLOSE_NAMESPACE_ +#endif // CCI_CFG_CCI_PARAM_UNTYPED_H_INCLUDED_ diff --git a/third_party/cci-1.0.0/cci_cfg/cci_param_untyped_handle.cpp b/third_party/cci-1.0.0/cci_cfg/cci_param_untyped_handle.cpp new file mode 100644 index 000000000..ceae4ed19 --- /dev/null +++ b/third_party/cci-1.0.0/cci_cfg/cci_param_untyped_handle.cpp @@ -0,0 +1,313 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + ****************************************************************************/ + +/** + * @author Enrico Galli, Intel + */ + +#include "cci_cfg/cci_param_untyped_handle.h" + +#include "cci_cfg/cci_broker_manager.h" +#include "cci_cfg/cci_param_if.h" +#include "cci_cfg/cci_report_handler.h" +#include "cci_core/cci_name_gen.h" + +CCI_OPEN_NAMESPACE_ + +cci_param_untyped_handle:: + cci_param_untyped_handle( cci_param_if & param + , const cci_originator & originator ) + : m_param(¶m) + , m_originator(originator) +{ + m_param->add_param_handle(this); +} + +cci_param_untyped_handle:: + cci_param_untyped_handle(const cci_originator & originator) + : m_param(NULL) + , m_originator(originator) +{} + +cci_param_untyped_handle::~cci_param_untyped_handle() +{ + invalidate(); +} + +cci_param_untyped_handle:: + cci_param_untyped_handle(const cci_param_untyped_handle& param_handle) + : m_param(param_handle.m_param) + , m_originator(promote_originator(param_handle.m_originator)) +{ + if(m_param) { + m_param->add_param_handle(this); + } +} + +#ifdef CCI_HAS_CXX_RVALUE_REFS +cci_param_untyped_handle:: + cci_param_untyped_handle(cci_param_untyped_handle&& param_handle) + : m_param(CCI_MOVE_(param_handle.m_param)) + , m_originator(promote_originator(param_handle.m_originator)) +{ + if(m_param) { + m_param->add_param_handle(this); + } +} +#endif // CCI_HAS_CXX_RVALUE_REFS + +cci_param_untyped_handle& +cci_param_untyped_handle::operator=(const cci_param_untyped_handle& param_handle) +{ + if (this == ¶m_handle) + return *this; + + if (m_param) { + m_param->remove_param_handle(this); + } + + m_param = param_handle.m_param; + // The originator is explicitly not assigned here. + + if (m_param) { + m_param->add_param_handle(this); + } + return *this; +} + +#ifdef CCI_HAS_CXX_RVALUE_REFS +cci_param_untyped_handle& +cci_param_untyped_handle::operator=(cci_param_untyped_handle&& param_handle) +{ + if (this == ¶m_handle) + return *this; + + if (m_param) { + m_param->remove_param_handle(this); + } + + m_param = CCI_MOVE_(param_handle.m_param); + // The originator is explicitly not assigned here. + + if (m_param) { + m_param->add_param_handle(this); + } + return *this; +} +#endif // CCI_HAS_CXX_RVALUE_REFS + +std::string cci_param_untyped_handle::get_description() const +{ + check_is_valid(); + return m_param->get_description(); +} + +cci_value_map cci_param_untyped_handle::get_metadata() const +{ + check_is_valid(); + return m_param->get_metadata(); +} + +void cci_param_untyped_handle::set_cci_value(const cci_value& val) +{ + check_is_valid(); + m_param->set_cci_value(val, NULL, m_originator); +} + +void cci_param_untyped_handle::set_cci_value(const cci_value& val, const void *pwd) +{ + check_is_valid(); + m_param->set_cci_value(val, pwd, m_originator); +} + +cci_value cci_param_untyped_handle::get_cci_value() const +{ + check_is_valid(); + return m_param->get_cci_value(m_originator); +} + +cci_param_mutable_type cci_param_untyped_handle::get_mutable_type() const +{ + check_is_valid(); + return m_param->get_mutable_type(); +} + +cci_value cci_param_untyped_handle::get_default_cci_value() const +{ + check_is_valid(); + return m_param->get_default_cci_value(); +} + +bool cci_param_untyped_handle::is_default_value() const +{ + check_is_valid(); + return m_param->is_default_value(); +} + +bool cci_param_untyped_handle::is_preset_value() const +{ + check_is_valid(); + return m_param->is_preset_value(); +} + +cci_originator +cci_param_untyped_handle::get_value_origin() const +{ + check_is_valid(); + return m_param->get_value_origin(); +} + +#define CCI_PARAM_UNTYPED_HANDLE_CALLBACK_IMPL_(name) \ +cci_callback_untyped_handle \ +cci_param_untyped_handle::register_##name##_callback( \ + const cci_param_##name##_callback_untyped &cb, \ + cci_untyped_tag) \ +{ \ + check_is_valid(); \ + return m_param->register_##name##_callback(cb, m_originator); \ +} \ + \ +cci_callback_untyped_handle \ +cci_param_untyped_handle::register_##name##_callback( \ + const cci_callback_untyped_handle& cb, cci_typed_tag) \ +{ \ + check_is_valid(); \ + return m_param->register_##name##_callback(cb, m_originator); \ +} \ + \ +bool cci_param_untyped_handle::unregister_##name##_callback( \ + const cci_callback_untyped_handle &cb) \ +{ \ + check_is_valid(); \ + return m_param->unregister_##name##_callback(cb, m_originator); \ +} + +// Pre write callback +CCI_PARAM_UNTYPED_HANDLE_CALLBACK_IMPL_(pre_write) + +// Post write callback +CCI_PARAM_UNTYPED_HANDLE_CALLBACK_IMPL_(post_write) + +// Pre read callback +CCI_PARAM_UNTYPED_HANDLE_CALLBACK_IMPL_(pre_read) + +// Post read callback +CCI_PARAM_UNTYPED_HANDLE_CALLBACK_IMPL_(post_read) + +bool cci_param_untyped_handle::unregister_all_callbacks() +{ + check_is_valid(); + return m_param->unregister_all_callbacks(m_originator); +} + +bool cci_param_untyped_handle::has_callbacks() const +{ + check_is_valid(); + return m_param->has_callbacks(); +} + +bool cci_param_untyped_handle::lock(const void* pwd) +{ + check_is_valid(); + return m_param->lock(pwd); +} + +bool cci_param_untyped_handle::unlock(const void* pwd) +{ + check_is_valid(); + return m_param->unlock(pwd); +} + +bool cci_param_untyped_handle::is_locked() const +{ + check_is_valid(); + return m_param->is_locked(); +} + +cci_param_data_category cci_param_untyped_handle::get_data_category() const +{ + check_is_valid(); + return m_param->get_data_category(); +} + +const char* cci_param_untyped_handle::name() const +{ + check_is_valid(); + return m_param->name(); +} + +cci_originator cci_param_untyped_handle::get_originator() const +{ + return m_originator; +} + +const void* cci_param_untyped_handle::get_raw_value() const +{ + check_is_valid(); + return m_param->get_raw_value(m_originator); +} + +const void* cci_param_untyped_handle::get_raw_default_value() const +{ + check_is_valid(); + return m_param->get_raw_default_value(); +} + +void cci_param_untyped_handle::set_raw_value(const void* vp) +{ + set_raw_value(vp, NULL); +} + +void cci_param_untyped_handle::set_raw_value(const void* vp, const void* pwd) +{ + check_is_valid(); + m_param->set_raw_value(vp, pwd, m_originator); +} + +const std::type_info& cci_param_untyped_handle::get_type_info() const +{ + check_is_valid(); + return m_param->get_type_info(); +} + +bool cci_param_untyped_handle::is_valid() const +{ + return m_param != NULL; +} + +void cci_param_untyped_handle::invalidate() { + if(m_param) { + m_param->remove_param_handle(this); + } + m_param = NULL; +} + +void cci_param_untyped_handle::check_is_valid() const +{ + bool invalid_error = !is_valid(); + if(invalid_error) { + CCI_REPORT_ERROR("cci_param_untyped_handle/check_is_valid", + "The handled parameter is not valid."); + cci_abort(); // cannot recover from here + } +} + +#undef CCI_PARAM_UNTYPED_HANDLE_CALLBACK_IMPL_ + +CCI_CLOSE_NAMESPACE_ diff --git a/third_party/cci-1.0.0/cci_cfg/cci_param_untyped_handle.h b/third_party/cci-1.0.0/cci_cfg/cci_param_untyped_handle.h new file mode 100644 index 000000000..88c96e414 --- /dev/null +++ b/third_party/cci-1.0.0/cci_cfg/cci_param_untyped_handle.h @@ -0,0 +1,298 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + ****************************************************************************/ + +#ifndef CCI_CCI_PARAM_UNTYPED_HANDLE_H_INCLUDED_ +#define CCI_CCI_PARAM_UNTYPED_HANDLE_H_INCLUDED_ + +#include "cci_cfg/cci_mutable_types.h" +#include "cci_cfg/cci_originator.h" +#include "cci_cfg/cci_param_callbacks.h" +#include "cci_core/cci_core_types.h" +#include "cci_core/cci_value.h" + +/** + * @author Guillaume Delbergue, Ericsson / GreenSocs + */ + +CCI_OPEN_NAMESPACE_ + +// Forward declaration +class cci_param_if; + +// CCI Configuration parameter base class +/** +* Type independent base class all cci parameters derive from. +* This class gives some easier access to type independent functions. +*/ +class cci_param_untyped_handle +{ +public: + + /// @name Construction, destruction, assignment + //@{ + /// Constructor to create handle with given originator. + cci_param_untyped_handle(cci_param_if& param, + const cci_originator& originator); + + /// Constructor to create an invalid param handle with given originator. + explicit cci_param_untyped_handle(const cci_originator& originator = cci_originator()); + + /// Copy constructor + cci_param_untyped_handle(const cci_param_untyped_handle& param_handle); + + /// Copy assignment - update handle to refer to a new parameter + cci_param_untyped_handle& + operator=(const cci_param_untyped_handle& param_handle); + +#ifdef CCI_HAS_CXX_RVALUE_REFS + /// Move constructor + cci_param_untyped_handle(cci_param_untyped_handle&& that); + /// Move assignment - update handle to refer to a new parameter + cci_param_untyped_handle& + operator=(cci_param_untyped_handle&& that); +#endif // CCI_HAS_CXX_RVALUE_REFS + + /// Destructor. + ~cci_param_untyped_handle(); + + //@} + + ///@name Description and metadata + ///@{ + + /// @copydoc cci_param_untyped::get_description + virtual std::string get_description() const; + + /// @copydoc cci_param_untyped::get_metadata + cci_value_map get_metadata() const; + + ///@} + + ///@name (Untyped) parameter value access + ///@{ + + /** + * @copydoc cci_param_if::set_cci_value(const cci_value&) + * @note The @c originator is taken from the parameter handle here + */ + void set_cci_value(const cci_value& val); + + /** + * @copydoc cci_param_if::set_cci_value(const cci_value&,const void*) + * @note The @c originator is taken from the parameter handle here + */ + void set_cci_value(const cci_value& val, const void *pwd); + + /** + * @copydoc cci_param_if::get_cci_value(const cci_originator&) + * @note The @c originator is taken from the parameter handle here + */ + cci_value get_cci_value() const; + + /** + * @copydoc cci_param_if::get_default_cci_value + * @note The @c originator is taken from the parameter handle here + */ + cci_value get_default_cci_value() const; + + ///@} + + ///@name Parameter Value Status + ///@{ + + /// @copydoc cci_param_if::is_default_value + virtual bool is_default_value() const; + + + /// @copydoc cci_param_if::is_preset_value + virtual bool is_preset_value() const; + + ///@} + + ///@name Originator queries + ///@{ + + /// @copydoc cci_param_if::get_originator + cci_originator get_originator() const; + + /// @copydoc cci_param_if::get_value_origin + cci_originator get_value_origin() const; + + ///@} + +#define CCI_PARAM_UNTYPED_HANDLE_CALLBACK_DECL_(name) \ + /* @copydoc cci_param_untyped::register_##name##_callback(const cci_param_##name##_callback_untyped, cci_untyped_tag) */ \ + cci_callback_untyped_handle register_##name##_callback( \ + const cci_param_##name##_callback_untyped &cb, \ + cci_untyped_tag = cci_untyped_tag()); \ + \ + /* @copydoc cci_param_untyped::register_##name##_callback(cci_param_##name##_callback_untyped::signature, C*, cci_untyped_tag) */ \ + template \ + cci_callback_untyped_handle register_##name##_callback( \ + cci_param_##name##_callback_untyped::signature (C::*cb), C* obj, \ + cci_untyped_tag = cci_untyped_tag()) \ + { \ + return register_##name##_callback(sc_bind(cb, obj, sc_unnamed::_1)); \ + } \ + \ + /* @copydoc cci_param_untyped::unregister_##name##_callback(const cci_callback_untyped_handle) */ \ + bool unregister_##name##_callback(const cci_callback_untyped_handle &cb); \ + \ + /* TODO: doc */ \ + cci_callback_untyped_handle register_##name##_callback( \ + const cci_callback_untyped_handle& cb, cci_typed_tag) + + /// @name Pre write callback handling + /// @{ + + CCI_PARAM_UNTYPED_HANDLE_CALLBACK_DECL_(pre_write); + + /// @} + + /// @name Post write callback handling + /// @{ + + CCI_PARAM_UNTYPED_HANDLE_CALLBACK_DECL_(post_write); + + /// @} + + /// @name Pre read callback handling + /// @{ + + CCI_PARAM_UNTYPED_HANDLE_CALLBACK_DECL_(pre_read); + + /// @} + + /// @name Post read callback handling + /// @{ + + CCI_PARAM_UNTYPED_HANDLE_CALLBACK_DECL_(post_read); + + /// @} + +#undef CCI_PARAM_UNTYPED_HANDLE_CALLBACK_DECL_ + + /// @name CCI callback handling + /// @{ + + /// @copydoc cci_param_untyped::unregister_all_callbacks + bool unregister_all_callbacks(); + + /// @copydoc cci_param_untyped::has_callbacks + bool has_callbacks() const; + + /// @} + + ///@name Write-access control + ///@{ + + /// @copydoc cci_param_untyped::lock + bool lock(const void* pwd = NULL); + + /// @copydoc cci_param_untyped::unlock + bool unlock(const void* pwd = NULL); + + /// @copydoc cci_param_untyped::is_locked + bool is_locked() const; + + ///@} + + ///@name Query parameter type and name + ///@{ + + /// @copydoc cci_param_typed::get_data_category + cci_param_data_category get_data_category() const; + + /// @copydoc cci_param_untyped::name + const char* name() const; + + /// @copydoc cci_param_typed::get_type_info + const std::type_info& get_type_info() const; + + /// @copydoc cci_param_typed::get_mutable_type + cci_param_mutable_type get_mutable_type() const; + + ///@} + + /** + * @brief Indicates if the handled parameter is valid or not + * @return whether handle currently points to a valid parameter + */ + bool is_valid() const; + + /// Invalidate the parameter handle + /** + * remove the parameter handle from the original + * parameter before invalidating. Otherwise, just invalidate. + */ + void invalidate(); + +protected: + ///@name Type-punned value operations + ///@{ + + /// @copydoc cci_param_typed::get_raw_value + const void* get_raw_value() const; + + /// @copydoc cci_param_typed::get_raw_default_value + const void* get_raw_default_value() const; + + /// @copydoc cci_param_typed::set_raw_value(const void*) + void set_raw_value(const void* vp); + + /// @copydoc cci_param_typed::set_raw_value(const void*, const void*) + void set_raw_value(const void* vp, const void* pwd); + + ///@} + + /// Promote a gifted originator to one that represents the current context + /// when possible (i.e. when within the module hierarchy) + /** + * @param gifted_originator associated with the copy ctor broker argument + * @return context originator if possible; otherwise, the gifted_originator + */ + inline const cci_originator promote_originator(const cci_originator &gifted_originator); + +private: + cci_param_if* m_param; + cci_originator m_originator; + + /// Check handled parameter is valid + /** + * In case the handled parameter is no more valid, it will report an error. + */ + void check_is_valid() const; +}; + +/// Convenience shortcut for untyped parameter handles +typedef cci_param_untyped_handle cci_param_handle ; + + +const cci_originator cci_param_untyped_handle::promote_originator( + const cci_originator &gifted_originator) +{ + if (sc_core::sc_get_current_object()) + return cci_originator(); + else + return gifted_originator; +} + +CCI_CLOSE_NAMESPACE_ + +#endif //CCI_BASE_PARAM_HANDLE_H_INCLUDED_ diff --git a/third_party/cci-1.0.0/cci_cfg/cci_report_handler.cpp b/third_party/cci-1.0.0/cci_cfg/cci_report_handler.cpp new file mode 100644 index 000000000..9adf00451 --- /dev/null +++ b/third_party/cci-1.0.0/cci_cfg/cci_report_handler.cpp @@ -0,0 +1,145 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + ****************************************************************************/ + +#include "cci_cfg/cci_report_handler.h" + +#include // std::strncmp +#include "cci_cfg/cci_config_macros.h" + +CCI_OPEN_NAMESPACE_ + +void +cci_report_handler::report( sc_core::sc_severity severity, const char* msg_type + , const char* msg, const char* file, int line) +{ + std::string cci_msg_type = CCI_SC_REPORT_MSG_TYPE_PREFIX_; + cci_msg_type.append(msg_type); + sc_core::sc_report_handler::report(severity,cci_msg_type.c_str(),msg,file,line); +} + +//functions that throw a report for each cci_param_failure type +void +cci_report_handler::set_param_failed(const char* msg, const char* file, int line) +{ + report(sc_core::SC_ERROR,"SET_PARAM_FAILED",msg,file,line); +} + +void +cci_report_handler::get_param_failed(const char* msg, const char* file, int line) +{ + report(sc_core::SC_ERROR,"GET_PARAM_FAILED",msg,file,line); +} + +void +cci_report_handler::add_param_failed(const char* msg, const char* file, int line) +{ + report(sc_core::SC_ERROR,"ADD_PARAM_FAILED",msg,file,line); +} + +void +cci_report_handler::remove_param_failed(const char* msg, const char* file, int line) +{ + report(sc_core::SC_ERROR,"REMOVE_PARAM_FAILED",msg,file,line); +} + +void +cci_report_handler::cci_value_failure(const char* msg, const char* file, int line) +{ + report(sc_core::SC_ERROR,"CCI_VALUE_FAILURE",msg,file,line); +} + +/* ------------------------------------------------------------------------ */ + +// function to return cci_param_failure that matches thrown (or cached) report +cci_param_failure +cci_report_handler::decode_param_failure(const sc_core::sc_report& rpt) +{ + using namespace std; + static const char cci_msg_type_prefix[] = CCI_SC_REPORT_MSG_TYPE_PREFIX_; + static const size_t cci_msg_type_prefix_len = strlen(cci_msg_type_prefix); + + const char* rpt_msg_type = rpt.get_msg_type(); + + if( strncmp(cci_msg_type_prefix, rpt_msg_type, cci_msg_type_prefix_len) == 0 ) + { + static struct cci_msg_type + { + const char* str; + cci_param_failure val; + } + const cci_msg_types[] = + { + { "SET_PARAM_FAILED", CCI_SET_PARAM_FAILURE }, + { "GET_PARAM_FAILED", CCI_GET_PARAM_FAILURE }, + { "ADD_PARAM_FAILED", CCI_ADD_PARAM_FAILURE }, + { "REMOVE_PARAM_FAILED", CCI_REMOVE_PARAM_FAILURE }, + { "CCI_VALUE_FAILURE", CCI_VALUE_FAILURE }, + { NULL, CCI_UNDEFINED_FAILURE } + }; + + const cci_msg_type* cci_type = cci_msg_types; + const char* msg_type = rpt_msg_type + cci_msg_type_prefix_len; + + for( ; cci_type->str != NULL; ++cci_type ) { + if (strcmp(cci_type->str, msg_type) == 0) + break; + } + return cci_type->val; + } + + //not a CCI failure report + return CCI_NOT_FAILURE; +} + +/* ------------------------------------------------------------------------ */ + +cci_param_failure cci_handle_exception(cci_param_failure expect) +{ + try + { + /*re-*/throw; // current exception + } + catch(const sc_core::sc_report& rpt) + { + cci_param_failure err = cci_report_handler::decode_param_failure(rpt); + + if (err == CCI_NOT_FAILURE) + /*re-*/throw; // unmatched sc_report + + if (err != expect && expect != CCI_ANY_FAILURE) + /*re-*/throw; // unmatched CCI failure + + // OK, found expected error - return error code + return err; + } + // unmatched exceptions will continue to propagate here +} + +/* ------------------------------------------------------------------------ */ + +void cci_abort() +{ +# if CCI_SYSTEMC_VERSION_CODE_ >= CCI_VERSION_HELPER_(2,3,2) + sc_core::sc_abort(); +# else + std::terminate(); +# endif +} + +CCI_CLOSE_NAMESPACE_ diff --git a/third_party/cci-1.0.0/cci_cfg/cci_report_handler.h b/third_party/cci-1.0.0/cci_cfg/cci_report_handler.h new file mode 100644 index 000000000..764e26ee0 --- /dev/null +++ b/third_party/cci-1.0.0/cci_cfg/cci_report_handler.h @@ -0,0 +1,147 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + ****************************************************************************/ + +#ifndef CCI_CCI_REPORT_HANDLER_H_INCLUDED_ +#define CCI_CCI_REPORT_HANDLER_H_INCLUDED_ + +#include "cci_core/cci_cmnhdr.h" + +CCI_OPEN_NAMESPACE_ + +enum cci_param_failure +{ + CCI_NOT_FAILURE = 0, + + CCI_SET_PARAM_FAILURE, + CCI_GET_PARAM_FAILURE, + CCI_ADD_PARAM_FAILURE, + CCI_REMOVE_PARAM_FAILURE, + CCI_VALUE_FAILURE, + CCI_UNDEFINED_FAILURE, + + CCI_ANY_FAILURE = CCI_UNDEFINED_FAILURE +}; + +/* ------------------------------------------------------------------------ */ + +class cci_report_handler : public sc_core::sc_report_handler +{ +public: + static void report( sc_core::sc_severity severity + , const char* msg_type, const char* msg + , const char* file, int line); + + //functions that throw a report for each cci_param_failure type + static void + set_param_failed(const char* msg="", const char* file=NULL, int line = 0); + + static void + get_param_failed(const char* msg="", const char* file=NULL, int line = 0); + + static void + add_param_failed(const char* msg="", const char* file=NULL, int line = 0); + + static void + remove_param_failed(const char* msg="", const char* file=NULL, int line = 0); + + static void + cci_value_failure(const char* msg="", const char* file=NULL, int line = 0); + + // function to return cci_param_failure that matches thrown (or cached) report + static cci_param_failure + decode_param_failure(const sc_core::sc_report& rpt); + +}; // class cci_report_handler + +/* ------------------------------------------------------------------------ */ + +/** + * Helper function to handle CCI parameter failure exceptions + * + * @param expect A cci_param_failure category to handle (default: CCI_ANY_FAILURE) + * @return Current cci_param_failure (if matching expect), rethrows otherwise + * + * This function inspects the currently active exception and compares it against + * an expected cci_param_failure value. If the current exception is @b not + * a CCI failure (or doesn't match the expected value), the exception is rethrown. + * Otherwise, the decoded param failure is returned. + * + * @note This function must be called within a @c catch clause, i.e. there has + * to be a currently active exception - usually an @ref sc_core::sc_report + * + * @b Example + * \code + * try { + * cci::cci_value val; // null value + * val.get_string(); // invalid cci_value access + * } catch (...) { + * cci::cci_param_failure err = cci::cci_handle_exception(); + * SC_REPORT_WARNING( "Example/Warning", "Caught CCI param failure"); + * sc_assert( err == CCI_VALUE_FAILURE ); + * } + * \endcode + * + * @see cci_report_handler::decode_param_failure + */ +cci_param_failure +cci_handle_exception(cci_param_failure expect = CCI_ANY_FAILURE); + +/* ------------------------------------------------------------------------ */ +// cci_abort - abort simulation after irrecoverable error + +#if CCI_CPLUSPLUS >= 201103L && (!defined(_MSC_VER) || _MSC_VER >= 1900) +// C++11: use standard C++ attribute +# define CCI_NORETURN_ [[noreturn]] +#else +# if defined(_MSC_VER) +# define CCI_NORETURN_ __declspec(noreturn) +# elif defined(__GNUC__) || defined(__MINGW32__) || defined(__clang__) +# define CCI_NORETURN_ __attribute__((noreturn)) +# else +# define CCI_NORETURN_ /* nothing */ +# endif +#endif // CCI_NORETURN_ + +/// abort simulation +CCI_NORETURN_ void cci_abort(); + +#undef CCI_NORETURN_ + +/* ------------------------------------------------------------------------ */ +// CCI report macro helpers + +#define CCI_REPORT_INFO(_id, _message) \ + CCI_NAMESPACE::cci_report_handler:: \ + report(sc_core::SC_INFO,_id,_message,__FILE__,__LINE__) + +#define CCI_REPORT_WARNING(_id, _message) \ + CCI_NAMESPACE::cci_report_handler:: \ + report(sc_core::SC_WARNING,_id,_message,__FILE__,__LINE__) + +#define CCI_REPORT_ERROR(_id, _message) \ + CCI_NAMESPACE::cci_report_handler:: \ + report(sc_core::SC_ERROR,_id,_message,__FILE__,__LINE__) + +#define CCI_REPORT_FATAL(_id, _message) \ + CCI_NAMESPACE::cci_report_handler:: \ + report(sc_core::SC_FATAL,_id,_message,__FILE__,__LINE__) + +CCI_CLOSE_NAMESPACE_ + +#endif // CCI_CFG_CCI_REPORT_HANDLER_H_INCLUDED_ diff --git a/third_party/cci-1.0.0/cci_configuration b/third_party/cci-1.0.0/cci_configuration new file mode 100644 index 000000000..070f9fb9e --- /dev/null +++ b/third_party/cci-1.0.0/cci_configuration @@ -0,0 +1,42 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + ****************************************************************************/ + +#ifndef CCI_CCI_HEADER_INCLUDED_ +#define CCI_CCI_HEADER_INCLUDED_ + +// CCI core includes + +#include "cci_core/cci_version.h" +#include "cci_core/cci_name_gen.h" +#include "cci_core/cci_core_types.h" +#include "cci_core/cci_value.h" +#include "cci_core/cci_value_converter.h" + +// CCI config includes + +#include "cci_cfg/cci_mutable_types.h" +#include "cci_cfg/cci_originator.h" +#include "cci_cfg/cci_broker_handle.h" +#include "cci_cfg/cci_broker_if.h" +#include "cci_cfg/cci_broker_manager.h" +#include "cci_cfg/cci_param_typed.h" +#include "cci_cfg/cci_param_typed_handle.h" +#include "cci_cfg/cci_macros_undef.h" + +#endif // CCI_CCI_HEADER_INCLUDED_ diff --git a/third_party/cci-1.0.0/cci_core/cci_callback.h b/third_party/cci-1.0.0/cci_core/cci_callback.h new file mode 100644 index 000000000..8a43c5d0f --- /dev/null +++ b/third_party/cci-1.0.0/cci_core/cci_callback.h @@ -0,0 +1,425 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + ****************************************************************************/ + +/** +* \file cci_callback.h +* \author Philipp A. Hartmann, Intel +* \author Enrico Galli, Intel +* \brief Callback interface classes +*/ + +#ifndef CCI_CORE_CCI_CALLBACK_H_INCLUDED_ +#define CCI_CORE_CCI_CALLBACK_H_INCLUDED_ + +#include // std::swap +#include "cci_core/cci_cmnhdr.h" + +CCI_OPEN_NAMESPACE_ + +// forward declarations + +template +class cci_callback; + +class cci_callback_untyped_handle; + +template +class cci_callback_typed_handle; + +CCI_CLOSE_NAMESPACE_ + +// include here to propagate forward declarations +#include "cci_core/cci_callback_impl.h" + +CCI_OPEN_NAMESPACE_ + +/* ------------------------------------------------------------------------ */ + +/** + * \brief Callback wrapper class + * \tparam ArgType Type of the (single) callback argument + * \tparam ResultType Return type of the callback (default: \c void) + * + * This class provides a simple callback wrapper for any callable object + * of the signature + * \code + * ResultType ( ArgType ) + * \endcode + * + * As a special extension, callbacks can have a "generalization" relationship: + * If the matching \ref cci_callback_traits template's boolean + * member \ref is_generalizable equals to \c true and the nested types + * \li \c generic_type + * \li \c generic_wrap + * exist, cci_callback instances of the signature + * \code + * ResultType (Traits::generic_type) + * \endcode + * can be wrapped and calls are automatically forwarded to these callbacks + * appropriately. + * + * \see cci_callback_untyped_handle, cci_callback_typed_handle + * \todo Add support for callbacks without payloads (\c ArgType ==\c void) + */ +template +class cci_callback +{ + template friend class cci_callback; + friend class cci_callback_untyped_handle; //; + typedef cci_callback_traits traits; + +public: + typedef cci_callback type; + typedef ResultType signature(ArgType); + + cci_callback(const cci_callback& cb) + : m_cb(cb.m_cb ? cb.m_cb->clone() : NULL) + {} + +#ifdef CCI_HAS_CXX_RVALUE_REFS + cci_callback(cci_callback&& cb) + : m_cb(cb.m_cb) + { + cb.m_cb = NULL; + } +#endif // CCI_HAS_CXX_RVALUE_REFS + + /// construction from a "generalized" callback + template< typename T > + cci_callback( const cci_callback& cb +#ifndef CCI_DOXYGEN_IS_RUNNING + , typename cci_impl::enable_if< + cci_impl::callback_is_generalized::value + >::type* = NULL +#endif // CCI_DOXYGEN_IS_RUNNING + ) + : m_cb( new cci_impl::callback_generic_adapt(cb.m_cb) ) + {} + + cci_callback& operator=(cci_callback copy) + { + copy.swap(*this); + return *this; + } + + /// construction from a functor + template< typename C + // TODO: Add is_callable restriction, see e.g. + // http://talesofcpp.fusionfenix.com/post-11/true-story-call-me-maybe + > + cci_callback( C c ) + : m_cb( new cci_impl::callback_impl(CCI_MOVE_(c)) ) + {} + + void swap(cci_callback& that) + { + using std::swap; + swap(m_cb, that.m_cb); + } + + /// invoke callback + ResultType operator()(ArgType arg) const + { + sc_assert( m_cb ); // can only happen in "moved-from" state + // TODO: add perfect forwarding + return m_cb->invoke(arg); + } + + ~cci_callback() + { + if (m_cb) + m_cb->release(); + } + +private: + typedef cci_impl::callback_typed_if impl_if; + impl_if* m_cb; +}; + +/* ------------------------------------------------------------------------ */ + +/** + * \brief Generic callback handle class + * + * This class provides a generic callback handle to store arbitrary callback + * instances (returning a the corresponding return type). + * + * The held callback can be invoked explicity via the two template functions + * \li \ref cci_callback_untyped_handle::invoke + * \li \ref cci_callback_untyped_handle::unchecked_invoke + * + * The lifetime of the held callback is extended until the last handle + * instance pointing to the underlying callback object is destroyed + * (shared ownership). + * + * \see cci_callback, cci_callback_typed_handle + */ +class cci_callback_untyped_handle +{ +public: + /// C++03 compatibility typedef + typedef cci_callback_untyped_handle type; + + /// default constructor - creates invalid handle + cci_callback_untyped_handle() : m_cb() {} + + /** + * \brief Obtain a handle from a callback instance + * \tparam ArgType Argument type / signature of the callback + * \param cb Callback to obtain handle from + */ + template + cci_callback_untyped_handle( const cci_callback& cb ) + : m_cb(cb.m_cb) + { + if (m_cb) + m_cb->acquire(); + } + + /// Copy constructor - both handles point to the same callback object + cci_callback_untyped_handle(const cci_callback_untyped_handle& that) + : m_cb(that.m_cb) + { + if (m_cb) + m_cb->acquire(); + } + + /// Assignment - both handles point to the same callback object + cci_callback_untyped_handle& operator=(const cci_callback_untyped_handle& that) + { + cci_callback_untyped_handle copy(that); + copy.swap(*this); + return *this; + } + + /// Exchange contents of two untyped callback handles + void swap(type& that) + { + using std::swap; + swap(m_cb, that.m_cb); + } + + ~cci_callback_untyped_handle() + { + if (m_cb) + m_cb->release(); + } + + /// check, if handle currently holds a callback + bool valid() const + { return m_cb != NULL; } + + /** + * \brief check, if handle currently holds a callback with the given signature + * \tparam ResultType Return type of the wrapped callback + * \tparam ArgType Argument type of the wrapped callback + */ + template + bool valid() const; + + /// clear held callback + void clear() + { reset(NULL); } + + /** + * \brief invoke callback with given signature + * \tparam ResultType Return type of the wrapped callback + * \tparam ArgType Argument type of the wrapped callback + * + * On valid handles, this function invokes the held callback after + * checing that the expected signature matches. + * + * \throw sc_core::sc_report + * \todo Document error case. + * + * \see cci_callback_untyped_handle::unchecked_invoke + */ + template + ResultType invoke(ArgType arg) const; + + /** + * \brief invoke callback with given signature + * \tparam ResultType Return type of the wrapped callback + * \tparam ArgType Argument type of the wrapped callback + * + * On valid handles, this function invokes the held callback + * \b without checking that the expected signature matches. + * + * \warning If the held callback expects a different signature, + * the behavior is undefined. + * + * \see cci_callback_untyped_handle::invoke + */ + template + ResultType unchecked_invoke(ArgType arg) const; + + /// compare two handles + bool operator==( const cci_callback_untyped_handle& that ) const + { + return get() == that.get(); + } + +protected: + const cci_impl::callback_untyped_if * get() const + { + if (m_cb) + return m_cb->get(); + return NULL; + } + + void reset(cci_impl::callback_untyped_if* cb) + { + if (m_cb) m_cb->release(); + m_cb = cb; + if (m_cb) m_cb->acquire(); + } + +private: + cci_impl::callback_untyped_if * m_cb; +}; + +/* ------------------------------------------------------------------------ */ + +/** + * \brief Typed callback handle class + * \tparam ArgType Type of the (single) callback argument + * \tparam ResultType Return type of the wrapped callback (default: \c void) + * + * This class provides a typed callback handle to store arbitrary callback + * instances (returning a the corresponding return type). + * + * The held callback can be invoked explicity via the + * \ref cci_callback_typed_handle::invoke function. + * + * The lifetime of the held callback is extended until the last handle + * instance pointing to the underlying callback object is destroyed + * (shared ownership). + * + * \see cci_callback, cci_callback_untyped_handle + */ +template +class cci_callback_typed_handle + : public cci_callback_untyped_handle +{ + typedef cci_callback_untyped_handle base_type; + typedef cci_callback cb_type; + + // disallow untyped/templated overloads + using base_type::invoke; + using base_type::unchecked_invoke; + +public: + /// C++03 compatibility typedef + typedef cci_callback_typed_handle type; + + /// default constructor - creates invalid handle + cci_callback_typed_handle() + : base_type() {} + + /// construct from a callback instance + cci_callback_typed_handle(const cb_type& cb) + : base_type(cb) {} + + /** + * \brief Construct from an untyped callback handle, iff signature matches + * + * This constructor is used for type recovery from untyped handles. + * If the underlying signature of the source handle matches the + * expected signature of the typed handle, the conversion is successful + * and the constructed handle is valid. + * + * Otherwise, an invalid handle is constructed. + */ + explicit cci_callback_typed_handle(const base_type& cb); + + /** + * \brief invoke the held callback + * \see cci_callback_untyped_handle::invoke + */ + ResultType invoke(ArgType arg) const; +}; + +/* ------------------------------------------------------------------------ */ + +template +bool +cci_callback_untyped_handle::valid() const +{ + typedef cci_callback_traits traits; + typedef cci_impl::callback_typed_if if_type; + return m_cb && dynamic_cast(m_cb); +} + +template +ResultType +cci_callback_untyped_handle::invoke(ArgType arg) const +{ + typedef cci_callback_traits traits; + typedef cci_impl::callback_typed_if if_type; + const if_type* typed_cb = dynamic_cast(m_cb); + + sc_assert( m_cb ); /// \todo Add proper error handling + sc_assert( typed_cb ); + return typed_cb->invoke(arg); /// \todo [cxx11] add perfect forwarding +} + +template +ResultType +cci_callback_untyped_handle::unchecked_invoke(ArgType arg) const +{ + typedef cci_callback_traits traits; + typedef cci_impl::callback_typed_if if_type; + + sc_assert( m_cb ); /// \todo Add proper error handling + const if_type* typed_cb = static_cast(m_cb); + return typed_cb->invoke(arg); /// \todo [cxx11] add perfect forwarding +} + +/* ------------------------------------------------------------------------ */ + +template +cci_callback_typed_handle:: + cci_callback_typed_handle(const cci_callback_untyped_handle& cb) + : base_type(cb) +{ + if (!this->valid()) // invalid source + return; + + if (this->template valid()) // matching source + return; + + // check, if convertible from a generic handle + typedef cci_callback_traits traits; + cci_impl::callback_untyped_if* cb_adapt + = cci_impl::callback_generic_adapt::convert(this->get()); + this->reset(cb_adapt); + if (cb_adapt) cb_adapt->release(); +} + +template +ResultType +cci_callback_typed_handle::invoke(ArgType arg) const +{ + /// \todo [cxx11] add perfect forwarding + return base_type::template unchecked_invoke(arg); +} + +CCI_CLOSE_NAMESPACE_ + +#endif // CCI_CORE_CCI_CALLBACK_H_INCLUDED_ diff --git a/third_party/cci-1.0.0/cci_core/cci_callback_impl.h b/third_party/cci-1.0.0/cci_core/cci_callback_impl.h new file mode 100644 index 000000000..9f7febdc4 --- /dev/null +++ b/third_party/cci-1.0.0/cci_core/cci_callback_impl.h @@ -0,0 +1,240 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + ****************************************************************************/ + +/** +* \file cci_callback_impl.h +* \author Philipp A. Hartmann, Intel +* \brief Callback implementation classes +* +* \note Any classes defined in the \ref cci::cci_impl namespace +* are not part of the CCI standard. +*/ +#ifndef CCI_CORE_CCI_CALLBACK_IMPL_H_INCLUDED_ +#define CCI_CORE_CCI_CALLBACK_IMPL_H_INCLUDED_ + +#include "cci_core/cci_cmnhdr.h" +#include "cci_core/cci_meta.h" + +CCI_OPEN_NAMESPACE_ +///@cond CCI_HIDDEN_FROM_DOXYGEN +namespace cci_impl { + +/// implementation-defined helper to define default callback traits +template +struct callback_traits +{ + typedef ArgType argument_type; + typedef ResultType result_type; + + static const bool is_generalizable = false; +}; + +/// implementation-defined helper to define generalizable callback traits +template +class callback_traits::type::generic_type + >::type +> +{ + typedef typename cci_impl::remove_reference::type nonref_argtype; +public: + typedef ArgType argument_type; + typedef ResultType result_type; + + typedef typename nonref_argtype::generic_type generic_type; + typedef typename nonref_argtype::generic_wrap generic_wrap; + + static const bool is_generalizable = true; +}; + +} // namespace cci_impl +///@endcond + +/// default callback traits +template +struct cci_callback_traits + : cci_impl::callback_traits {}; + +/* ------------------------------------------------------------------------ */ + +///@cond CCI_HIDDEN_FROM_DOXYGEN +namespace cci_impl { + +struct callback_untyped_if +{ + virtual void acquire() = 0; + virtual void release() = 0; + + virtual callback_untyped_if* clone() const = 0; + virtual ~callback_untyped_if() {} + + virtual const callback_untyped_if* get() const + { return this; } + +protected: + callback_untyped_if() {} + +private: + callback_untyped_if(const callback_untyped_if&) /* = delete */; + callback_untyped_if& operator=(const callback_untyped_if&) /* = delete */; +}; // callback_untyped_if + +template +struct callback_typed_if + : callback_untyped_if // +{ + typedef typename Traits::result_type result_type; + typedef typename Traits::argument_type argument_type; + + virtual result_type invoke(argument_type) const = 0; + + virtual callback_typed_if* clone() const = 0; + virtual ~callback_typed_if(){} + +}; // callback_typed_if + +/* ------------------------------------------------------------------------ */ + +/// Implementation of a callback +template +struct callback_impl + : callback_typed_if +{ + typedef callback_typed_if if_type; + typedef typename if_type::argument_type argument_type; + typedef typename if_type::result_type result_type; + + explicit callback_impl(const Functor& f) + : m_func(f), m_refcnt(1) {} + +#ifdef CCI_HAS_CXX_RVALUE_REFS + explicit callback_impl(Functor&& f) + : m_func(CCI_MOVE_(f)), m_refcnt(1) {} +#endif // CCI_HAS_CXX_RVALUE_REFS + + virtual result_type invoke(argument_type arg) const + { + return m_func(arg); + } + + virtual callback_impl* clone() const + { return new callback_impl(m_func); } + + virtual void acquire() { ++m_refcnt; } + virtual void release() { if (!--m_refcnt) delete this; } + +protected: + Functor m_func; + unsigned m_refcnt; +}; // callback_impl + +/* ------------------------------------------------------------------------ */ + +template +struct callback_is_generalized; + +template +struct callback_is_generalized + : false_type {}; + +template +struct callback_is_generalized + : is_same {}; + +/* ------------------------------------------------------------------------ */ + +/// Implementation of a generic callback adapter +template +struct callback_generic_adapt; + +template +struct callback_generic_adapt + : callback_untyped_if +{ + static callback_untyped_if* convert( const callback_untyped_if* ) + { return NULL; } + +private: + void acquire() {} + void release() {} + callback_untyped_if* clone() const { return NULL; } +}; + +template +struct callback_generic_adapt + : callback_typed_if +{ + typedef typename Traits::argument_type argument_type; + typedef typename Traits::result_type result_type; + typedef typename Traits::generic_type generic_type; + + typedef cci_callback_traits generic_traits; + typedef callback_typed_if if_type; + + static callback_untyped_if* convert( const callback_untyped_if* f ) + { + if (!f) + return NULL; + + // is this a generalized callback instance? + const if_type* typed_if = dynamic_cast(f); + if (typed_if) + return new callback_generic_adapt( const_cast(typed_if) ); + + return NULL; + } + + explicit callback_generic_adapt(if_type* f) + : m_func(f), m_refcnt(1) + { + m_func->acquire(); + } + + virtual result_type invoke(argument_type arg) const + { + // convert to generic argument and call functor + return m_func->invoke( typename Traits::generic_wrap(arg).get() ); + } + + virtual void acquire() { ++m_refcnt; } + virtual void release() { if (!--m_refcnt) delete this; } + + virtual const callback_untyped_if* get() const + { return m_func->get(); } + + virtual callback_generic_adapt* clone() const + { return new callback_generic_adapt(m_func->clone()); } + +protected: + ~callback_generic_adapt() + { + m_func->release(); + } + + if_type* m_func; + unsigned m_refcnt; +}; + +} // namespace cci_impl +///@endcond +CCI_CLOSE_NAMESPACE_ + +#endif // CCI_CORE_CCI_CALLBACK_IMPL_H_INCLUDED_ diff --git a/third_party/cci-1.0.0/cci_core/cci_cmnhdr.h b/third_party/cci-1.0.0/cci_core/cci_cmnhdr.h new file mode 100644 index 000000000..bf5c045f8 --- /dev/null +++ b/third_party/cci-1.0.0/cci_core/cci_cmnhdr.h @@ -0,0 +1,144 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + ****************************************************************************/ + +/** + * \file cci_cmnhdr.h + * \brief Some platform helpers other implementation-defined parts + * + * @author Enrico Galli, Intel + * @author Philipp A. Hartmann, Intel + * + * \note The contents of this file are entirely implementation-defined. + */ +#ifndef CCI_CORE_CCI_CMNHDR_H_INCLUDED_ +#define CCI_CORE_CCI_CMNHDR_H_INCLUDED_ + +#include "cci_core/systemc.h" + +/** + * @def CCI_NAMESPACE + * @brief Main CCI namespace (overridable) + * @hideinitializer + * @see cci + */ +#ifndef CCI_NAMESPACE +# define CCI_NAMESPACE cci +#endif // CCI_NAMESPACE + +/// Opening a CCI namespace block (internal) +# define CCI_OPEN_NAMESPACE_ namespace CCI_NAMESPACE { +/// Closing a CCI namespace block (internal) +# define CCI_CLOSE_NAMESPACE_ } /* namespace cci */ + +/* ------------------------------------------------------------------------ */ + +/** @namespace cci + * @brief Accellera Configuration, Control & Inspection (CCI) standard + */ + +/** @namespace cci_utils + * @brief CCI utilities (not part of the interoperability standard) + */ + +/* ------------------------------------------------------------------------ */ + +/** + * @def CCI_CPLUSPLUS + * @brief Selected C++ standard baseline + * @hideinitializer + * + * This macro can be used inside the library sources to make certain assumptions + * on the available features in the underlying C++ implementation. + * + * Supported values are + * @li @c 199711L (C++03, ISO/IEC 14882:1998, 14882:2003) + * @li @c 201103L (C++11, ISO/IEC 14882:2011) + * @li @c 201402L (C++14, ISO/IEC 14882:2014) + * @li @c 201703L (C++17, ISO/IEC 14882:2017) + * + * Starting with SystemC 2.3.2, this value should match the @c SC_CPLUSPLUS + * macro in order to build compatible models. + */ +#ifndef CCI_CPLUSPLUS +# ifdef SC_CPLUSPLUS // as defined by SystemC >= 2.3.2 +# define CCI_CPLUSPLUS SC_CPLUSPLUS +# else // copy deduction from SystemC 2.3.2 + +# ifdef _MSC_VER // don't rely on __cplusplus for MSVC + // Instead, we select the C++ standard with reasonable support. + // If some features still need to be excluded on specific MSVC + // versions, we'll do so at the point of definition. + +# if defined(_MSVC_LANG) // MSVC'2015 Update 3 or later, use compiler setting +# define CCI_CPLUSPLUS _MSVC_LANG +# elif _MSC_VER < 1800 // MSVC'2010 and earlier, assume C++03 +# define CCI_CPLUSPLUS 199711L +# elif _MSC_VER < 1900 // MSVC'2013, assume C++11 +# define CCI_CPLUSPLUS 201103L +# else // MSVC'2015 before Update 3, assume C++14 +# define CCI_CPLUSPLUS 201402L +# endif +# else // not _MSC_VER + // use compiler setting +# define CCI_CPLUSPLUS __cplusplus +# endif // not _MSC_VER + +# endif // not SC_CPLUSPLUS +#endif // CCI_CPLUSPLUS + +/* ------------------------------------------------------------------------ */ + +// Macros to check if certain C++ features are supported +#ifndef __has_feature // Optional of course. +# define __has_feature(x) 0 // Compatibility with non-clang compilers. +#endif +#ifndef __has_extension +# define __has_extension __has_feature // Compatibility with pre-3.0 compilers. +#endif + +/* ------------------------------------------------------------------------ */ +// Support for C++ rvalue-references / perfect forwarding + +#ifndef CCI_HAS_CXX_RVALUE_REFS +# if CCI_CPLUSPLUS >= 201103L +# define CCI_HAS_CXX_RVALUE_REFS +# endif +#endif // detect: CCI_HAS_CXX_RVALUE_REFS + +#ifdef CCI_HAS_CXX_RVALUE_REFS +# include +# define CCI_MOVE_(Obj)::std::move(Obj) +# define CCI_FORWARD_(Type,Obj) ::std::forward(Obj) +#else +# define CCI_MOVE_(Obj) Obj +# define CCI_FORWARD_(Type,Obj) Obj +#endif // CCI_HAS_CXX_RVALUE_REFS + +/* ------------------------------------------------------------------------ */ +// Extern templates (supported by all major compilers even before C++11) + +#ifndef CCI_TPLEXTERN_ +# if defined(__GNUC__) && CCI_CPLUSPLUS < 201103L +# define CCI_TPLEXTERN_ __extension__ extern +# else +# define CCI_TPLEXTERN_ extern +# endif +#endif // CCI_TPLEXTERN_ + +#endif // CCI_CORE_CCI_CMNHDR_H_INCLUDED_ diff --git a/third_party/cci-1.0.0/cci_core/cci_core_types.h b/third_party/cci-1.0.0/cci_core/cci_core_types.h new file mode 100644 index 000000000..d82dcc274 --- /dev/null +++ b/third_party/cci-1.0.0/cci_core/cci_core_types.h @@ -0,0 +1,60 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + ****************************************************************************/ + +#ifndef CCI_CCI_CORE_TYPES_H_INCLUDED_ +#define CCI_CCI_CORE_TYPES_H_INCLUDED_ + +#include "cci_core/cci_cmnhdr.h" + +CCI_OPEN_NAMESPACE_ + +/** + * Enumeration for basic parameter data types, whose rough getting and setting + * is supported directly. + */ +enum cci_param_data_category { + /// Boolean valued parameter + CCI_BOOL_PARAM, + /// Integer number valued parameter + CCI_INTEGRAL_PARAM, + /// Real number valued parameter + CCI_REAL_PARAM, + /// String valued parameter + CCI_STRING_PARAM, + /// List valued parameter + CCI_LIST_PARAM, + /// Parameter with values of any other type (objects etc.) + CCI_OTHER_PARAM +}; + +/** + * Enumeration for convenient cci_param_typed constructor. + * Choose if a param gets a relative or an absolute name. + */ +enum cci_name_type { + /// Relative name + CCI_RELATIVE_NAME, + /// Absolute name + CCI_ABSOLUTE_NAME +}; + +CCI_CLOSE_NAMESPACE_ + +#endif + diff --git a/third_party/cci-1.0.0/cci_core/cci_filtered_range.h b/third_party/cci-1.0.0/cci_core/cci_filtered_range.h new file mode 100644 index 000000000..5137a8280 --- /dev/null +++ b/third_party/cci-1.0.0/cci_core/cci_filtered_range.h @@ -0,0 +1,236 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + ****************************************************************************/ + +#ifndef CCI_CORE_CCI_FILTERED_RANGE_H_INCLUDED_ +#define CCI_CORE_CCI_FILTERED_RANGE_H_INCLUDED_ + +/** + * @author Guillaume Delbergue, Ericsson / GreenSocs + */ + +#include + +#include "cci_core/cci_cmnhdr.h" + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4355) // 'this' : used in base member initializer list +#endif // _MSC_VER + +CCI_OPEN_NAMESPACE_ + +/** + * @class cci_filtered_range + * @brief CCI filtered range class + * + * The filtered range class allows to iterate over a range skipping some + * elements lazily. A predicate controls elements which are skipped. + */ +template > +class cci_filtered_range +{ +public: + typedef typename Container::reference reference; + typedef typename Container::const_reference const_reference; + typedef typename Container::reference pointer; + typedef typename Container::const_reference const_pointer; + +private: + typedef typename Container::iterator container_iterator; + + /// internal implementation class (implementation-defined) + template + class iterator_impl + { + friend class cci_filtered_range; + + public: + typedef std::bidirectional_iterator_tag iterator_category; + typedef typename BaseIterator::value_type value_type; + typedef typename BaseIterator:: difference_type difference_type; + typedef typename BaseIterator:: pointer pointer; + typedef typename BaseIterator:: reference reference; + + iterator_impl(): + m_current(), + m_fr(NULL) + {}; + + private: + iterator_impl(container_iterator it): + m_current(it), + m_fr(NULL) + {}; + + iterator_impl(container_iterator it, const cci_filtered_range* fr): + m_current(it), + m_fr(fr) + {}; + + public: + iterator_impl& operator--() { + decrement(); + return *this; + } + + iterator_impl& operator++() { + increment(); + return *this; + } + + iterator_impl operator--(int) { + iterator_impl ret = *this; + decrement(); + return ret; + } + + iterator_impl operator++(int) { + iterator_impl ret = *this; + increment(); + return ret; + } + + reference operator*() const { + return *m_current; + } + + pointer operator->() const { + return &(*m_current); + } + + bool operator==(const iterator_impl& it) const { + return m_current == it.m_current; + } + + bool operator!=(const iterator_impl& it) const { + return !(*this == it); + } + + private: + void increment() { + if(m_fr) { + if(m_current != m_fr->m_container.end()) { + ++m_current; + } + while((m_current != m_fr->m_container.end()) + && (!m_fr->m_pred(*(m_current)))) { + ++m_current; + } + } + } + + void decrement() { + if(m_fr) { + if(m_current != m_fr->m_begin) { + --m_current; + } + while((m_current != m_fr->m_begin) + && (!m_fr->m_pred(*(m_current)))) { + --m_current; + } + } + } + + container_iterator m_current; + const cci_filtered_range* m_fr; + }; + +public: + typedef iterator_impl iterator; + typedef iterator_impl const_iterator; + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; + + cci_filtered_range(const Predicate& pred, + const Container& container): + m_pred(pred), + m_container(container), + m_begin(m_container.begin(), this) + { + init(); + } + + iterator begin() { + return m_begin; + } + + iterator end() { + return m_container.end(); + } + + const_iterator begin() const { + const_iterator it(m_begin.m_current, this); + return it; + } + + const_iterator end() const { + return m_container.end(); + } + + const_iterator cbegin() const { + return begin(); + } + + const_iterator cend() const { + return end(); + } + + reverse_iterator rbegin() { + return reverse_iterator(iterator(m_container.end(), this)); + } + + const_reverse_iterator rbegin() const { + return crbegin(); + } + + const_reverse_iterator crbegin() const { + return const_reverse_iterator(const_iterator(m_container.end(), this)); + } + + reverse_iterator rend() { + return reverse_iterator(iterator(m_begin.m_current, this)); + } + + const_reverse_iterator rend() const { + return crend(); + } + + const_reverse_iterator crend() const { + return const_reverse_iterator(const_iterator(m_begin.m_current, this)); + } + +public: + void init() { + if ((m_begin != end()) && (!m_pred(*m_begin))) { + ++m_begin; // Internally call increment() to setup the invariant + } + } + + Predicate m_pred; + Container m_container; + iterator m_begin; +}; + +CCI_CLOSE_NAMESPACE_ + +#ifdef _MSC_VER +#pragma warning(pop) +#endif // _MSC_VER + +#endif // CCI_CORE_CCI_FILTERED_RANGE_H_INCLUDED_ diff --git a/third_party/cci-1.0.0/cci_core/cci_meta.h b/third_party/cci-1.0.0/cci_core/cci_meta.h new file mode 100644 index 000000000..5afbd77de --- /dev/null +++ b/third_party/cci-1.0.0/cci_core/cci_meta.h @@ -0,0 +1,90 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + ****************************************************************************/ + +/** + * \file cci_meta.h + * \author Philipp A. Hartmann, Intel + * \brief Some template meta-programming helpers + * + * \note Only \ref cci::cci_tag et.al. are part of the standard. + */ +#ifndef CCI_CORE_CCI_META_H_INCLUDED_ +#define CCI_CORE_CCI_META_H_INCLUDED_ + +#include "cci_core/cci_cmnhdr.h" +#include "cci_core/systemc.h" + +#if CCI_CPLUSPLUS >= 201103L +# include +#endif + +CCI_OPEN_NAMESPACE_ + +/// Typed tag class +template struct cci_tag { typedef T type; }; + +/// Explicitly typed tag class +template struct cci_typed_tag : cci_tag {}; + +/// Tag alias for an untyped tag +typedef cci_tag cci_untyped_tag; + +///@cond CCI_HIDDEN_FROM_DOXYGEN +namespace cci_impl { + +#if CCI_CPLUSPLUS >= 201103L +using std::enable_if; +using std::integral_constant; +using std::true_type; +using std::false_type; +using std::is_same; +using std::remove_reference; + +#else // use Boost/local implementation for type traits + +template +struct enable_if : sc_boost::enable_if_c {}; + +/// A type encoding for an integral value +template struct integral_constant +{ + typedef IntegralType value_type; + typedef integral_constant type; + static const value_type value = V; +}; + +typedef integral_constant true_type; +typedef integral_constant false_type; + +template struct is_same : false_type {}; +template struct is_same : true_type {}; + +template struct remove_reference { typedef T type; }; +template struct remove_reference { typedef T type; }; + +#endif // CCI_CPLUSPLUS >= 201103L + +/// C++03 implementation of std::void_t (from C++17) +template struct always_void { typedef void type; }; + +} // namespace cci_impl +///@endcond +CCI_CLOSE_NAMESPACE_ + +#endif // CCI_CORE_CCI_META_H_INCLUDED_ diff --git a/third_party/cci-1.0.0/cci_core/cci_name_gen.cpp b/third_party/cci-1.0.0/cci_core/cci_name_gen.cpp new file mode 100644 index 000000000..962442b9c --- /dev/null +++ b/third_party/cci-1.0.0/cci_core/cci_name_gen.cpp @@ -0,0 +1,124 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + ****************************************************************************/ + +#include "cci_core/cci_name_gen.h" + +#include +#include +#include + +#include "cci_cfg/cci_report_handler.h" + +CCI_OPEN_NAMESPACE_ + +#if CCI_SYSTEMC_VERSION_CODE_ < CCI_VERSION_HELPER_(2,3,2) +enum cci_name_state { + cci_name_free, + cci_name_used +}; + +std::map >& +cci_get_cci_unique_names() +{ + /// CCI unique names map used when SystemC < 2.3.2 + static std::map > + cci_unique_names; + return cci_unique_names; +} +#endif + +#define CCI_NAME_CONFLICT_WITH_SYSTEMC_WARNING_(old_name, new_name) \ + std::stringstream msg; \ + msg << name << " is already used in the SystemC hierarchy, using " \ + << new_name << " instead"; \ + CCI_REPORT_WARNING("cci_name_gen/gen_unique_name", msg.str().c_str()) + +const char* cci_gen_unique_name(const char *name) +{ + if(!name || !*name) { + CCI_REPORT_ERROR("cci_name_gen/gen_unique_name", + "empty name is not allowed"); + cci_abort(); // cannot recover from here + } +#if CCI_SYSTEMC_VERSION_CODE_ >= CCI_VERSION_HELPER_(2,3,2) + if (!sc_core::sc_register_hierarchical_name(name)) { + const char* new_name = sc_core::sc_gen_unique_name(name); + sc_core::sc_register_hierarchical_name(new_name); + CCI_NAME_CONFLICT_WITH_SYSTEMC_WARNING_(name, new_name); + return sc_core::sc_get_hierarchical_name(new_name); + } + return sc_core::sc_get_hierarchical_name(name); +#else + bool systemc_conflict = false; + std::pair >::iterator, bool> ret; + ret = cci_get_cci_unique_names().insert(std::pair >(name, + std::make_pair(0, cci_name_used))); + if(sc_core::sc_find_object(name)) { + systemc_conflict = true; + } + if (!ret.second || systemc_conflict) { + std::stringstream new_name; + new_name << name << "_" << ret.first->second.first; + ret.first->second.first++; + cci_gen_unique_name(new_name.str().c_str()); + if (systemc_conflict) { + CCI_NAME_CONFLICT_WITH_SYSTEMC_WARNING_(name, new_name.str()); + } + return cci_get_cci_unique_names().find(new_name.str())->first.c_str(); + } + return cci_get_cci_unique_names().find(name)->first.c_str(); +#endif +} + +const char* cci_get_name(const char *name) +{ +#if CCI_SYSTEMC_VERSION_CODE_ >= CCI_VERSION_HELPER_(2,3,2) + return sc_core::sc_get_hierarchical_name(name); +#else + std::map >::iterator + it = cci_get_cci_unique_names().find(name); + if (it != cci_get_cci_unique_names().end()) { + return it->first.c_str(); + } else { + return NULL; + } +#endif +} + +bool cci_unregister_name(const char *name) +{ +#if CCI_SYSTEMC_VERSION_CODE_ >= CCI_VERSION_HELPER_(2,3,2) + return sc_core::sc_unregister_hierarchical_name(name); +#else + std::map >::iterator + it = cci_get_cci_unique_names().find(name); + if (it != cci_get_cci_unique_names().end()) { + it->second.second = cci_name_free; + return true; + } else { + return false; + } +#endif +} + +#undef CCI_NAME_CONFLICT_WITH_SYSTEMC_WARNING_ + +CCI_CLOSE_NAMESPACE_ diff --git a/third_party/cci-1.0.0/cci_core/cci_name_gen.h b/third_party/cci-1.0.0/cci_core/cci_name_gen.h new file mode 100644 index 000000000..17451df85 --- /dev/null +++ b/third_party/cci-1.0.0/cci_core/cci_name_gen.h @@ -0,0 +1,55 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + ****************************************************************************/ + +#ifndef CCI_CORE_CCI_NAME_GEN_H_INCLUDED_ +#define CCI_CORE_CCI_NAME_GEN_H_INCLUDED_ + +#include "cci_core/cci_cmnhdr.h" + +CCI_OPEN_NAMESPACE_ + +/// Generate a cci-wide unique name. +/** + * Keeps the first name as it is, later adds _number, beginning with _0 + * + * @param name name of the CCI element + * + * @return pointer to the name + */ +const char* cci_gen_unique_name(const char* name); + +/// Get cci name pointer +/** + * @param name name of the CCI element + * + * @return pointer to the name if exists or NULL if the name doesn't exist. + */ +const char* cci_get_name(const char* name); + +/// Unregister a cci name +/** + * @param name name of the CCI element to unregister + * + * @return true if unregistration succeeded. Otherwise, false. + */ +bool cci_unregister_name(const char* name); + +CCI_CLOSE_NAMESPACE_ + +#endif diff --git a/third_party/cci-1.0.0/cci_core/cci_value.cpp b/third_party/cci-1.0.0/cci_core/cci_value.cpp new file mode 100644 index 000000000..42076d2f7 --- /dev/null +++ b/third_party/cci-1.0.0/cci_core/cci_value.cpp @@ -0,0 +1,975 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + ****************************************************************************/ + +/** + * @file cci_value.cpp + * @author Philipp A. Hartmann, OFFIS/Intel + */ + +#if defined(_MSC_VER) && _MSC_VER <= 1600 +# pragma warning(disable:4661) +# define CCI_TPLEXTERN_ +#endif // excluded from MSVC'2010 + +#include "cci_core/cci_value.h" +#include "cci_core/rapidjson.h" +#include "cci_cfg/cci_report_handler.h" + +#include // std::swap +#include //std::stringstream + +namespace rapidjson = RAPIDJSON_NAMESPACE; + +CCI_OPEN_NAMESPACE_ + +///@cond CCI_HIDDEN_FROM_DOXYGEN +namespace /* anonymous */ { + +typedef rapidjson::CrtAllocator allocator_type; +typedef rapidjson::UTF8<> encoding_type; +typedef rapidjson::GenericValue json_value; +typedef rapidjson::GenericMember json_member; +typedef rapidjson::GenericDocument json_document; + +typedef json_value::ValueIterator json_value_iter; +typedef json_value::MemberIterator json_member_iter; + +static allocator_type json_allocator; + +// wrapper implementation is simply a RapidJSON value +typedef json_value impl_type; + +// helper to convert to wrapper implementation +static inline impl_type* impl_cast(void* p) + { return static_cast(p); } + +// simple memory pool for impl wrapper objects (non-deallocating) +// - this pool handles the "top-level" objects only +// - RapidJSON allocation is still done via a plain malloc/free allocator +struct impl_pool +{ + static impl_type* allocate() + { + impl_type* ret = free_list_; + if (free_list_ != NULL) { + free_list_ = *reinterpret_cast(free_list_); + new (ret) impl_type(); // initialize JSON object (placement new) + } else { + ret = new impl_type(); + } + return ret; + } + + static void deallocate(impl_type* elem) { + if (elem == NULL) return; // delete NULL is no-op + elem->~impl_type(); // release internal memory (not pooled) + *reinterpret_cast(elem) = free_list_; + free_list_ = elem; + } +private: + static impl_type* free_list_; +}; +impl_type* impl_pool::free_list_; + +} // anonymous namespace + +#define PIMPL( x ) \ + (impl_cast((x).pimpl_)) + +#define DEREF( x ) \ + (*PIMPL(x)) + +#define THIS \ + (PIMPL(*this)) + +#define VALUE_ASSERT( Cond, Msg ) \ + do { if( !(Cond) ) { \ + cci_report_handler::cci_value_failure \ + ( Msg "\n Condition: " #Cond, __FILE__, __LINE__ ); \ + cci_abort(); /* cannot recover from here */ \ + } } while( false ) +///@endcond + +// ---------------------------------------------------------------------------- +// cci_value_cref + +void +cci_value_cref::report_error( const char* msg, const char* file, int line ) const +{ + cci_report_handler::cci_value_failure( msg, file, line ); +} + +bool +operator == ( cci_value_cref const & left, cci_value_cref const & right ) +{ + if( PIMPL(left) == PIMPL(right) ) + return true; + + if( !PIMPL(left) || !PIMPL(right) ) { // only one is set + // equal, if both are conceptually null + return ( PIMPL(left) && DEREF(left).IsNull() ) + || ( PIMPL(right) && DEREF(right).IsNull() ) ; + } + + return DEREF(left) == DEREF(right); +} + +cci_value_category +cci_value_cref::category() const +{ + if( !THIS ) + return CCI_NULL_VALUE; + + switch(THIS->GetType()) + { + case rapidjson::kFalseType: + case rapidjson::kTrueType: + return CCI_BOOL_VALUE; + + case rapidjson::kNumberType: + return THIS->IsDouble() ? CCI_REAL_VALUE : CCI_INTEGRAL_VALUE; + + case rapidjson::kStringType: + return CCI_STRING_VALUE; + + case rapidjson::kArrayType: + return CCI_LIST_VALUE; + + case rapidjson::kObjectType: + return CCI_OTHER_VALUE; + + case rapidjson::kNullType: + default: + return CCI_NULL_VALUE; + } +} + +bool cci_value_cref::is_null() const + { return !THIS || THIS->IsNull(); } + +bool cci_value_cref::is_bool() const + { return THIS && THIS->IsBool(); } + +bool cci_value_cref::is_int() const + { return THIS && THIS->IsInt(); } + +bool cci_value_cref::is_int64() const + { return THIS && THIS->IsInt64(); } + +bool cci_value_cref::is_uint() const + { return THIS && THIS->IsUint(); } + +bool cci_value_cref::is_uint64() const + { return THIS && THIS->IsUint64(); } + +bool cci_value_cref::is_double() const + { return THIS && THIS->IsDouble(); } + +bool cci_value_cref::is_string() const + { return THIS && THIS->IsString(); } + +bool cci_value_cref::is_list() const + { return THIS && THIS->IsArray(); } + +bool cci_value_cref::is_map() const + { return THIS && THIS->IsObject(); } + +#define ASSERT_TYPE( Cond ) \ + VALUE_ASSERT( Cond, "invalid type access" ) + +bool cci_value_cref::get_bool() const +{ + ASSERT_TYPE(is_bool()); + return THIS->GetBool(); +} + +int cci_value_cref::get_int() const +{ + ASSERT_TYPE(is_int()); + return THIS->GetInt(); +} + +unsigned cci_value_cref::get_uint() const +{ + ASSERT_TYPE(is_uint()); + return THIS->GetUint(); +} + +int64 cci_value_cref::get_int64() const +{ + ASSERT_TYPE(is_int64()); + return THIS->GetInt64(); +} + +uint64 cci_value_cref::get_uint64() const +{ + ASSERT_TYPE(is_uint64()); + return THIS->GetUint64(); +} + +double cci_value_cref::get_double() const +{ + ASSERT_TYPE(is_number()); + return THIS->GetDouble(); +} + +cci_value_string_cref cci_value_cref::get_string() const +{ + ASSERT_TYPE(is_string()); + return cci_value_string_cref(pimpl_); +} + +cci_value_list_cref cci_value_cref::get_list() const +{ + ASSERT_TYPE(is_list()); + return cci_value_list_cref(pimpl_); +} + +cci_value_map_cref cci_value_cref::get_map() const +{ + ASSERT_TYPE(is_map()); + return cci_value_map_cref(pimpl_); +} + +std::ostream& operator<<( std::ostream& os, cci_value_cref const& v ) +{ + if( v.is_null() ) { + os << "null"; + } else { + rapidjson::OStreamWrapper wos(os); + rapidjson::Writer writer(wos); + DEREF(v).Accept( writer ); + } + return os; +} + +// ---------------------------------------------------------------------------- +// cci_value_ref + +cci_value +cci_value_ref::move() +{ + cci_value ret; + ret.init(); // ensure target validity + DEREF(ret) = *THIS; // RapidJSON has move semantics upon plain assignment + return ret; +} + +void +cci_value_ref::swap( cci_value_ref& that ) +{ + VALUE_ASSERT( pimpl_ && that.pimpl_, "swap with invalid value failed" ); + THIS->Swap( DEREF(that) ); +} + +cci_value_ref +cci_value_ref::operator=( const cci_value_cref &that ) +{ + if( that.is_null() ) + set_null(); + else if (THIS != PIMPL(that) ) { + sc_assert( THIS ); + THIS->CopyFrom( DEREF(that), json_allocator ); + } + return *this; +} + +cci_value_ref +cci_value_ref::set_null() +{ + if( THIS ) THIS->SetNull(); + return this_type( THIS ); +} + +cci_value_ref +cci_value_ref::set_bool(bool v) +{ + sc_assert( THIS ); + THIS->SetBool(v); + return this_type( THIS ); +} + +cci_value_ref +cci_value_ref::set_int(int v) +{ + sc_assert( THIS ); + THIS->SetInt(v); + return this_type( THIS ); +} + +cci_value_ref +cci_value_ref::set_uint(unsigned v) +{ + sc_assert( THIS ); + THIS->SetUint(v); + return this_type( THIS ); +} + +cci_value_ref +cci_value_ref::set_int64(int64 v) +{ + sc_assert( THIS ); + THIS->SetInt64(v); + return this_type( THIS ); +} + +cci_value_ref +cci_value_ref::set_uint64(uint64 v) +{ + sc_assert( THIS ); + THIS->SetUint64(v); + return this_type( THIS ); +} + +cci_value_ref +cci_value_ref::set_double(double d) +{ + sc_assert( THIS ); + THIS->SetDouble(d); + return this_type( THIS ); +} + +cci_value_string_ref +cci_value_ref::set_string( const char* s, size_t len ) +{ + sc_assert( THIS ); + THIS->SetString(s, static_cast(len), json_allocator); + return cci_value_string_ref(THIS); +} + +cci_value_list_ref +cci_value_ref::set_list() +{ + sc_assert( THIS ); + THIS->SetArray(); + return cci_value_list_ref( THIS ); +} + +cci_value_map_ref +cci_value_ref::set_map() +{ + sc_assert( THIS ); + THIS->SetObject(); + return cci_value_map_ref( THIS ); +} + +std::istream& operator>>( std::istream& is, cci_value_ref v ) +{ + sc_assert( PIMPL(v) ); + json_document d; + rapidjson::IStreamWrapper wis(is); + + d.ParseStream< rapidjson::kParseStopWhenDoneFlag >( wis ); + // VALUE_ASSERT( !d.HasParseError(), "cci_value stream extraction failed" ); + if( !d.HasParseError() ) + DEREF(v).Swap( d ); + else + is.setstate( std::istream::failbit ); + + return is; +} + +// ---------------------------------------------------------------------------- +// cci_value_string_cref + +cci_value_string_cref::size_type +cci_value_string_cref::size() const + { return THIS->GetStringLength(); } + +const char* +cci_value_string_cref::c_str() const + { return THIS->GetString(); } + +bool +cci_value_string_cref::operator==( cci_value_string_cref const & s ) const + { return *THIS == DEREF(s); } + +bool +cci_value_string_cref::operator==( const char * s ) const + { return !s ? false : *THIS == s; } + +bool +cci_value_string_cref::operator==( const std::string& s ) const + { return *THIS == rapidjson::StringRef( s.c_str(), s.size() ); } + +// ---------------------------------------------------------------------------- +// cci_value_string_ref + +cci_value +cci_value_string_ref::move() +{ + cci_value ret; + ret.init(); // ensure target validity + DEREF(ret) = *THIS; // RapidJSON has move semantics upon plain assignment + THIS->SetString("", 0); + return ret; +} + +void +cci_value_string_ref::swap(this_type & that) +{ + VALUE_ASSERT( pimpl_ && that.pimpl_, "swap with invalid value failed" ); + THIS->Swap( DEREF(that) ); +} + +// ---------------------------------------------------------------------------- +// cci_value_list/map::(const_)iterator + +///@cond CCI_HIDDEN_FROM_DOXYGEN +namespace cci_impl { + +struct value_iterator_list_tag {}; +struct value_iterator_map_tag {}; + +template struct value_iterator_tag; +template<> struct value_iterator_tag : value_iterator_list_tag {}; +template<> struct value_iterator_tag : value_iterator_list_tag {}; +template<> struct value_iterator_tag : value_iterator_map_tag {}; +template<> struct value_iterator_tag : value_iterator_map_tag {}; + +template +struct value_iterator_impl_json +{ + typedef void* impl_type; // type-punned pointer for now + typedef std::ptrdiff_t difference_type; + + static impl_type advance(impl_type it, difference_type n, value_iterator_list_tag) + { return static_cast(it) + n; } + + static impl_type advance(impl_type it, difference_type n, value_iterator_map_tag) + { return static_cast(it) + n; } + + static difference_type distance(impl_type a, impl_type b, value_iterator_list_tag) + { return static_cast(b) - static_cast(a); } + + static difference_type distance(impl_type a, impl_type b, value_iterator_map_tag) + { return static_cast(b) - static_cast(a); } +}; + +template +typename value_iterator_impl::impl_type +value_iterator_impl::advance(difference_type n) const + { return value_iterator_impl_json::advance( impl_, n, value_iterator_tag() ); } + +template +int value_iterator_impl::compare(impl_type other_impl) const +{ + // comparing internal pointers is sufficient here + if (impl_ < other_impl) return -1; + if (impl_ > other_impl) return 1; + return 0; +} + +template +typename value_iterator_impl::difference_type +value_iterator_impl::distance(impl_type that_impl) const + { return value_iterator_impl_json::distance( that_impl, impl_, value_iterator_tag() ); } + +template class value_iterator_impl; +template class value_iterator_impl; +template class value_iterator_impl; +template class value_iterator_impl; +} // namespace cci_impl +///@endcond + +template class cci_value_iterator; +template class cci_value_iterator; +template class cci_value_iterator; +template class cci_value_iterator; + +// ---------------------------------------------------------------------------- +// cci_value_list_cref + +cci_value_list_cref::size_type +cci_value_list_cref::size() const + { return THIS->Size(); } + +cci_value_list_cref::size_type +cci_value_list_cref::capacity() const + { return THIS->Capacity(); } + +cci_value_cref +cci_value_list_cref::at( size_type index ) const +{ + VALUE_ASSERT( index < size(), "index out of bounds" ); + return cci_value_cref( &(*THIS)[static_cast(index)] ); +} + +cci_value_cref +cci_value_list_cref::operator[]( size_type index ) const + { return cci_value_cref( &(*THIS)[static_cast(index)] ); } + +cci_value_list_cref::const_iterator +cci_value_list_cref::cbegin() const + { return const_iterator(THIS->Begin()); } + +cci_value_list_cref::const_iterator +cci_value_list_cref::cend() const + { return const_iterator(THIS->End()); } + +// ---------------------------------------------------------------------------- +// cci_value_list_ref + +cci_value +cci_value_list_ref::move() +{ + cci_value ret; + ret.set_list(); + DEREF(ret) = *THIS; // RapidJSON has move semantics upon plain assignment + THIS->SetArray(); + return ret; +} + +void +cci_value_list_ref::swap(this_type & that) +{ + VALUE_ASSERT( pimpl_ && that.pimpl_, "swap with invalid value failed" ); + THIS->Swap( DEREF(that) ); +} + +cci_value_list_ref +cci_value_list_ref::clear() +{ + THIS->Clear(); + return *this; +} + +cci_value_list_ref +cci_value_list_ref::reserve( size_type new_capacity ) +{ + THIS->Reserve( static_cast(new_capacity) + , json_allocator ); + return *this; +} + +cci_value_list_ref +cci_value_list_ref::push_back( const_reference value ) +{ + json_value v; + if( PIMPL(value) ) + v.CopyFrom( DEREF(value), json_allocator ); + THIS->PushBack( v, json_allocator ); + return *this; +} + +#ifdef CCI_HAS_CXX_RVALUE_REFS +cci_value_list_ref +cci_value_list_ref::push_back( cci_value&& value ) +{ + json_value v; + if( PIMPL(value) ) + v = DEREF(value); // RapidJSON has move semantics upon plain assignment + THIS->PushBack( v, json_allocator ); + return *this; +} +#endif // CCI_HAS_CXX_RVALUE_REFS + +cci_value_list_ref::iterator +cci_value_list_ref::begin() + { return iterator(THIS->Begin()); } + +cci_value_list_ref::iterator +cci_value_list_ref::end() + { return iterator(THIS->End()); } + +cci_value_list_ref::iterator +cci_value_list_ref::insert( const_iterator pos, const_reference value ) +{ + return insert(pos, 1u, value); +} + +cci_value_list_ref::iterator +cci_value_list_ref::insert( const_iterator pos, size_type count, const_reference value ) +{ + // RapidJSON doesn't support Insert, yet + json_value_iter json_pos = static_cast(pos.raw()); + size_type offset = json_pos - THIS->Begin(); + + VALUE_ASSERT( offset <= THIS->Size(), "invalid insertion position" ); + + if (!count) // nothing to insert + return iterator(json_pos); + + json_value new_val(rapidjson::kArrayType); + new_val.Reserve(static_cast(size() + count), json_allocator); + + json_value_iter it = THIS->Begin(); + while ( it != json_pos ) // move prefix values into new array + new_val.PushBack(*it++, json_allocator); + + while( count-- > 0u ) { // copy values at new position + json_value v; + if( PIMPL(value) ) + v.CopyFrom( DEREF(value), json_allocator ); + new_val.PushBack( v, json_allocator ); + } + + while ( it != THIS->End() ) // move suffix values into new array + new_val.PushBack(*it++, json_allocator); + + THIS->Swap( new_val ); // update current value + return iterator(THIS->Begin() + offset); // iterator to first inserted element +} + +cci_value_list_ref::iterator +cci_value_list_ref::erase(const_iterator pos) +{ + json_value_iter json_pos = static_cast(pos.raw()); + return iterator( THIS->Erase(json_pos) ); +} + +cci_value_list_ref::iterator +cci_value_list_ref::erase(const_iterator first, const_iterator last) +{ + json_value_iter json_first = static_cast(first.raw()); + json_value_iter json_last = static_cast(last.raw()); + return iterator( THIS->Erase(json_first, json_last) ); +} + +void +cci_value_list_ref::pop_back() + { THIS->PopBack(); } + +// ---------------------------------------------------------------------------- +// cci_value_map_cref + +cci_value_map_elem_cref::cci_value_map_elem_cref(void* raw) + : key ( &static_cast(raw)->name ) + , value( &static_cast(raw)->value ) + , pimpl_(raw) +{} + +cci_value_map_cref::size_type +cci_value_map_cref::size() const + { return THIS->MemberCount(); } + +cci_value_cref::impl_type +cci_value_map_cref::do_lookup( const char* key, size_type keylen + , lookup_mode mode /* = KEY_REQUIRED */ ) const +{ + json_value kv( rapidjson::StringRef(key, keylen) ); + json_value::ConstMemberIterator it = THIS->FindMember(kv); + + if( it != THIS->MemberEnd() ) + return const_cast(&it->value); + + if( mode == KEY_OPTIONAL ) + return NULL; + + if( mode == KEY_CREATE ) + { + json_value k( key, static_cast(keylen), json_allocator ); + THIS->AddMember( k, json_value().Move(), json_allocator ); + it = THIS->FindMember(kv); + sc_assert( it != THIS->MemberEnd() ); + return const_cast(&it->value); + } + + std::stringstream ss; + ss << "cci_value map has no element with key '" << key << "'"; + report_error( ss.str().c_str(), __FILE__, __LINE__ ); + return NULL; +} + +cci_value_map_cref::const_iterator +cci_value_map_cref::do_find(const char* key, size_type keylen) const +{ + return const_iterator(THIS->FindMember(rapidjson::StringRef(key, keylen))); +} + +cci_value_map_cref::const_iterator +cci_value_map_cref::cbegin() const + { return const_iterator(THIS->MemberBegin()); } + +cci_value_map_cref::const_iterator +cci_value_map_cref::cend() const + { return const_iterator(THIS->MemberEnd()); } + +// ---------------------------------------------------------------------------- +// cci_value_map_ref + +cci_value_map_elem_ref::cci_value_map_elem_ref(void* raw) + : key ( &static_cast(raw)->name ) + , value( &static_cast(raw)->value ) + , pimpl_(raw) +{} + +cci_value +cci_value_map_ref::move() +{ + cci_value ret; + ret.set_map(); + DEREF(ret) = *THIS; // RapidJSON has move semantics upon plain assignment + THIS->SetObject(); + return ret; +} + +void +cci_value_map_ref::swap(this_type & that) +{ + VALUE_ASSERT( pimpl_ && that.pimpl_, "swap with invalid value failed" ); + THIS->Swap( DEREF(that) ); +} + +cci_value_map_ref +cci_value_map_ref::clear() +{ + THIS->RemoveAllMembers(); + return *this; +} + +cci_value_map_ref +cci_value_map_ref::do_push( const char * key, size_type keylen + , cci_value::const_reference value ) +{ + json_value k( key, static_cast(keylen), json_allocator ); + json_value v; + if( PIMPL(value) ) + v.CopyFrom( DEREF(value), json_allocator ); + THIS->AddMember( k, v, json_allocator ); + return *this; +} + +#ifdef CCI_HAS_CXX_RVALUE_REFS +cci_value_map_ref +cci_value_map_ref::do_push( const char * key, size_type keylen + , cci_value&& value ) +{ + json_value k( key, keylen, json_allocator ); + json_value v; + if( PIMPL(value) ) + v = DEREF(value); // RapidJSON has move semantics upon plain assignment + THIS->AddMember( k, v, json_allocator ); + return *this; +} +#endif // CCI_HAS_CXX_RVALUE_REFS + +cci_value_map_ref::iterator +cci_value_map_ref::begin() + { return iterator(THIS->MemberBegin()); } + +cci_value_map_ref::iterator +cci_value_map_ref::end() + { return iterator(THIS->MemberEnd()); } + +cci_value_map_ref::size_type +cci_value_map_ref::do_erase(const char* key, size_type keylen) +{ + json_value json_key(rapidjson::StringRef(key, keylen)); + size_type count = 0; + for( json_member_iter it = THIS->FindMember(json_key); + it != THIS->MemberEnd(); it = THIS->FindMember(json_key) ) + { + THIS->EraseMember(it); + count++; + } + return count; +} + +cci_value_map_ref::iterator +cci_value_map_ref::erase(const_iterator pos) +{ + json_member_iter json_pos = static_cast(pos.raw()); + return iterator( THIS->EraseMember(json_pos) ); +} + +cci_value_map_ref::iterator +cci_value_map_ref::erase(const_iterator first, const_iterator last) +{ + json_member_iter json_first = static_cast(first.raw()); + json_member_iter json_last = static_cast(last.raw()); + return iterator( THIS->EraseMember(json_first, json_last) ); +} + +// ---------------------------------------------------------------------------- +// cci_value(, _list, _map ) -- owning wrapper implementations + +#define WRAPPER_ASSIGN_PRECOND_(Kind) \ + WRAPPER_ASSIGN_PRECOND_FOR_ ## Kind +#define WRAPPER_ASSIGN_PRECOND_FOR_cci_value \ + if( that.is_null() ) { set_null(); return *this; } \ + init() +#define WRAPPER_ASSIGN_PRECOND_FOR_cci_value_list \ + sc_assert( is_list() && that.is_list() ) +#define WRAPPER_ASSIGN_PRECOND_FOR_cci_value_map \ + sc_assert( is_map() && that.is_map() ) + +#define WRAPPER_DO_INIT_(Kind) \ + WRAPPER_DO_INIT_ ## Kind +#define WRAPPER_DO_INIT_cci_value \ + ((void)0) +#define WRAPPER_DO_INIT_cci_value_list \ + (THIS)->SetArray() +#define WRAPPER_DO_INIT_cci_value_map \ + (THIS)->SetObject() + +#define DEFINE_WRAPPER_(Kind) \ + Kind::this_type & \ + Kind::operator=( const_reference that ) \ + { \ + WRAPPER_ASSIGN_PRECOND_( Kind ); \ + reference::operator=( that ); \ + return *this; \ + } \ + \ + void \ + Kind::swap( this_type & that ) \ + { \ + using std::swap; \ + swap( pimpl_ , that.pimpl_ ); \ + swap( own_pimpl_, that.own_pimpl_ ); \ + } \ + \ + Kind::impl_type \ + Kind::do_init() \ + { \ + sc_assert( !own_pimpl_ ); \ + pimpl_ = own_pimpl_ = impl_pool::allocate(); \ + WRAPPER_DO_INIT_( Kind ); \ + return THIS; \ + } \ + \ + Kind::~Kind() \ + { \ + impl_pool::deallocate(impl_cast(own_pimpl_)); \ + } + +DEFINE_WRAPPER_(cci_value) +DEFINE_WRAPPER_(cci_value_list) +DEFINE_WRAPPER_(cci_value_map) + +#ifdef CCI_HAS_CXX_RVALUE_REFS + +cci_value::cci_value( this_type && that ) + : cci_value_ref(CCI_MOVE_(that.pimpl_)) + , own_pimpl_(CCI_MOVE_(that.own_pimpl_)) +{ + that.pimpl_ = NULL; + that.own_pimpl_ = NULL; +} + +cci_value::cci_value( cci_value_list && that ) + : own_pimpl_() +{ + do_init(); + *THIS = CCI_MOVE_(DEREF(that)); + DEREF(that).SetArray(); +} + +cci_value_list::cci_value_list( this_type && that ) + : own_pimpl_() +{ + do_init(); + *THIS = CCI_MOVE_(DEREF(that)); + DEREF(that).SetArray(); +} + +cci_value::cci_value( cci_value_map && that ) + : own_pimpl_() +{ + do_init(); + *THIS = CCI_MOVE_(DEREF(that)); + DEREF(that).SetObject(); +} + +cci_value_map::cci_value_map( this_type && that ) + : own_pimpl_() +{ + do_init(); + *THIS = CCI_MOVE_(DEREF(that)); + DEREF(that).SetObject(); +} + +cci_value& cci_value::operator=( this_type && that ) +{ + if (own_pimpl_ == that.own_pimpl_) return *this; + impl_pool::deallocate(impl_cast(own_pimpl_)); + pimpl_ = own_pimpl_ = that.own_pimpl_; + that.pimpl_ = that.own_pimpl_ = NULL; + return *this; +} + +cci_value& cci_value::operator=( cci_value_list && that ) +{ + init(); + *THIS = CCI_MOVE_(DEREF(that)); + DEREF(that).SetArray(); + return *this; +} + +cci_value_list& cci_value_list::operator=(this_type && that) +{ + if (own_pimpl_ == that.own_pimpl_) return *this; + *THIS = CCI_MOVE_(DEREF(that)); + DEREF(that).SetArray(); + return *this; +} + +cci_value& cci_value::operator=(cci_value_map && that) +{ + init(); + *THIS = CCI_MOVE_(DEREF(that)); + DEREF(that).SetObject(); + return *this; +} + +cci_value_map& cci_value_map::operator=(this_type && that) +{ + if (own_pimpl_ == that.own_pimpl_) return *this; + *THIS = CCI_MOVE_(DEREF(that)); + DEREF(that).SetObject(); + return *this; +} + +#endif // CCI_HAS_CXX_RVALUE_REFS + +// ---------------------------------------------------------------------------- +// JSON (de)serialize + +bool +cci_value_ref::json_deserialize( std::string const & src ) +{ + json_document doc; + try { + doc.Parse( src.c_str() ); + } + catch ( rapidjson::ParseException const & ) + { + return false; + } + THIS->Swap( doc ); + return true; +} + +std::string +cci_value_cref::to_json() const +{ + std::string dst; + rapidjson::StringOutputStream str(dst); + rapidjson::Writer writer(str); + if (!THIS) { + writer.Null(); + } else { + THIS->Accept(writer); + } + VALUE_ASSERT(writer.IsComplete(), "incomplete JSON sequence"); + return dst; +} + +CCI_CLOSE_NAMESPACE_ diff --git a/third_party/cci-1.0.0/cci_core/cci_value.h b/third_party/cci-1.0.0/cci_core/cci_value.h new file mode 100644 index 000000000..44e66c24d --- /dev/null +++ b/third_party/cci-1.0.0/cci_core/cci_value.h @@ -0,0 +1,1546 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + ****************************************************************************/ + +#ifndef CCI_CCI_VALUE_H_INCLUDED_ +#define CCI_CCI_VALUE_H_INCLUDED_ + +#include // std::strlen +#include "cci_core/cci_core_types.h" +#include "cci_core/cci_value_iterator.h" +#include "cci_core/systemc.h" // sc_dt::(u)int64, potentially strip out + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4231) // extern template +#endif // _MSC_VER + +/** + * @file cci_value.h + * @author Philipp A. Hartmann, OFFIS/Intel + */ + +CCI_OPEN_NAMESPACE_ + +// define our own typedefs to avoid SystemC dependency? +using sc_dt::int64; +using sc_dt::uint64; + +// forward declarations +class cci_value; +class cci_value_cref; +class cci_value_ref; +class cci_value_string_cref; +class cci_value_string_ref; +class cci_value_list; +class cci_value_list_cref; +class cci_value_list_ref; +class cci_value_map; +class cci_value_map_cref; +class cci_value_map_ref; +class cci_value_map_elem_ref; +class cci_value_map_elem_cref; + +template struct cci_value_converter; + +/** +* Enumeration for data type categories, whose rough getting and setting is +* supported by base class directly +*/ +enum cci_value_category { + /// Indicates that there is no data + CCI_NULL_VALUE = 0, + /// A boolean valued component of data + CCI_BOOL_VALUE, + /// An integer number component of data + CCI_INTEGRAL_VALUE, + /// A real number number component of data + CCI_REAL_VALUE, + /// A string component of data + CCI_STRING_VALUE, + /// A list component of data + CCI_LIST_VALUE, + /// A component of data that doesn't fit the other categories + CCI_OTHER_VALUE +}; + +#ifndef CCI_DOXYGEN_IS_RUNNING +# define CCI_VALUE_CONVERTER_(Type) \ + typename cci_value_converter::type +#define CCI_VALUE_CHECKED_CONVERTER_(Type) \ + CCI_VALUE_CONVERTER_(Type) * +# define CCI_VALUE_REQUIRES_CONVERTER_(Type) \ + CCI_VALUE_CHECKED_CONVERTER_(Type) = 0 +#else +# define CCI_VALUE_CONVERTER_(Type) Type +#endif // CCI_DOXYGEN_IS_RUNNING + +/// @ref cci_value comparisons +bool operator==( cci_value_cref const &, cci_value_cref const & ); + +/// @ref cci_value ostream insertion +std::ostream& operator<<( std::ostream&, cci_value_cref const & ); + +/// @ref cci_value istream extraction +std::istream& operator>>( std::istream&, cci_value_ref ); + +// -------------------------------------------------------------------------- + +/// reference to a constant (nested) @ref cci_value +class cci_value_cref +{ + friend class cci_value_ref; + friend class cci_value_list_cref; + friend class cci_value_list_ref; + friend class cci_value_map_cref; + friend class cci_value_map_ref; + friend class cci_value_map_elem_cref; + template friend class cci_impl::value_iterator_impl; + friend bool operator==( cci_value_cref const &, cci_value_cref const & ); + friend std::ostream& operator<<( std::ostream&, cci_value_cref const & ); + +protected: + typedef void* impl_type; // use type-punned pointer for now + typedef cci_impl::value_ptr proxy_ptr; + + explicit cci_value_cref(impl_type i = NULL) + : pimpl_(i) {} + +public: + typedef cci_value value_type; + typedef cci_value_cref const_reference; + typedef cci_value_ref reference; + + /** @name Type queries */ + ///@{ + cci_value_category category() const; + bool is_null() const; + + bool is_bool() const; + bool is_false() const + { return is_bool() && !get_bool(); } + bool is_true() const + { return is_bool() && get_bool(); } + + bool is_number() const + { return is_int64() || is_uint64() || is_double(); } + + bool is_int() const; + bool is_uint() const; + bool is_int64() const; + bool is_uint64() const; + bool is_double() const; + + bool is_string() const; + + bool is_map() const; + + bool is_list() const; + //@} + + /** @name Get basic value */ + //@{ + + /// get boolean value + bool get_bool() const; + + /// get integer value + int get_int() const; + /// get unsigned integer value + unsigned get_uint() const; + /// get 64-bit integer value + int64 get_int64() const; + /// get 64-bit unsigned integer value + uint64 get_uint64() const; + /// get floating point value + double get_double() const; + /// get the numeric value (alias for get_double()) + double get_number() const { return get_double(); } + //@} + + /** + * @name Get complex value + * These functions return (constant) references to the complex value types + * that can be stored in a cci_value (strings, lists, maps). + */ + //@{ + cci_value_string_cref get_string() const; + cci_value_list_cref get_list() const; + cci_value_map_cref get_map() const; + //@} + + /** @name Get arbitrarily typed value */ + //@{ + /// try to get a value of a @ref cci_value_converter enabled type + template + bool try_get( T& dst +#ifndef CCI_DOXYGEN_IS_RUNNING + , CCI_VALUE_REQUIRES_CONVERTER_(T) +#endif // CCI_DOXYGEN_IS_RUNNING + ) const; + + /// get a value of a @ref cci_value_converter enabled type + template + CCI_VALUE_CONVERTER_(T) get() const; + //@} + + /// convert value to JSON + std::string to_json() const; + + /** @brief overloaded addressof operator + * + * The \c addressof operator is replaced in the reference proxy classes + * \c cci_value_*ref to avoid taking an address of a (usually) + * temporary object. + * + * All reference objects provide the replacement, only the top-level + * objects (cci_value, cci_value_list, cci_value_map) provide default + * \c addressof semantics again. + */ + proxy_ptr operator&() const { return proxy_ptr(*this); } + + /// Does this reference point to the same value as another reference? + bool is_same(cci_value_cref that) const { return pimpl_ == that.pimpl_; } + +protected: + void + report_error( const char* msg + , const char* file = NULL, int line = 0 ) const; + +protected: + impl_type pimpl_; + +private: + /// constant reference, disabled assignment + cci_value_cref operator=( cci_value_cref const& ) /* = delete */; +}; + +template +bool +cci_value_cref::try_get( T& dst +#ifndef CCI_DOXYGEN_IS_RUNNING + , CCI_VALUE_CHECKED_CONVERTER_(T) +#endif // CCI_DOXYGEN_IS_RUNNING + ) const +{ + typedef cci_value_converter conv; + return conv::unpack( dst, *this ); +} + +template +CCI_VALUE_CONVERTER_(T) cci_value_cref::get() const +{ + T result{}; + if( !try_get(result) ) { + report_error("conversion from cci_value failed", __FILE__, __LINE__); + } + return result; +} + +// -------------------------------------------------------------------------- + +/// reference to a mutable (nested) @ref cci_value +class cci_value_ref + : public cci_value_cref +{ + friend class cci_value_string_ref; + friend class cci_value_list_ref; + friend class cci_value_map_ref; + friend class cci_value_map_elem_ref; + template friend class cci_impl::value_iterator_impl; + friend std::istream& operator>>( std::istream&, cci_value_ref ); + typedef cci_value_cref base_type; + typedef cci_value_ref this_type; + + typedef cci_impl::value_ptr proxy_ptr; +protected: + explicit cci_value_ref(impl_type i = NULL) + : cci_value_cref(i) {} + +public: + /// move contents to another value (becomes @c null afterwards) + cci_value move(); + + /// exchange contents with another cci_value + void swap( this_type& that ); + friend void swap(this_type a, this_type b) { a.swap(b); } + + this_type operator=( const base_type& ); + this_type operator=( const this_type& ); + + /** @name Set basic value + * + * The various @c set_* functions update the represented value + * (and its @ref category()) accordingly. + * + * These functions provide a "fluent interface" by returning a reference + * to the surrounding variant object. This enables chained function calls, + * which is especially convenient for complex values like lists and maps. + */ + ///@{ + + /// set value to @c null + cci_value_ref set_null(); + /// set boolean value (@c true, @c false) + cci_value_ref set_bool( bool v ); + /// set integer value + cci_value_ref set_int( int v ); + /// set unsigned integer value + cci_value_ref set_uint( unsigned v ); + /// set 64-bit integer value + cci_value_ref set_int64( int64 v ); + /// set unsigned 64-bit integer value + cci_value_ref set_uint64( uint64 v ); + /// set double value + cci_value_ref set_double( double v ); + /// set double value (alias for set_double()) + cci_value_ref set_number( double v ) { return set_double(v); } + + /// set string value from null-terminated string + cci_value_string_ref set_string( const char* s ); + /// set string value from std::string + cci_value_string_ref set_string( const std::string& s ); + /// set string value from cci_value::const_string_reference + cci_value_string_ref set_string( cci_value_string_cref s ); + /// set string value from null-terminated string and length + cci_value_string_ref set_string( const char* s, size_t len ); + + /// set value to an (empty) list + cci_value_list_ref set_list(); + /// set value to an (empty) map + cci_value_map_ref set_map(); + ///@} + + /** @name Get complex value + * + * The functions return a reference to a (mutable) @ref cci_value object + * of the corresponding complex value type (string, list, map). + */ + + ///@{ + using base_type::get_string; + cci_value_string_ref get_string(); + + using base_type::get_list; + cci_value_list_ref get_list(); + + using base_type::get_map; + cci_value_map_ref get_map(); + ///@} + + /** @name Set arbitrarily typed value */ + //@{ + /// set value to cci_value_converter enabled type + template + cci_value_ref set(T const & dst +#ifndef CCI_DOXYGEN_IS_RUNNING + , CCI_VALUE_REQUIRES_CONVERTER_(T) +#endif // CCI_DOXYGEN_IS_RUNNING + ); + /// try to set value to cci_value_converter enabled type + template + bool try_set(T const & dst +#ifndef CCI_DOXYGEN_IS_RUNNING + , CCI_VALUE_REQUIRES_CONVERTER_(T) +#endif // CCI_DOXYGEN_IS_RUNNING + ); + ///@} + + /// @copydoc cci_value_cref::operator& + proxy_ptr operator&() const { return proxy_ptr(*this); } +protected: + /// try to set the value from a JSON-encoded string + bool json_deserialize( std::string const& ); +}; + +inline cci_value_ref +cci_value_ref::operator=( const this_type & that ) + { return *this = base_type(that); } + +template +bool +cci_value_ref::try_set( T const & src +#ifndef CCI_DOXYGEN_IS_RUNNING + , CCI_VALUE_CHECKED_CONVERTER_(T) +#endif // CCI_DOXYGEN_IS_RUNNING + ) +{ + typedef cci_value_converter conv; + return conv::pack( *this, src ); +} + +template +cci_value_ref +cci_value_ref::set( T const& src +#ifndef CCI_DOXYGEN_IS_RUNNING + , CCI_VALUE_CHECKED_CONVERTER_(T) +#endif // CCI_DOXYGEN_IS_RUNNING + ) +{ + if( !try_set(src) ) { + report_error("conversion to cci_value failed", __FILE__, __LINE__); + } + return *this; +} + +// -------------------------------------------------------------------------- + +/// reference to constant cci_value string value +class cci_value_string_cref + : public cci_value_cref +{ + friend class cci_value_cref; + friend class cci_value_map_elem_cref; + friend class cci_value_map_elem_ref; + typedef cci_value_cref base_type; + typedef cci_value_string_cref this_type; + typedef cci_impl::value_ptr proxy_ptr; + +protected: + explicit cci_value_string_cref(impl_type i = NULL) + : base_type(i) {} + +public: + typedef size_t size_type; + + /// empty string? + bool empty() const { return size() == 0; } + size_type length() const { return size(); } + size_type size() const; + + /// implicit conversion to std::string + operator std::string() const { return std::string( c_str(), length() ); } + /// obtain underlying null-terminated string + char const * c_str() const; + + /// character access by index + char operator[]( size_type index ) const + { return c_str()[index]; } + + /** @name string equality comparisons */ + //@{ + bool operator==(cci_value_string_cref const &) const; + bool operator==(const char* s) const; + bool operator==(std::string const & ) const; + + friend bool operator==( const char * a, cci_value_string_cref const & b) + { return b == a; } + friend bool operator==( std::string const & a, cci_value_string_cref const & b ) + { return b == a; } + //@} + + /// @copydoc cci_value_cref::operator& + proxy_ptr operator&() const { return proxy_ptr(*this); } + +private: + // exclude non-string value functions + using base_type::get_bool; + using base_type::get_int; + using base_type::get_uint; + using base_type::get_int64; + using base_type::get_uint64; + using base_type::get_double; + using base_type::get_list; + using base_type::get_map; + +private: + // constant reference, no assignment + this_type& operator=( this_type const& ) /* = delete */; +}; + +/// specialisation for printing a plain string reference (not JSON encoded) +inline std::ostream& +operator<<( std::ostream& os, cci_value_string_cref const& s ) +{ + os.write( s.c_str(), static_cast(s.length()) ); + return os; +} + +// -------------------------------------------------------------------------- + +/// reference to mutable cci_value string value +class cci_value_string_ref + : public cci_value_string_cref +{ + friend class cci_value_ref; + typedef cci_value_string_cref base_type; + typedef cci_value_string_ref this_type; + typedef cci_impl::value_ptr proxy_ptr; + +protected: + explicit cci_value_string_ref(impl_type i = NULL) + : base_type(i) {} + +public: + /// move contents to another value (becomes empty string afterwards) + cci_value move(); + + /// exchange contents with another string value + friend void swap(this_type a, this_type b) { a.swap(b); } + void swap( this_type& that ); + + /** @name assign string contents */ + //@{ + this_type operator=( this_type const& ); + this_type operator=( cci_value_string_cref s ); + this_type operator=( const char * s ); + this_type operator=( std::string const & s ); + //@} + + /// @copydoc cci_value_cref::operator& + proxy_ptr operator&() const { return proxy_ptr(*this); } +}; + +inline cci_value_string_ref +cci_value_string_ref::operator=( this_type const& s ) + { return cci_value_ref(pimpl_).set_string(s); } + +inline cci_value_string_ref +cci_value_string_ref::operator=( cci_value_string_cref s ) + { return cci_value_ref(pimpl_).set_string(s); } + +inline cci_value_string_ref +cci_value_string_ref::operator=( const char * s ) + { return cci_value_ref(pimpl_).set_string(s); } + +inline cci_value_string_ref +cci_value_string_ref::operator=( std::string const & s ) + { return cci_value_ref(pimpl_).set_string(s); } + +inline cci_value_string_ref +cci_value_ref::get_string() + { return cci_value_string_ref( base_type::get_string().pimpl_ ); } + +inline cci_value_string_ref +cci_value_ref::set_string(char const * s) + { return set_string( s ? s : "", s ? std::strlen(s) : 0u ); } + +inline cci_value_string_ref +cci_value_ref::set_string(cci_value_string_cref s) + { return set_string( s.c_str(), s.length() ); } + +inline cci_value_string_ref +cci_value_ref::set_string(std::string const & s) + { return set_string( s.c_str(), s.length() ); } + +// -------------------------------------------------------------------------- + +///@cond CCI_HIDDEN_FROM_DOXYGEN +// iterator implementations in cci_value.cpp +namespace cci_impl { +CCI_TPLEXTERN_ template class value_iterator_impl; +CCI_TPLEXTERN_ template class value_iterator_impl; +} // namespace cci_impl +CCI_TPLEXTERN_ template class cci_value_iterator; +CCI_TPLEXTERN_ template class cci_value_iterator; +///@endcond + +/// reference to constant cci_value list value +class cci_value_list_cref + : public cci_value_cref +{ + friend class cci_value_cref; + typedef cci_value_cref base_type; + typedef cci_value_list_cref this_type; + typedef cci_impl::value_ptr proxy_ptr; + +protected: + explicit cci_value_list_cref(impl_type i = NULL) + : base_type(i) {} + +public: + typedef size_t size_type; + typedef cci_value_iterator iterator; + typedef cci_value_iterator const_iterator; + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; + + /** @name list queries */ + //@{ + bool empty() const { return size() == 0; } + /// number of elements in the list + size_type size() const; + /// capacity of underlying storage + size_type capacity() const; + //@} + + /** @name (constant) element access by index + * @see cci_value_list_ref::at, cci_value_list_ref::operator[] + */ + //@{ + /** @brief unchecked element access + * @warning Given index is not checked and leads to undefined behavior + * for out-of-bounds accesses + */ + const_reference operator[]( size_type index ) const; + /** @brief checked element access + * @note Given index is bounds-checked, i.e. reports an error + * for attempted out-of-bounds accesses + */ + const_reference at( size_type index ) const; + + /// return first element in the list + const_reference front() const + { return (*this)[0]; } + + /// return last element in the list + const_reference back() const + { return (*this)[size() - 1]; } + //@} + + /** @name (constant) iterator interface */ + //@{ + const_iterator cbegin() const; + const_iterator cend() const; + + const_iterator begin() const + { return cbegin(); } + const_iterator end() const + { return cend(); } + + const_reverse_iterator rbegin() const + { return crbegin(); } + const_reverse_iterator rend() const + { return crend(); } + + const_reverse_iterator crbegin() const + { return const_reverse_iterator(cend()); } + const_reverse_iterator crend() const + { return const_reverse_iterator(cbegin()); } + //@} + + /// @copydoc cci_value_cref::operator& + proxy_ptr operator&() const { return proxy_ptr(*this); } + +private: + // exclude non-list value functions + using base_type::get_bool; + using base_type::get_int; + using base_type::get_uint; + using base_type::get_int64; + using base_type::get_uint64; + using base_type::get_double; + using base_type::get_string; + using base_type::get_map; + +private: + // constant reference, no assignment + this_type& operator=( this_type const& ) /* = delete */; +}; + +// -------------------------------------------------------------------------- + +/// reference to mutable cci_value list value +class cci_value_list_ref + : public cci_value_list_cref +{ + friend class cci_value_ref; + typedef cci_value_list_cref base_type; + typedef cci_value_list_ref this_type; + typedef cci_impl::value_ptr proxy_ptr; + +protected: + explicit cci_value_list_ref(impl_type i = NULL) + : base_type(i) {} + +public: + this_type operator=( this_type const& ); + this_type operator=( base_type const& ); + + /// move contents to another value (becomes empty list afterwards) + cci_value move(); + + /// exchange contents with another list value + void swap( this_type& ); + friend void swap(this_type a, this_type b) { a.swap(b); } + + /// reserve space in underlying storage + this_type reserve( size_type ); + + /// clear list elements + this_type clear(); + + /** @name (mutable) element access by index + * @see cci_value_list_cref::at, cci_value_list_cref::operator[] + */ + //@{ + using base_type::operator[]; + ///@copydoc cci_value_list_cref::operator[] + reference operator[]( size_type index ); + + using base_type::at; + ///@copydoc cci_value_list_cref::at + reference at( size_type index ); + + using base_type::front; + ///@copydoc cci_value_list_cref::front + reference front() + { return (*this)[0]; } + + using base_type::back; + ///@copydoc cci_value_list_cref::back + reference back() + { return (*this)[size() - 1]; } + //@} + + /** @name (mutable) iterator interface */ + //@{ + using base_type::begin; + iterator begin(); + + using base_type::end; + iterator end(); + + using base_type::rbegin; + reverse_iterator rbegin() + { return reverse_iterator(end()); } + + using base_type::rend; + reverse_iterator rend() + { return reverse_iterator(begin()); } + //@} + + /** @name push new elements to the end of the list */ + //@{ + /// append value obtained from a constant cci_value reference + this_type push_back( const_reference v ); +#ifdef CCI_HAS_CXX_RVALUE_REFS + /// append value obtained from temporary cci_value rvalues + this_type push_back( cci_value && v ); +#endif // CCI_HAS_CXX_RVALUE_REFS + /// append arbitrary cci_value_converter enabled value + template + this_type push_back( const T & v +#ifndef CCI_DOXYGEN_IS_RUNNING + , CCI_VALUE_REQUIRES_CONVERTER_(T) +#endif // CCI_DOXYGEN_IS_RUNNING + ); + //@} + + /** @name insert elements into the list */ + //@{ + iterator insert( const_iterator pos, const_reference value ); + iterator insert( const_iterator pos, size_type count, const_reference value ); + template< class InputIt > + iterator insert( const_iterator pos, InputIt first, InputIt last ); + //@} + + /** @name erase elements from the list */ + //@{ + iterator erase( const_iterator pos ); + iterator erase( const_iterator first, const_iterator last ); + + void pop_back(); + //@} + + /// @copydoc cci_value_cref::operator& + proxy_ptr operator&() const { return proxy_ptr(*this); } +}; + +inline cci_value_list_ref +cci_value_list_ref::operator=( this_type const & that ) + { return *this = base_type(that); } + +inline cci_value_list_ref +cci_value_list_ref::operator=( base_type const & that ) + { cci_value_ref v(pimpl_); v = that; return *this; } + +inline cci_value_list_ref::reference +cci_value_list_ref::operator[]( size_type index ) + { return reference( base_type::operator[](index).pimpl_ ); } + +inline cci_value_list_ref::reference +cci_value_list_ref::at( size_type index ) + { return reference( base_type::at(index).pimpl_ ); } + +inline cci_value_list_ref +cci_value_ref::get_list() + { return cci_value_list_ref( base_type::get_list().pimpl_ ); } + +// -------------------------------------------------------------------------- + +/// reference to a constant cci_value map element +class cci_value_map_elem_cref +{ + template friend class cci_impl::value_iterator_impl; + typedef cci_impl::value_ptr proxy_ptr; + + typedef void value_type; // TODO: add explicit value_type +public: + typedef cci_value_map_elem_cref const_reference; + typedef cci_value_map_elem_ref reference; + + /// constant reference to the element's key + cci_value_string_cref key; + /// constant reference to the element's value + cci_value_cref value; + + /// @copydoc cci_value_cref::operator& + proxy_ptr operator&() const { return proxy_ptr(*this); } + + /// Does this reference point to the same value as another reference? + bool is_same(cci_value_map_elem_cref that) const { return pimpl_ == that.pimpl_; } + +protected: + typedef void* impl_type; // use type-punned pointer for now + impl_type pimpl_; + cci_value_map_elem_cref(impl_type i = NULL); +}; + +/// reference to a mutable cci_value map element +class cci_value_map_elem_ref +{ + template friend class cci_impl::value_iterator_impl; + typedef cci_impl::value_ptr proxy_ptr; + typedef void value_type; // TODO: add explicit value_type +public: + typedef cci_value_map_elem_cref const_reference; + typedef cci_value_map_elem_ref reference; + + /// constant reference to the element's key + cci_value_string_cref key; + /// mutable reference to the element's value + cci_value_ref value; + + /// @copydoc cci_value_cref::operator& + proxy_ptr operator&() const { return proxy_ptr(*this); } + +protected: + typedef void* impl_type; // use type-punned pointer for now + impl_type pimpl_; + cci_value_map_elem_ref(impl_type i = NULL); +}; + +///@cond CCI_HIDDEN_FROM_DOXYGEN +// iterator implementations in cci_value.cpp +namespace cci_impl { +CCI_TPLEXTERN_ template class value_iterator_impl; +CCI_TPLEXTERN_ template class value_iterator_impl; +} // namespace cci_impl +CCI_TPLEXTERN_ template class cci_value_iterator; +CCI_TPLEXTERN_ template class cci_value_iterator; +///@endcond + +/// reference to constant cci_value map +class cci_value_map_cref + : public cci_value_cref +{ + friend class cci_value_cref; + typedef cci_value_cref base_type; + typedef cci_value_map_cref this_type; + typedef cci_impl::value_ptr proxy_ptr; + +protected: + explicit cci_value_map_cref(impl_type i = NULL) + : base_type(i) {} + +public: + typedef size_t size_type; + typedef cci_value_iterator iterator; + typedef cci_value_iterator const_iterator; + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; + + /** @name map queries */ + //@{ + bool empty() const { return size() == 0; } + /// number of entries in the map + size_type size() const; + //@} + + /** @name map element queries + * Check for the existence of an entry with a given key + */ + //@{ + bool has_entry( const char * key ) const + { return NULL != do_lookup( key, std::strlen(key), KEY_OPTIONAL ); } + bool has_entry( std::string const & key ) const + { return NULL != do_lookup( key.c_str(), key.length(), KEY_OPTIONAL ); } + bool has_entry( cci_value_string_cref key ) const + { return NULL != do_lookup( key.c_str(), key.length(), KEY_OPTIONAL ); } + //@} + + /** @name (constant) map value access + * + * Accessing values in a constant map is only possible via the @ref at + * functions, which require the existence of an entry with the given key. + * + * @see has_entry, find, cci_value_map_ref::operator[] + */ + //@{ + /** @brief checked value access + * @note Access is checked, i.e. reports an error + * for value accesses through non-existent keys + */ + const_reference at( const char* key ) const + { return const_reference( do_lookup( key, std::strlen(key) ) ); } + ///@copydoc cci_value_map_cref::at(const char*) const + const_reference at( std::string const& key ) const + { return const_reference( do_lookup( key.c_str(), key.length() ) ); } + ///@} + + /** @name (constant) iterator interface */ + //@{ + const_iterator cbegin() const; + const_iterator cend() const; + + const_iterator begin() const + { return cbegin(); } + const_iterator end() const + { return cend(); } + + const_reverse_iterator rbegin() const + { return crbegin(); } + const_reverse_iterator rend() const + { return crend(); } + + const_reverse_iterator crbegin() const + { return const_reverse_iterator(cend()); } + const_reverse_iterator crend() const + { return const_reverse_iterator(cbegin()); } + //@} + + /** @name find (constant) entries in the map + * + * These overloads return a const_iterator pointing + * to an entry in the map and \ref end() otherwise. + * + * @see cci_value_map_ref::find + */ + //@{ + const_iterator find( const char* key ) const + { return do_find( key, std::strlen(key) ); } + const_iterator find( const std::string& key ) const + { return do_find( key.c_str(), key.length() ); } + //@} + + /// @copydoc cci_value_cref::operator& + proxy_ptr operator&() const { return proxy_ptr(*this); } + +protected: + enum lookup_mode { KEY_REQUIRED = 0, KEY_OPTIONAL, KEY_CREATE }; + impl_type do_lookup( const char* key, size_type keylen + , lookup_mode mode = KEY_REQUIRED ) const; + const_iterator do_find(const char* key, size_type keylen) const; + +private: + // exclude non-map value functions + using base_type::get_bool; + using base_type::get_int; + using base_type::get_uint; + using base_type::get_int64; + using base_type::get_uint64; + using base_type::get_double; + using base_type::get_string; + using base_type::get_list; + +private: + // constant reference, no assignment + this_type& operator=( this_type const& ) /* = delete */; +}; + +// -------------------------------------------------------------------------- + +/// reference to mutable cci_value map +class cci_value_map_ref + : public cci_value_map_cref +{ + friend class cci_value_ref; + typedef cci_value_map_cref base_type; + typedef cci_value_map_ref this_type; + typedef cci_impl::value_ptr proxy_ptr; +protected: + explicit cci_value_map_ref(impl_type i = NULL) + : base_type(i) {} + +public: + + this_type operator=( base_type const& ); + this_type operator=( this_type const& ); + + /// move contents to another value (becomes empty map afterwards) + cci_value move(); + + /// exchange contents with another map + void swap( this_type& ); + friend void swap(this_type a, this_type b) { a.swap(b); } + + /// clear map entries + this_type clear(); + + /** @name (mutable) map value access + * + * Accessing values in a mutable map is possible via @ref at() or + * @ref operator[], differing in their behavior for non-existent keys. + * + * @see has_entry, find, cci_value_map_cref::at + */ + //@{ + using base_type::at; + /// @copydoc cci_value_map_cref::at + reference at( const char* key ) + { return reference( do_lookup( key, std::strlen(key) ) ); } + /// @copydoc cci_value_map_cref::at + reference at( std::string const& key ) + { return reference( do_lookup( key.c_str(), key.length() ) ); } + /** @brief inserting value access + * @note If there is no entry with the requested key, a new entry + * with a @c null value will be created. + */ + reference operator[]( const char* key ) + { return reference( do_lookup( key, std::strlen(key), KEY_CREATE ) ); } + ///@copydoc cci_value_map_ref::operator[](const char*) + reference operator[]( std::string const& key ) + { return reference( do_lookup( key.c_str(), key.length(), KEY_CREATE ) ); } + //@} + + /** @name (mutable) iterator interface */ + //@{ + using base_type::begin; + iterator begin(); + + using base_type::end; + iterator end(); + + using base_type::rbegin; + reverse_iterator rbegin() + { return reverse_iterator(end()); } + + using base_type::rend; + reverse_iterator rend() + { return reverse_iterator(begin()); } + //@} + + /** @name find (mutable) elements in the map + * + * These overloads return an iterator pointing + * to an element in the map and \ref end() otherwise. + * + * @see cci_value_map_cref::find + */ + //@{ + iterator find( const char* key ) + { return iterator( do_find( key, std::strlen(key) ).raw() ); } + iterator find( const std::string& key ) + { return iterator( do_find( key.c_str(), key.length() ).raw() ); } + //@} + + ///@name map element addition + //@{ + /// add value obtained from a constant cci_value reference + this_type push_entry( const char* key, const_reference value ) + { return do_push( key, std::strlen(key), value ); } + + /// add value obtained from a constant cci_value reference + this_type push_entry( std::string const& key, const_reference value ) + { return do_push( key.c_str(), key.length(), value ); } + +#ifdef CCI_HAS_CXX_RVALUE_REFS + /// add value obtained from a temporary cci_value rvalue reference + this_type push_entry( const char* key, cci_value&& value ) + { return do_push( key, std::strlen(key), CCI_MOVE_(value) ); } + + /// add value obtained from a rvalue cci_value rvalue reference + this_type push_entry( std::string const& key, cci_value&& value ) + { return do_push( key.c_str(), key.length(), CCI_MOVE_(value) ); } +#endif // CCI_HAS_CXX_RVALUE_REFS + + /// add an arbitrary cci_value_converter enabled value + template + this_type push_entry( const char* key, const T & value +#ifndef CCI_DOXYGEN_IS_RUNNING + , CCI_VALUE_REQUIRES_CONVERTER_(T) +#endif + ) + { return do_push( key, std::strlen(key), value ); } + + /// add an arbitrary cci_value_converter enabled value + template + this_type push_entry( std::string const & key, const T & value +#ifndef CCI_DOXYGEN_IS_RUNNING + , CCI_VALUE_REQUIRES_CONVERTER_(T) +#endif + ) + { return do_push( key.c_str(), key.length(), value ); } + //@} + + /** @name erase elements from the map */ + //@{ + size_type erase( const char* key ) + { return do_erase( key, std::strlen(key) ); } + size_type erase( const std::string& key ) + { return do_erase( key.c_str(), key.length() ); } + + iterator erase( const_iterator pos ); + iterator erase( const_iterator first, const_iterator last ); + //@} + + /// @copydoc cci_value_cref::operator& + proxy_ptr operator&() const { return proxy_ptr(*this); } + +private: + template + this_type do_push(const char* key, size_type keylen, const T& value); + this_type do_push(const char* key, size_type keylen, const_reference value); +#ifdef CCI_HAS_CXX_RVALUE_REFS + this_type do_push(const char* key, size_type keylen, cci_value&& value); +#endif // CCI_HAS_CXX_RVALUE_REFS + size_type do_erase(const char* key, size_type keylen); +}; + +inline cci_value_map_ref +cci_value_map_ref::operator=( this_type const & that ) + { return *this = base_type(that); } + +inline cci_value_map_ref +cci_value_map_ref::operator=( base_type const & that ) + { cci_value_ref v(pimpl_); v = that; return *this; } + +inline cci_value_map_ref +cci_value_ref::get_map() + { return cci_value_map_ref( base_type::get_map().pimpl_ ); } + +// -------------------------------------------------------------------------- + +/** + * @brief generic variant type + * + * This class provides the first-class type for representing arbitrary values. + * It can represent its values via a set of primitive types: + * * @c null (default) + * * boolean values (@c true, @c false) + * * numeric values (signed/unsigned integral or floating-point numbers) + * * strings + * * lists of values + * * maps of (key, value) pairs + * + * First-class objects of this class have strict value semantics, i.e. each + * value represents a distinct object. Due to the hierarchical nature of the + * data structure, values embedded somewhere in a list or map are referenced + * by dedicated reference objects (cci_value_cref, cci_value_ref, and their + * specialized variants for strings, lists and maps), with or without constness. + * + * Users can add automatic conversions from/to cci_value objects by providing + * an implementation (or specialisation) of the cci_value_converter class. + * Corresponding specializations for the builtin types, the SystemC data types + * and some freuquently used standard types are provided by default already. + * + * \see cci_value_list, cci_value_map, cci_value_converter + */ +class cci_value + : public cci_value_ref +{ + typedef cci_value this_type; + friend class cci_value_ref; + friend class cci_value_string_ref; +public: + /// reference to a constant value + typedef cci_value_cref const_reference; + /// reference to a mutable value + typedef cci_value_ref reference; + /// reference to a constant string value + typedef cci_value_string_cref const_string_reference; + /// reference to a mutable string value + typedef cci_value_string_ref string_reference; + /// reference to a constant list value + typedef cci_value_list_cref const_list_reference; + /// reference to a mutable list value + typedef cci_value_list_ref list_reference; + /// reference to a constant map value + typedef cci_value_map_cref const_map_reference; + /// reference to a mutable map value + typedef cci_value_map_ref map_reference; + + /// default constructor + cci_value() + : cci_value_ref(), own_pimpl_() {} + + /// constructor from arbitrary cci_value_converter enabled value + template + explicit + cci_value( T const & src +#ifndef CCI_DOXYGEN_IS_RUNNING + , CCI_VALUE_REQUIRES_CONVERTER_(T) +#endif // CCI_DOXYGEN_IS_RUNNING + ); + + cci_value( this_type const & that ); + cci_value( const_reference that ); +#ifdef CCI_HAS_CXX_RVALUE_REFS + cci_value( this_type&& that ); + cci_value( cci_value_list&& that ); + cci_value( cci_value_map&& that ); +#endif // CCI_HAS_CXX_RVALUE_REFS + + this_type& operator=( this_type const & ); + this_type& operator=( const_reference ); +#ifdef CCI_HAS_CXX_RVALUE_REFS + this_type& operator=( this_type&& ); + this_type& operator=( cci_value_list&& ); + this_type& operator=( cci_value_map&& ); +#endif // CCI_HAS_CXX_RVALUE_REFS + + friend void swap(this_type& a, this_type& b) { a.swap(b); } + void swap( reference that ) { init(); reference::swap( that ); } + void swap( cci_value & that ); + + ~cci_value(); + + /** @name Set value functions + * \see cci_value_ref + */ + //@{ + /// @copydoc cci_value_ref::set + template< typename T > + reference set( T const & v +#ifndef CCI_DOXYGEN_IS_RUNNING + , CCI_VALUE_REQUIRES_CONVERTER_(T) +#endif // CCI_DOXYGEN_IS_RUNNING + ) + { init(); return reference::set(v); } + + /// @copydoc cci_value_ref::set_null + reference set_null() + { init(); return reference::set_null(); } + + /// @copydoc cci_value_ref::set_bool + reference set_bool( bool v ) + { init(); return reference::set_bool(v); } + + /// @copydoc cci_value_ref::set_int + reference set_int( int v ) + { init(); return reference::set_int(v); } + /// @copydoc cci_value_ref::set_uint + reference set_uint( unsigned v ) + { init(); return reference::set_uint(v); } + /// @copydoc cci_value_ref::set_int64 + reference set_int64( int64 v ) + { init(); return reference::set_int64(v); } + /// @copydoc cci_value_ref::set_uint64 + reference set_uint64(uint64 v) + { init(); return reference::set_uint64(v); } + + /// @copydoc cci_value_ref::set_double + reference set_double(double v) + { init(); return cci_value_ref::set_double(v); } + /// @copydoc cci_value_ref::set_number + reference set_number( double v ) + { return set_double(v); } + + /// @copydoc cci_value_ref::set_string(const char*) + string_reference set_string( const char* s ) + { init(); return reference::set_string(s); } + /// @copydoc cci_value_ref::set_string(const std::string&) + string_reference set_string( const std::string& s ) + { init(); return reference::set_string(s); } + /// @copydoc cci_value_ref::set_string(cci_value_string_cref) + string_reference set_string( const_string_reference s ) + { init(); return reference::set_string(s); } + + /// @copydoc cci_value_ref::set_list + list_reference set_list() + { init(); return cci_value_ref::set_list(); } + + /// @copydoc cci_value_ref::set_map + map_reference set_map() + { init(); return cci_value_ref::set_map(); } + //@} + + /** @name JSON (de)serialization + */ + + using const_reference::to_json; + static cci_value from_json( std::string const & json ); + + friend std::istream& operator>>( std::istream& is, this_type & v ) + { v.init(); return is >> reference(v); } + //@} + + /// @copydoc cci_value_cref::operator& + const cci_value * operator&() const { return this; } + /// @copydoc cci_value_cref::operator& + cci_value * operator&() { return this; } + +private: + impl_type init(); + impl_type do_init(); + + bool json_deserialize( std::string const & src ) + { init(); return reference::json_deserialize( src ); } + + impl_type own_pimpl_; +}; + +template +cci_value::cci_value( T const & v +#ifndef CCI_DOXYGEN_IS_RUNNING + , CCI_VALUE_CHECKED_CONVERTER_(T) +#endif // CCI_DOXYGEN_IS_RUNNING + ) + : cci_value_ref(), own_pimpl_() +{ + do_init(); + set(v); +} + +inline +cci_value::cci_value( this_type const & that ) + : reference(), own_pimpl_() +{ + *this = that; +} + +inline +cci_value::cci_value( const_reference that ) + : reference(), own_pimpl_() +{ + *this = that; +} + +inline cci_value & +cci_value::operator=( this_type const & that ) +{ + return *this = const_reference(that); +} + +inline cci_value::impl_type +cci_value::init() +{ + if( !pimpl_ ) + pimpl_ = do_init(); + return pimpl_; +} + +inline cci_value +cci_value::from_json( std::string const & json ) +{ + cci_value v; + bool ok = v.json_deserialize( json ); + sc_assert( ok ); + return v; +} + +// -------------------------------------------------------------------------- +// The following two functions depend on the completeness of the cci_value +// class, enforced by some compilers (e.g. Clang). + + +///@cond CCI_HIDDEN_FROM_DOXYGEN +#ifdef CCI_HAS_CXX_RVALUE_REFS +# define CCI_VALUE_MOVE_(v) CCI_MOVE_(v) +#else +# define CCI_VALUE_MOVE_(v) cci_value::const_reference(v) +#endif // CCI_HAS_CXX_RVALUE_REFS +///@endcond + +template +cci_value_list_ref::this_type +cci_value_list_ref::push_back( const T& value +#ifndef CCI_DOXYGEN_IS_RUNNING + , CCI_VALUE_CHECKED_CONVERTER_(T) +#endif // CCI_DOXYGEN_IS_RUNNING + ) +{ + cci_value v(value); + return push_back( CCI_VALUE_MOVE_(v) ); +} + +template +cci_value_map_ref +cci_value_map_ref::do_push( const char* key, size_type keylen, const T& value ) +{ + cci_value v(value); + return push_entry( key, CCI_VALUE_MOVE_(v) ); +} + +// -------------------------------------------------------------------------- + +/** + * @brief list of cci_value values + * + * This class is equivalent to a cci_value after calling @c set_list(). + * @see cci_value, cci_value_list_cref, cci_value_list_ref + */ +class cci_value_list + : public cci_value_list_ref +{ + friend class cci_value; + typedef cci_value_list this_type; +public: + typedef cci_value_list_cref const_reference; + typedef cci_value_list_ref reference; + + cci_value_list(); + + cci_value_list( this_type const & ); + cci_value_list( const_reference ); +#ifdef CCI_HAS_CXX_RVALUE_REFS + cci_value_list( this_type&& ); +#endif // CCI_HAS_CXX_RVALUE_REFS + + this_type& operator=( this_type const & ); + this_type& operator=( const_reference ); +#ifdef CCI_HAS_CXX_RVALUE_REFS + this_type& operator=( this_type && ); +#endif // CCI_HAS_CXX_RVALUE_REFS + + friend void swap(this_type& a, this_type& b) { a.swap(b); } + void swap( reference that ) { reference::swap( that ); } + void swap( this_type & ); + + ~cci_value_list(); + + ///@copydoc cci_value_cref::operator& + const cci_value_list * operator&() const { return this; } + ///@copydoc cci_value_cref::operator& + cci_value_list * operator&() { return this; } + +private: + impl_type do_init(); + impl_type own_pimpl_; +}; + +inline +cci_value_list::cci_value_list() + : reference(), own_pimpl_() +{ + do_init(); +} + +inline +cci_value_list::cci_value_list( this_type const & that ) + : reference(), own_pimpl_() +{ + do_init(); + *this = that; +} + +inline +cci_value_list::cci_value_list( const_reference that ) + : reference(), own_pimpl_() +{ + do_init(); + *this = that; +} + +inline cci_value_list & +cci_value_list::operator=( this_type const & that ) +{ + return *this = const_reference(that); +} + +// -------------------------------------------------------------------------- + +/** + * @brief map of (key, cci_value) pairs + * + * This class is equivalent to a cci_value after calling @c set_map(). + * @see cci_value, cci_value_map_cref, cci_value_map_ref + */ +class cci_value_map + : public cci_value_map_ref +{ + friend class cci_value; + typedef cci_value_map this_type; +public: + typedef cci_value_map_cref const_reference; + typedef cci_value_map_ref reference; + + cci_value_map(); + + cci_value_map( this_type const & ); + cci_value_map( const_reference ); +#ifdef CCI_HAS_CXX_RVALUE_REFS + cci_value_map( this_type && ); +#endif // CCI_HAS_CXX_RVALUE_REFS + + this_type& operator=( this_type const& ); + this_type& operator=( const_reference ); +#ifdef CCI_HAS_CXX_RVALUE_REFS + this_type& operator=( this_type && ); +#endif // CCI_HAS_CXX_RVALUE_REFS + + friend void swap(this_type& a, this_type& b) { a.swap(b); } + void swap( reference that ) { reference::swap( that ); } + void swap( this_type & ); + + ~cci_value_map(); + + /// @copydoc cci_value_cref::operator& + const cci_value_map * operator&() const { return this; } + /// @copydoc cci_value_cref::operator& + cci_value_map * operator&() { return this; } + +private: + impl_type do_init(); + impl_type own_pimpl_; +}; + +inline +cci_value_map::cci_value_map() + : reference(), own_pimpl_() +{ + do_init(); +} + +inline +cci_value_map::cci_value_map( this_type const & that ) + : reference(), own_pimpl_() +{ + do_init(); + *this = that; +} + +inline +cci_value_map::cci_value_map( const_reference that ) + : reference(), own_pimpl_() +{ + do_init(); + *this = that; +} + +inline cci_value_map & +cci_value_map::operator=( this_type const & that ) +{ + return *this = const_reference(that); +} + +// -------------------------------------------------------------------------- + +template +cci_value_list_ref::iterator +cci_value_list_ref::insert( const_iterator pos, InputIt first, InputIt last ) +{ + iterator::difference_type offs = pos - begin(); + while( first != last ) + pos = insert( pos, cci_value(*first++) ) + 1; + return begin() + offs; +} + +CCI_CLOSE_NAMESPACE_ + +#undef CCI_VALUE_CONVERTER_ +#undef CCI_VALUE_CHECKED_CONVERTER_ +#undef CCI_VALUE_REQUIRES_CONVERTER_ +#undef CCI_VALUE_MOVE_ + +#ifdef _MSC_VER +#pragma warning(pop) +#endif // _MSC_VER + +#endif // CCI_CCI_VALUE_H_INCLUDED_ diff --git a/third_party/cci-1.0.0/cci_core/cci_value_converter.cpp b/third_party/cci-1.0.0/cci_core/cci_value_converter.cpp new file mode 100644 index 000000000..36b057780 --- /dev/null +++ b/third_party/cci-1.0.0/cci_core/cci_value_converter.cpp @@ -0,0 +1,361 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + ****************************************************************************/ + +#if defined(_MSC_VER) && _MSC_VER <= 1600 +# pragma warning(disable:4661) +# define CCI_TPLEXTERN_ +#endif // excluded from MSVC'2010 + +#include "cci_core/cci_value_converter.h" + +/** + * @file cci_value_converter.cpp + * @brief conversions from and to a @ref cci_value (common types) + * @author Philipp A. Hartmann, OFFIS/Intel + */ + +CCI_OPEN_NAMESPACE_ + +#define DEFINE_PACK_( Type ) \ + template<> bool \ + cci_value_converter::pack( cci_value::reference dst, type const & src ) + +#define DEFINE_UNPACK_(Type) \ + template<> bool \ + cci_value_converter::unpack( type & dst, cci_value::const_reference src ) + +// ---------------------------------------------------------------------------- +// explicit template instantiations + +template struct cci_value_converter; +template struct cci_value_converter; +template struct cci_value_converter; +template struct cci_value_converter; +template struct cci_value_converter; +template struct cci_value_converter; +template struct cci_value_converter; + +template struct cci_value_converter; +template struct cci_value_converter; +template struct cci_value_converter; +template struct cci_value_converter; +template struct cci_value_converter; +template struct cci_value_converter; +template struct cci_value_converter; +template struct cci_value_converter; + +#ifdef SC_INCLUDE_FX +template struct cci_value_converter; +template struct cci_value_converter; +template struct cci_value_converter; +template struct cci_value_converter; +template struct cci_value_converter; +template struct cci_value_converter; +#endif // SC_INCLUDE_FX + +#ifndef CCI_DOXYGEN_IS_RUNNING +// ---------------------------------------------------------------------------- +// C++ builtin types + +#define DEFINE_BUILTIN_( Type, Alias ) \ + DEFINE_PACK_(Type) \ + { \ + dst.set_ ## Alias( src ); \ + return true; \ + } \ + DEFINE_UNPACK_(Type) \ + { \ + if( !src.is_ ## Alias() ) return false; \ + dst = src.get_ ## Alias(); \ + return true; \ + } + +DEFINE_BUILTIN_(bool, bool) +DEFINE_BUILTIN_(int, int) +DEFINE_BUILTIN_(int64, int64) +DEFINE_BUILTIN_(unsigned, uint) +DEFINE_BUILTIN_(uint64, uint64) +DEFINE_BUILTIN_(double, number) + +DEFINE_BUILTIN_(std::string, string) + +// ---------------------------------------------------------------------------- +// SystemC builtin types + +DEFINE_PACK_( sc_core::sc_time ) +{ +#if CCI_SYSTEMC_VERSION_CODE_ >= CCI_VERSION_HELPER_(2,3,2) + sc_core::sc_time_tuple tp = src; + dst.set_list() + .push_back( tp.value() ) + .push_back( tp.unit_symbol() ); +#else // print as seconds + dst.set_list() + .push_back( src.to_seconds() ) + .push_back( "s" ); +#endif + return true; +} + +static inline sc_core::sc_time sc_time_from_unit( unsigned unit ) +{ + ///@todo add error handling + sc_assert( unit <= sc_core::SC_SEC ); + sc_core::sc_time_unit tu = static_cast( unit ); + return sc_core::sc_time( 1, tu ); +} + +#if CCI_SYSTEMC_VERSION_CODE_ < CCI_VERSION_HELPER_(2,3,2) +static inline sc_core::sc_time sc_time_from_symbol( cci_value_string_cref sym ) +{ + static struct symbol + { + const char * sym[2]; + sc_core::sc_time_unit unit; + } + symbol_table[] = + { + { { "fs", "SC_FS" }, sc_core::SC_FS }, + { { "ps", "SC_PS" }, sc_core::SC_PS }, + { { "ns", "SC_NS" }, sc_core::SC_NS }, + { { "us", "SC_US" }, sc_core::SC_US }, + { { "ms", "SC_MS" }, sc_core::SC_MS }, + { { "s", "SC_SEC" }, sc_core::SC_SEC }, + { { "sec" }, sc_core::SC_SEC }, + { { NULL, NULL }, sc_core::sc_time_unit() } + }; + symbol* cursor = symbol_table; + while( *cursor->sym && !(sym == cursor->sym[0] || sym == cursor->sym[1] ) ) + cursor++; + + sc_assert( unsigned(cursor - symbol_table) < (sizeof(symbol_table)/sizeof(symbol) ) ); + return sc_time_from_unit( unsigned(cursor - symbol_table) ); +} +#endif // SystemC 2.3.2 + +DEFINE_UNPACK_( sc_core::sc_time ) +{ + cci_value value, unit; + // encoded as tuple + if( src.is_list() && src.get_list().size() == 2 ) + { + cci_value::const_list_reference l = src.get_list(); + value = l[0]; + unit = l[1]; + } + // encoded as map: "value"=, "unit"= + else if( src.is_map() && src.get_map().size() == 2 ) + { + cci_value::const_map_reference m = src.get_map(); + if( m.has_entry("value") && m.has_entry("unit") ) + { + value = m.at("value"); + unit = m.at("unit"); + } + } +#if CCI_SYSTEMC_VERSION_CODE_ >= CCI_VERSION_HELPER_(2,3,2) + // encoded as string: "NN " + else if( src.is_string() ) + { + dst = sc_core::sc_time::from_string( src.get_string().c_str() ); + return true; + } +#endif // SystemC 2.3.2 + + if( !value.is_number() ) + return false; + + if( unit.is_string() ) + { +#if CCI_SYSTEMC_VERSION_CODE_ >= CCI_VERSION_HELPER_(2,3,2) + dst = sc_core::sc_time( value.get_double(), unit.get_string().c_str() ); +#else + dst = value.get_double() * sc_time_from_symbol( unit.get_string() ); +#endif // SystemC 2.3.2 + return true; + } + else if( unit.is_uint() && unit.get_uint() <= sc_core::SC_SEC ) + { + dst = value.get_double() * sc_time_from_unit( unit.get_uint() ) ; + return true; + } + return false; +} + +DEFINE_BUILTIN_( sc_dt::sc_bit, bool ) + +DEFINE_PACK_( sc_dt::sc_logic ) +{ + switch( src.value() ) + { + case sc_dt::Log_0: + case sc_dt::Log_1: + dst.set_bool( src.to_bool() ); + break; + default: + dst.set_string( std::string( 1, src.to_char() ) ); + break; + } + return true; +} + +DEFINE_UNPACK_( sc_dt::sc_logic ) +{ + if( src.is_bool() ) + { + dst = src.get_bool(); + return true; + } + else if( src.is_int() ) + { + dst = sc_dt::sc_logic( src.get_int() ); + return true; + } + else if( src.is_string() && src.get_string().size() == 1 ) + { + switch( src.get_string()[0] ) + { + case '0': dst = sc_dt::SC_LOGIC_0; return true; + case '1': dst = sc_dt::SC_LOGIC_1; return true; + case 'z': /* fallthrough */ + case 'Z': dst = sc_dt::SC_LOGIC_Z; return true; + case 'x': /* fallthrough */ + case 'X': dst = sc_dt::SC_LOGIC_X; return true; + default: /* nothing */ ; + } + } + return false; +} + +DEFINE_PACK_( sc_dt::sc_int_base ) +{ + dst.set_int64( src ); + return true; +} + +DEFINE_UNPACK_( sc_dt::sc_int_base ) +{ + if( src.is_int64() ) + dst = src.get_int64(); + else if( src.is_string() ) + dst = src.get_string().c_str(); + else + return false; + + return true; +} + +DEFINE_PACK_( sc_dt::sc_uint_base ) +{ + dst.set_uint64( src ); + return true; +} + +DEFINE_UNPACK_( sc_dt::sc_uint_base ) +{ + if( src.is_uint64() ) + dst = src.get_uint64(); + else if( src.is_string() ) + dst = src.get_string().c_str(); + else + return false; + + return true; +} + +DEFINE_PACK_( sc_dt::sc_signed ) +{ + if( src.length() <= 64 ) + dst.set_int64( src.to_int64() ); + else + dst.set_string( src.to_string() ); + + return true; +} + +DEFINE_UNPACK_( sc_dt::sc_signed ) +{ + ///@todo add bounds checks + if( src.is_int64() ) + dst = src.get_int64(); + else if( src.is_string() ) + dst = src.get_string().c_str(); + else + return false; + + return true; +} + +DEFINE_PACK_( sc_dt::sc_unsigned ) +{ + if( src.length() <= 64 ) + dst.set_uint64( src.to_uint64() ); + else + dst.set_string( src.to_string() ); + + return true; +} + +DEFINE_UNPACK_( sc_dt::sc_unsigned ) +{ + ///@todo add bounds checks + if( src.is_uint64() ) + dst = src.get_uint64(); + else if( src.is_string() ) + dst = src.get_string().c_str(); + else + return false; + + return true; +} + +DEFINE_PACK_( sc_dt::sc_bv_base ) +{ + dst.set_string( src.to_string() ); + return true; +} + +DEFINE_UNPACK_( sc_dt::sc_bv_base ) +{ + ///@todo add bounds checks + if( !src.is_string() ) + return false; + + dst = src.get_string().c_str(); + return true; +} + +DEFINE_PACK_( sc_dt::sc_lv_base ) +{ + dst.set_string( src.to_string() ); + return true; +} + +DEFINE_UNPACK_( sc_dt::sc_lv_base ) +{ + ///@todo add bounds checks + if( !src.is_string() ) + return false; + + dst = src.get_string().c_str(); + return true; +} + +#endif // CCI_DOXYGEN_IS_RUNNING +CCI_CLOSE_NAMESPACE_ diff --git a/third_party/cci-1.0.0/cci_core/cci_value_converter.h b/third_party/cci-1.0.0/cci_core/cci_value_converter.h new file mode 100644 index 000000000..26b038f3d --- /dev/null +++ b/third_party/cci-1.0.0/cci_core/cci_value_converter.h @@ -0,0 +1,412 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + ****************************************************************************/ +#ifndef CCI_CCI_VALUE_CONVERTER_H_INCLUDED_ +#define CCI_CCI_VALUE_CONVERTER_H_INCLUDED_ +/** + * @file cci_value_converter.h + * @brief conversions from and to a @ref cci::cci_value + * @author Philipp A. Hartmann, OFFIS/Intel + */ + +#include "cci_core/systemc.h" +#include "cci_core/cci_value.h" + +#include // std::strncpy + +CCI_OPEN_NAMESPACE_ + +/** + * @class cci_value_converter + * @brief traits class for cci_value conversions + * @tparam T C++ datatype to convert to/from @ref cci_value + * + * Whenever a C++ type @c T is used in conjunction with a cci_value, + * the requireed value conversion is performed by this traits class, + * providing the two conversion functions @ref pack and @ref unpack. + * Both functions return @c true upon success and @c false otherwise. + * In case of a failing conversion, it is recommended to leave the given + * destination object @c dst untouched. + * + * @note By default, the primary template is not implemented to + * enable instantiations with incomplete types. + * + * You only need to implement the two functions @ref pack / @ref unpack + * to enable conversion support for your custom datatype: + * @code + * struct my_int { int value; }; + * + * template<> bool + * cci_value_converter::pack( cci_value::reference dst, type const & src ) + * { + * dst.set_int( src.value ); + * return true; + * } + * template<> bool + * cci_value_converter::unpack( type & dst, cci_value::const_reference src ) + * { + * if( ! src.is_int() ) return false; + * dst.value = src.get_int(); + * return true; + * } + * @endcode + * + * To @em disable conversion support for a given type, you can refer + * to the helper template @ref cci_value_converter_disabled. + * + * Predefined converters + * @li C++ fundamental types: + * @c bool, @c (unsigned) @c char, @c (unsigned) @c short, + * @c (unsigned) @c int, @c (unsigned) @c long, + * @c float, @c double + * @li @c std::string + * @li SystemC data types: + * @c sc_dt::int64, @c sc_dt::uint64, @c sc_dt::sc_logic, + * @c sc_dt::sc_int_base, @c sc_dt::sc_uint_base, + * @c sc_dt::sc_signed, @c sc_dt::sc_unsigned, @c sc_dt::sc_bv_base + * @c sc_dt::sc_lv_base and their templated variants + * @li SystemC time (@c sc_core::sc_time) + * @li Fixed-size C++ arrays and @c std::vector of supported types + * + * @note SystemC fixpoint type support is prepared, but not yet implemented. + */ +template +struct cci_value_converter +{ + typedef T type; ///< common type alias + /// convert from \ref type value to a cci_value + static bool pack( cci_value::reference dst, type const & src ); + /// convert from cci_value to a \ref type value + static bool unpack( type & dst, cci_value::const_reference src ); +}; + +// --------------------------------------------------------------------------- +/** + * @brief helper to disable cci_value conversion for a given type + * @tparam T type without cci_value conversions + * + * In order to disable the conversion from/to a cci_value for a given type + * @c T during @em run-time, you can simply inherit from this helper in + * the specialization of cci_value_converter: + * @code + * struct my_type { ... }; + * template<> + * struct cci_value_converter + * : cci_value_converter_disabled {}; + * @endcode + * + * \note In order to disable support for a given type at @em compile-time, + * the specialization of cci_value_converter can be left empty. + */ +template< typename T > +struct cci_value_converter_disabled +{ + typedef T type; + static bool pack( cci_value::reference, T const & ) { return false; } + static bool unpack( type &, cci_value::const_reference ) { return false; } +}; + +///@cond CCI_HIDDEN_FROM_DOXYGEN + +// --------------------------------------------------------------------------- +// disallowed implementation as a safety guard + +template struct cci_value_converter { /* disallowed */ }; + +template<> struct cci_value_converter { /* disallowed */ }; +template<> struct cci_value_converter { /* disallowed */ }; +template<> struct cci_value_converter { /* disallowed */ }; +template<> struct cci_value_converter { /* disallowed */ }; +template<> struct cci_value_converter { /* disallowed */ }; +template<> struct cci_value_converter { /* disallowed */ }; +template<> struct cci_value_converter { /* disallowed */ }; +template<> struct cci_value_converter { /* disallowed */ }; +template<> struct cci_value_converter { /* disallowed */ }; + +// --------------------------------------------------------------------------- +/// helper to convert compatible types (implementation artefact) +template< typename T, typename U > +struct cci_value_delegate_converter +{ + typedef T type; + typedef cci_value_converter traits_type; + + static bool pack( cci_value::reference dst, type const & src ) + { + return traits_type::pack( dst, static_cast(src) ); + } + + static bool unpack( type & dst, cci_value::const_reference src ) + { + U u_dst; + bool ret = traits_type::unpack( u_dst, src ); + if( ret ) + dst = static_cast(u_dst); + return ret; + } +}; + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4231) // extern template +#endif // _MSC_VER + +// -------------------------------------------------------------------------- +// C++ builtin types + +// default instantiations (in cci_value_converter.cpp) +CCI_TPLEXTERN_ template struct cci_value_converter; +CCI_TPLEXTERN_ template struct cci_value_converter; +CCI_TPLEXTERN_ template struct cci_value_converter; +CCI_TPLEXTERN_ template struct cci_value_converter; +CCI_TPLEXTERN_ template struct cci_value_converter; +CCI_TPLEXTERN_ template struct cci_value_converter; +CCI_TPLEXTERN_ template struct cci_value_converter; + +// related numerical types +// (without range checks for now) + +#define CCI_VALUE_CONVERTER_DERIVED_( UnderlyingType, SpecializedType ) \ + template<> \ + struct cci_value_converter \ + : cci_value_delegate_converter {} + +CCI_VALUE_CONVERTER_DERIVED_( int, char ); +CCI_VALUE_CONVERTER_DERIVED_( int, signed char ); +CCI_VALUE_CONVERTER_DERIVED_( int, short ); +CCI_VALUE_CONVERTER_DERIVED_( unsigned, unsigned char ); +CCI_VALUE_CONVERTER_DERIVED_( unsigned, unsigned short ); +CCI_VALUE_CONVERTER_DERIVED_( int64, long ); +CCI_VALUE_CONVERTER_DERIVED_( uint64, unsigned long ); +CCI_VALUE_CONVERTER_DERIVED_( double, float ); + +#undef CCI_VALUE_CONVERTER_DERIVED_ +///@endcond + +// ---------------------------------------------------------------------------- +// C++ string literals + +template +struct cci_value_converter +{ + typedef char type[N]; ///< common type alias + static bool pack( cci_value::reference dst, type const & src ) + { + dst.set_string( src ); + return true; + } + static bool unpack( type & dst, cci_value::const_reference src ) + { + if( src.is_null() ) + { + dst[0] = '\0'; // convert "null" to empty string + return true; + } + if( !src.is_string() ) + return false; + + cci_value::const_string_reference str = src.get_string(); + std::strncpy( dst, str.c_str(), N-1 ); + dst[N-1] = '\0'; + return ( str.size() <= N-1 ); + } +}; + +// ---------------------------------------------------------------------------- +// C++ arrays + +template +struct cci_value_converter +{ + typedef T type[N]; ///< common type alias + static bool pack( cci_value::reference dst, type const & src ) + { + cci_value_list ret; + ret.reserve( N ); + + for( size_t i = 0; i < N; ++i ) + ret.push_back( src[i] ); + ret.swap( dst.set_list() ); + return true; + } + static bool unpack( type & dst, cci_value::const_reference src ) + { + if( !src.is_list() ) + return false; + + cci_value::const_list_reference lst = src.get_list(); + size_t i = 0; + for( ; i < N && i < lst.size() && lst[i].try_get( dst[i] ); ++i ) {} + + return ( i == lst.size() ); + } +}; + +template +struct cci_value_converter : cci_value_converter +{ + typedef const T type[N]; ///< common type alias + // deliberately not implemented + static bool unpack( type & dst, cci_value::const_reference src ); +}; + +// ---------------------------------------------------------------------------- +// std::vector + +template< typename T, typename Alloc > +struct cci_value_converter< std::vector > +{ + typedef std::vector type; ///< common type alias + static bool pack( cci_value::reference dst, type const & src ) + { + cci_value_list ret; + ret.reserve( src.size() ); + + for( size_t i = 0; i < src.size(); ++i ) + ret.push_back( src[i] ); + ret.swap( dst.set_list() ); + return true; + } + static bool unpack( type & dst, cci_value::const_reference src ) + { + if( !src.is_list() ) + return false; + + cci_value::const_list_reference lst = src.get_list(); + type ret; + T cur; + size_t i = 0; + ret.reserve( lst.size() ); + for( ; i < lst.size() && lst[i].try_get(cur); ++i ) + ret.push_back( cur ); + + return ( i == lst.size() ) ? ( dst.swap(ret), true) : false; + } +}; + +// ---------------------------------------------------------------------------- +// SystemC builtin types + +// default instantiations (in cci_value_converter.cpp) +CCI_TPLEXTERN_ template struct cci_value_converter; +CCI_TPLEXTERN_ template struct cci_value_converter; +CCI_TPLEXTERN_ template struct cci_value_converter; +CCI_TPLEXTERN_ template struct cci_value_converter; +CCI_TPLEXTERN_ template struct cci_value_converter; +CCI_TPLEXTERN_ template struct cci_value_converter; +CCI_TPLEXTERN_ template struct cci_value_converter; +CCI_TPLEXTERN_ template struct cci_value_converter; + +/// @see cci_value_converter primary template +template +struct cci_value_converter< sc_dt::sc_int > + : cci_value_converter< sc_dt::sc_int_base > +{ + typedef sc_dt::sc_int type; +}; + +/// @see cci_value_converter primary template +template +struct cci_value_converter< sc_dt::sc_uint > + : cci_value_converter< sc_dt::sc_uint_base > +{ + typedef sc_dt::sc_uint type; +}; + +/// @see cci_value_converter primary template +template +struct cci_value_converter< sc_dt::sc_bigint > + : cci_value_converter< sc_dt::sc_signed > +{ + typedef sc_dt::sc_bigint type; +}; + +/// @see cci_value_converter primary template +template +struct cci_value_converter< sc_dt::sc_biguint > + : cci_value_converter< sc_dt::sc_unsigned > +{ + typedef sc_dt::sc_biguint type; +}; + +/// @see cci_value_converter primary template +template +struct cci_value_converter< sc_dt::sc_bv > + : cci_value_converter< sc_dt::sc_bv_base > +{ + typedef sc_dt::sc_bv type; +}; + +/// @see cci_value_converter primary template +template +struct cci_value_converter< sc_dt::sc_lv > + : cci_value_converter< sc_dt::sc_lv_base > +{ + typedef sc_dt::sc_lv type; +}; + +CCI_CLOSE_NAMESPACE_ + +#endif // CCI_CCI_VALUE_CONVERTER_H_INCLUDED_ + +///@todo add support for SystemC fixpoint types +#if defined(SC_INCLUDE_FX) && !defined(CCI_CNF_CCI_VALUE_CONVERTER_H_INCLUDED_FX_) +#define CCI_CNF_CCI_VALUE_CONVERTER_H_INCLUDED_FX_ +CCI_OPEN_NAMESPACE_ + +CCI_TPLEXTERN_ template struct cci_value_converter; +CCI_TPLEXTERN_ template struct cci_value_converter; +CCI_TPLEXTERN_ template struct cci_value_converter; +CCI_TPLEXTERN_ template struct cci_value_converter; +CCI_TPLEXTERN_ template struct cci_value_converter; +CCI_TPLEXTERN_ template struct cci_value_converter; + +template +struct cci_value_converter< sc_dt::sc_fixed > + : cci_value_converter< sc_dt::sc_fix > +{ + typedef sc_dt::sc_fixed type; +}; + +template +struct cci_value_converter< sc_dt::sc_fixed_fast > + : cci_value_converter< sc_dt::sc_fix_fast > +{ + typedef sc_dt::sc_fixed_fast type; +}; + +template +struct cci_value_converter< sc_dt::sc_ufixed > + : cci_value_converter< sc_dt::sc_ufix > +{ + typedef sc_dt::sc_ufixed type; +}; + +template +struct cci_value_converter< sc_dt::sc_ufixed_fast > + : cci_value_converter< sc_dt::sc_ufix_fast > +{ + typedef sc_dt::sc_ufixed_fast type; +}; + +#ifdef _MSC_VER +#pragma warning(pop) +#endif // _MSC_VER + +CCI_CLOSE_NAMESPACE_ +#endif // SC_INCLUDE_FX && ! CCI_CNF_CCI_VALUE_CONVERTER_H_INCLUDED_FX_ diff --git a/third_party/cci-1.0.0/cci_core/cci_value_iterator.h b/third_party/cci-1.0.0/cci_core/cci_value_iterator.h new file mode 100644 index 000000000..f53235c8a --- /dev/null +++ b/third_party/cci-1.0.0/cci_core/cci_value_iterator.h @@ -0,0 +1,190 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + ****************************************************************************/ + +#ifndef CCI_CORE_CCI_VALUE_ITERATOR_H_INCLUDED_ +#define CCI_CORE_CCI_VALUE_ITERATOR_H_INCLUDED_ + +#include // std::iterator_traits, std::reverse_iterator +#include "cci_core/cci_cmnhdr.h" + +/** + * @file cci_value_iterator.h + * @author Philipp A. Hartmann, Intel + */ + +CCI_OPEN_NAMESPACE_ + +// forward declarations +class cci_value; +class cci_value_cref; +class cci_value_ref; +class cci_value_list_cref; +class cci_value_list_ref; +class cci_value_map_cref; +class cci_value_map_ref; +class cci_value_map_elem_ref; +class cci_value_map_elem_cref; +template class cci_value_iterator; + +///@cond CCI_HIDDEN_FROM_DOXYGEN +namespace cci_impl { + +/// helper class to avoid dangling pointers to cci_value reference objects +template struct value_ptr +{ + typedef T element_type; + + explicit value_ptr(const T& ref) : ref_(ref) {} + + T& operator*() { return ref_; } + T* operator->() { return ptr(); } + + bool operator==(const value_ptr& that) const { return ref_.is_same() == (*that).is_same(); } + bool operator!=(const value_ptr& that) const { return !(*this == that); } + + static value_ptr pointer_to(element_type& elem) { return value_ptr(elem); } + +private: + // avoid addressof operator + T* ptr() { return reinterpret_cast(&reinterpret_cast(ref_)); } + T ref_; // extend lifetime of reference +}; + +/// helper class to implement a cci_value_iterator +template class value_iterator_impl +{ +public: + // std::iterator_traits types + typedef T reference; // return by value! + typedef value_ptr pointer; // return proxy pointer + typedef typename T::value_type value_type; // "real" value type + typedef std::ptrdiff_t difference_type; + typedef std::random_access_iterator_tag iterator_category; + +protected: + typedef void* impl_type; // type-punned pointer for now + + value_iterator_impl(impl_type r = NULL) + : impl_(r) {} + + void increment(difference_type n = 1) { update(advance(n)); } + void decrement(difference_type n = 1) { update(advance(-n)); } + impl_type advance(difference_type n) const; + + difference_type distance(impl_type) const; + + int compare(impl_type) const; + + pointer ptr() const { return pointer(deref()); } + reference deref() const { return reference(raw()); } + impl_type raw() const { return impl_; } + +private: + void update(impl_type i) { impl_ = i; } + + impl_type impl_; // underlying iterator, +}; + +} // namespace cci_impl +///@endcond + +/** + * @brief Generic iterator impementation for \ref cci_value lists and maps + * + * @see cci_value_list, cci_value_map + */ +template +class cci_value_iterator + : protected cci_impl::value_iterator_impl +{ + typedef cci_impl::value_iterator_impl impl; + typedef cci_value_iterator const_type; + typedef cci_value_iterator nonconst_type; + + friend class cci_value_list_cref; + friend class cci_value_list_ref; + friend class cci_value_map_cref; + friend class cci_value_map_ref; + template friend class cci_value_iterator; + +private: + /// internal constructor + cci_value_iterator(typename impl::impl_type r) : impl(r) {} + +public: + /// @name C++ standard iterator types + ///@{ + typedef typename impl::value_type value_type; + typedef typename impl::pointer pointer; + typedef typename impl::reference reference; + typedef typename impl::difference_type difference_type; + typedef typename impl::iterator_category iterator_category; + ///@} + + /// constructs an invalid iterator (non-dereferencable, non-incrementable) + cci_value_iterator() : impl() {} + /// constructs an iterator from a potentially less \c const iterator + cci_value_iterator(const nonconst_type & that) + : impl(that.raw()) {} + + /// @name Unary increment/decrement operators + ///@{ + cci_value_iterator& operator++(){ impl::increment(); return *this; } + cci_value_iterator& operator--(){ impl::decrement(); return *this; } + cci_value_iterator operator++(int){ cci_value_iterator old(*this); impl::increment(); return old; } + cci_value_iterator operator--(int){ cci_value_iterator old(*this); impl::decrement(); return old; } + ///@} + + /// @name Binary increment/decrement operators + ///@{ + cci_value_iterator operator+( difference_type n ) const { return cci_value_iterator( impl::advance(n) ); } + cci_value_iterator operator-( difference_type n ) const { return cci_value_iterator( impl::advance(-n) ); } + + cci_value_iterator& operator+=( difference_type n ) { impl::increment(n); return *this; } + cci_value_iterator& operator-=( difference_type n ) { impl::decrement(n); return *this; } + ///@} + + /** @name Comparison between iterators + * @note These operator support comparisons between compatible const/non-const iterators. + */ + ///@{ + bool operator==( const_type that ) const { return impl::compare(that.raw()) == 0; } + bool operator!=( const_type that ) const { return impl::compare(that.raw()) != 0; } + bool operator<=( const_type that ) const { return impl::compare(that.raw()) <= 0; } + bool operator>=( const_type that ) const { return impl::compare(that.raw()) >= 0; } + bool operator< ( const_type that ) const { return impl::compare(that.raw()) < 0; } + bool operator> ( const_type that ) const { return impl::compare(that.raw()) > 0; } + ///@} + + /// @name Dereferencing the iterator + ///@{ + pointer operator&() const { return impl::ptr(); } + pointer operator->() const { return impl::ptr(); } + reference operator*() const { return impl::deref(); } + reference operator[]( difference_type n ) const { return (*this + n).deref(); } + ///@} + + /// Computing the distance between two iterators (from the same range) + difference_type operator-( const_type that ) const { return impl::distance(that.raw()); } + +}; // class cci_value_iterator + +CCI_CLOSE_NAMESPACE_ + +#endif // CCI_CORE_CCI_VALUE_ITERATOR_H_INCLUDED_ diff --git a/third_party/cci-1.0.0/cci_core/cci_version.h b/third_party/cci-1.0.0/cci_core/cci_version.h new file mode 100644 index 000000000..947837276 --- /dev/null +++ b/third_party/cci-1.0.0/cci_core/cci_version.h @@ -0,0 +1,62 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + ****************************************************************************/ + +/** + * @file cci_version.h + * @brief basic version information for CCI + * @author Philipp A. Hartmann, OFFIS/Intel + * + */ +#ifndef CCI_CORE_CCI_VERSION_H_INCLUDED_ +#define CCI_CORE_CCI_VERSION_H_INCLUDED_ + +#define CCI_SHORT_RELEASE_DATE 20180613 + +#define CCI_VERSION_ORIGINATOR "Accellera" +#define CCI_VERSION_MAJOR 1 +#define CCI_VERSION_MINOR 0 +#define CCI_VERSION_PATCH 0 +#define CCI_IS_PRERELEASE 0 + +// token stringification + +#define CCI_STRINGIFY_HELPER_( Arg ) \ + CCI_STRINGIFY_HELPER_DEFERRED_( Arg ) +#define CCI_STRINGIFY_HELPER_DEFERRED_( Arg ) \ + CCI_STRINGIFY_HELPER_MORE_DEFERRED_( Arg ) +#define CCI_STRINGIFY_HELPER_MORE_DEFERRED_( Arg ) \ + #Arg + +#define CCI_VERSION_RELEASE_DATE \ + CCI_STRINGIFY_HELPER_( CCI_SHORT_RELEASE_DATE ) + +#if ( CCI_IS_PRERELEASE == 1 ) +# define CCI_VERSION_PRERELEASE "pub_rev" +# define CCI_VERSION \ + CCI_STRINGIFY_HELPER_( CCI_VERSION_MAJOR.CCI_VERSION_MINOR.CCI_VERSION_PATCH ) \ + "_" CCI_VERSION_PRERELEASE "_" CCI_VERSION_RELEASE_DATE \ + "-" CCI_VERSION_ORIGINATOR +#else +# define CCI_VERSION_PRERELEASE "" // nothing +# define CCI_VERSION \ + CCI_STRINGIFY_HELPER_( CCI_VERSION_MAJOR.CCI_VERSION_MINOR.CCI_VERSION_PATCH ) \ + "-" CCI_VERSION_ORIGINATOR +#endif + +#endif // CCI_CORE_CCI_VERSION_H_INCLUDED_ diff --git a/third_party/cci-1.0.0/cci_core/rapidjson.h b/third_party/cci-1.0.0/cci_core/rapidjson.h new file mode 100644 index 000000000..3f42e3bf2 --- /dev/null +++ b/third_party/cci-1.0.0/cci_core/rapidjson.h @@ -0,0 +1,136 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + ****************************************************************************/ + +/** + * @file rapidjson.h + * @brief internal include file for the RapidJSON library + * @author Philipp A. Hartmann, OFFIS/Intel + * + * This file provides a local indirection to include RapidJSON from within + * the CCI library. RapidJSON is used for serialization from/to + * @ref cci_value. + * + * @note This file is @b not part of the public API! + */ + +#ifndef CCI_CORE_RAPIDJSON_H_INCLUDED_ +#define CCI_CORE_RAPIDJSON_H_INCLUDED_ + +///@cond CCI_HIDDEN_FROM_DOXYGEN + +#include +#include +#include "cci_core/cci_cmnhdr.h" + +// -------------------------------------------------------------------------- +// configure RapidJSON + +#define RAPIDJSON_NAMESPACE \ + CCI_NAMESPACE::cci_impl::json +#define RAPIDJSON_NAMESPACE_BEGIN \ + CCI_OPEN_NAMESPACE_ namespace cci_impl { namespace json { +#define RAPIDJSON_NAMESPACE_END \ + } } CCI_CLOSE_NAMESPACE_ + +// enable support for std::string +#define RAPIDJSON_HAS_STD_STRING 1 + +// parse floating point numbers with full precision +#define RAPIDJSON_PARSE_DEFAULT_FLAGS \ + ::RAPIDJSON_NAMESPACE::kParseFullPrecisionFlag + +// don't use explicit member iterator class +#define RAPIDJSON_NOMEMBERITERATORCLASS 1 + +RAPIDJSON_NAMESPACE_BEGIN + +struct AssertException + : std::logic_error +{ + AssertException( const char* msg ) + : std::logic_error(msg) {} +}; + +// throw on failing assertions +#define RAPIDJSON_ASSERT( expr ) \ + ((void)(( expr ) ? 0 : \ + ( throw ::RAPIDJSON_NAMESPACE::AssertException( #expr ), 0 ))) + +RAPIDJSON_NAMESPACE_END + +#include "rapidjson/rapidjson.h" + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +#if __GNUC__ >= 6 +RAPIDJSON_DIAG_OFF( terminate ) // ignore throwing assertions +#endif +#endif + +// throw exception by default +#define RAPIDJSON_PARSE_ERROR_EARLY_RETURN( what ) \ + ((void)0) +#define RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode,offset) \ + throw ::RAPIDJSON_NAMESPACE::ParseException( \ + ::RAPIDJSON_NAMESPACE::parseErrorCode, \ + #parseErrorCode,offset \ + ) + +#include "rapidjson/error/error.h" +#include "rapidjson/error/en.h" + +RAPIDJSON_NAMESPACE_BEGIN + +struct ParseException + : std::runtime_error, ParseResult +{ + ParseException( ParseErrorCode code, const char* msg, size_t offset ) + : std::runtime_error(msg), ParseResult(code,offset) {} +}; + +struct StringOutputStream +{ + typedef char Ch; + + explicit StringOutputStream(std::string& s) : s_(s) {} + + void Put(Ch c) { s_.push_back(c); } + void Clear() { s_.clear(); } + void Flush() { return; } + size_t Size() const { return s_.length(); } + + friend void PutReserve(StringOutputStream &stream, size_t count) + { stream.s_.reserve(stream.Size() + count); } + +private: + std::string& s_; +}; + +RAPIDJSON_NAMESPACE_END + +#include "rapidjson/document.h" +#include "rapidjson/istreamwrapper.h" +#include "rapidjson/ostreamwrapper.h" +#include "rapidjson/writer.h" + +#ifdef __GNUC__ +RAPIDJSON_DIAG_POP +#endif +///@endcond +#endif // CCI_CORE_RAPIDJSON_H_INCLUDED_ diff --git a/third_party/cci-1.0.0/cci_core/systemc.h b/third_party/cci-1.0.0/cci_core/systemc.h new file mode 100644 index 000000000..c496a38c0 --- /dev/null +++ b/third_party/cci-1.0.0/cci_core/systemc.h @@ -0,0 +1,100 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + ****************************************************************************/ + +/** + * @file systemc.h + * @brief include SystemC from within the CCI library + * @author Thomas Goodfellow, OFFIS + * @author Philipp A. Hartmann, OFFIS/Intel + * + * This file provides a local indirection to include SystemC from within + * the CCI library. Prefer this file over direct inclusion of the SystemC + * header inside the CCI implementation(s). + * + * Some features not yet present in some (supported) versions of SystemC + * may require local workarounds, e.g. @ref sc_core::sc_get_current_object() + * (added in SystemC 2.3.1). + * + */ + +#ifndef CCI_CORE_SYSTEMC_H_INCLUDED_ +#define CCI_CORE_SYSTEMC_H_INCLUDED_ + +#if defined(_MSC_VER) +#pragma warning( push ) +#pragma warning( disable: 4244 ) +#pragma warning( disable: 4267 ) +#endif + +// Required by CCI callback mechanism using sc_unnamed bind argument +#ifndef SC_INCLUDE_DYNAMIC_PROCESSES +# define SC_INCLUDE_DYNAMIC_PROCESSES +#endif + +#include +#ifdef NCSC +namespace sc_core { +inline sc_object* +sc_get_current_object() { + return sc_get_curr_simcontext()->active_object(); +} +} +# include +#endif + +#if defined(_MSC_VER) +#pragma warning( pop ) +#endif + +#ifdef SC_VERSION_HELPER_ +# define CCI_VERSION_HELPER_ \ + SC_VERSION_HELPER_ +# else +# define CCI_VERSION_HELPER_(Major,Minor,Patch) \ + (((Major)*100000) + ((Minor)*100) + (Patch)) +#endif + +#ifdef SC_VERSION_CODE +# define CCI_SYSTEMC_VERSION_CODE_ \ + SC_VERSION_CODE + +#elif defined(IEEE_1666_SYSTEMC) +# define CCI_SYSTEMC_VERSION_CODE_ \ + CCI_VERSION_HELPER_( SC_VERSION_MAJOR \ + , SC_VERSION_MINOR \ + , SC_VERSION_PATCH ) +#else // pre 1666-2011 +// assume 2.2.0 for now, eventually guess from SYSTEMC_VERSION (date) +# define CCI_SYSTEMC_VERSION_CODE_ \ + CCI_VERSION_HELPER_(2,2,0) + +#endif // CCI_SYSTEMC_VERSION_CODE_ + +// sc_core::sc_get_curr_simcontext()->active_object() +#if CCI_SYSTEMC_VERSION_CODE_ < CCI_VERSION_HELPER_(2,3,1) +namespace sc_core { +inline sc_object* sc_get_curr_simcontext()->active_object() +{ + struct dummy_object : sc_object {} dummy; + return dummy.get_parent_object(); +} +} // namespace sc_core +#endif // sc_core::sc_get_curr_simcontext()->active_object + +#endif // CCI_CORE_SYSTEMC_H_INCLUDED_ diff --git a/third_party/cci-1.0.0/cci_utils/broker.cpp b/third_party/cci-1.0.0/cci_utils/broker.cpp new file mode 100644 index 000000000..71c540a8f --- /dev/null +++ b/third_party/cci-1.0.0/cci_utils/broker.cpp @@ -0,0 +1,162 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + ****************************************************************************/ + +/** + * @author GreenSocs + */ + + +#include "cci_utils/broker.h" + +#include "cci_cfg/cci_param_if.h" +#include "cci_core/cci_name_gen.h" + +namespace cci_utils { + using namespace cci; + + +/* + * private function to determine if we send to the parent broker or not + */ + bool broker::sendToParent(const std::string &parname) const + { + return ((expose.find(parname) != expose.end()) && (!is_global_broker())); + } + +/* + * public interface functions + */ + broker::broker(const std::string& name) + : consuming_broker(name), + m_parent(get_parent_broker()) // local convenience function + { + sc_assert (name.length() > 0 && "Name must not be empty"); + } + + broker::~broker() + { + } + + cci_originator broker::get_value_origin(const std::string &parname) const + { + if (sendToParent(parname)) { + return m_parent.get_value_origin(parname); + } else { + return consuming_broker::get_value_origin(parname); + } + } + + cci_value broker::get_preset_cci_value(const std::string &parname) const + { + if (sendToParent(parname)) { + return m_parent.get_preset_cci_value(parname); + } else { + return consuming_broker::get_preset_cci_value(parname); + } + } + + void broker::lock_preset_value(const std::string &parname) + { + if (sendToParent(parname)) { + return m_parent.lock_preset_value(parname); + } else { + return consuming_broker::lock_preset_value(parname); + } + } + + cci_value broker::get_cci_value(const std::string &parname) const + { + if (sendToParent(parname)) { + return m_parent.get_cci_value(parname); + } else { + return consuming_broker::get_cci_value(parname); + } + } + + void broker::add_param(cci_param_if* par) + { + if (sendToParent(par->name())) { + return m_parent.add_param(par); + } else { + return consuming_broker::add_param(par); + } + } + + void broker::remove_param(cci_param_if* par) { + if (sendToParent(par->name())) { + return m_parent.remove_param(par); + } else { + return consuming_broker::remove_param(par); + } + } + +// Functions below here require an orriginator to be passed to the local +// method variant. + + void broker::set_preset_cci_value( + const std::string &parname, + const cci_value &cci_value, + const cci_originator& originator) + { + if (sendToParent(parname)) { + return m_parent.set_preset_cci_value(parname,cci_value, originator); + } else { + return consuming_broker::set_preset_cci_value(parname,cci_value,originator); + } + } + cci_param_untyped_handle broker::get_param_handle( + const std::string &parname, + const cci_originator& originator) const + { + if (sendToParent(parname)) { + return m_parent.get_param_handle(parname, originator); + } + cci_param_if* orig_param = get_orig_param(parname); + if (orig_param) { + return cci_param_untyped_handle(*orig_param, originator); + } + if (has_parent) { + return m_parent.get_param_handle(parname, originator); + } + return cci_param_untyped_handle(originator); + } + + + std::vector + broker::get_param_handles(const cci_originator& originator) const + { + if (has_parent) { + std::vector p_param_handles=m_parent.get_param_handles(); + std::vector param_handles=consuming_broker::get_param_handles(originator); + // this is likely to be more efficient the other way round, but it keeps + // things consistent and means the local (mre useful) params will be at the + // head of the list. + param_handles.insert(param_handles.end(),p_param_handles.begin(), p_param_handles.end()); + return param_handles; + } else { + return consuming_broker::get_param_handles(originator); + } + } + + bool broker::is_global_broker() const + { + return (!has_parent); + } + +} diff --git a/third_party/cci-1.0.0/cci_utils/broker.h b/third_party/cci-1.0.0/cci_utils/broker.h new file mode 100644 index 000000000..b3d29ce23 --- /dev/null +++ b/third_party/cci-1.0.0/cci_utils/broker.h @@ -0,0 +1,88 @@ +#ifndef CCI_UTILS_BROKER_H_INCLUDED_ +#define CCI_UTILS_BROKER_H_INCLUDED_ + +#include +#include "cci_cfg/cci_broker_manager.h" +#include "cci_utils/consuming_broker.h" + +namespace cci_utils +{ + + /// (Non-private) broker implementation + /** + * + * Global default Broker Implementation + * See cci_broker_if for details of the implemented API. + * + */ + class broker : public consuming_broker + { + public: +// a set of perameters that should be exposed up the broker stack + std::set expose; + + private: + /// for the public broker, this will be useless, but if people re-use this + /// broker, then it will help + bool has_parent; + cci::cci_broker_if &m_parent; + + // convenience function for constructor + cci::cci_broker_if &get_parent_broker() + { + if (sc_core::sc_get_current_object()) { + has_parent=true; + return unwrap_broker(cci::cci_get_broker()); + } else { + // We ARE the global broker + has_parent=false; + return *this; + } + } + + bool sendToParent(const std::string &parname) const; + + public: + + cci::cci_originator get_value_origin( + const std::string &parname) const; + + /// Constructor + broker(const std::string& name); + + /// Destructor + ~broker(); + + /// Return the preset value of a parameter (by name) + cci::cci_value get_preset_cci_value(const std::string &parname) const; + + /// Set the preset value of a parameter (by name, requires originator) + void set_preset_cci_value(const std::string &parname, + const cci::cci_value &cci_value, + const cci::cci_originator& originator); + + /// Lock parameter + void lock_preset_value(const std::string &parname); + + /// Get current cci_value + cci::cci_value get_cci_value(const std::string &parname) const; + + /// return a handle with which to access a parameter + cci::cci_param_untyped_handle get_param_handle(const std::string &parname, + const cci::cci_originator& originator) const; + + /// return a list of all the params that the originator can see from either + /// the private broker, or from up the broker stack. + std::vector get_param_handles(const cci::cci_originator& originator) const; + + void add_param(cci::cci_param_if* par); + + void remove_param(cci::cci_param_if* par); + + bool is_global_broker() const; + + }; + +} +#endif + diff --git a/third_party/cci-1.0.0/cci_utils/consuming_broker.cpp b/third_party/cci-1.0.0/cci_utils/consuming_broker.cpp new file mode 100644 index 000000000..283288e10 --- /dev/null +++ b/third_party/cci-1.0.0/cci_utils/consuming_broker.cpp @@ -0,0 +1,375 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + +****************************************************************************/ + +/** + * @author GreenSocs + */ + +#include "cci_utils/consuming_broker.h" + +#include "cci_cfg/cci_broker_if.h" +#include "cci_cfg/cci_broker_manager.h" +#include "cci_cfg/cci_config_macros.h" +#include "cci_cfg/cci_param_if.h" +#include "cci_cfg/cci_report_handler.h" +#include "cci_core/cci_name_gen.h" + +namespace cci_utils { + using namespace cci; + +// NB this broker must be instanced and registered in the same place +// + consuming_broker::consuming_broker(const std::string& name) + : m_name(cci_gen_unique_name(name.c_str())) + { + sc_assert (name.length() > 0 && "Name must not be empty"); + } + + consuming_broker::~consuming_broker() + { + } + + const char* consuming_broker::name() const + { + return m_name.c_str(); + } + + void consuming_broker::set_preset_cci_value( + const std::string &parname, + const cci_value & value, + const cci_originator& originator) + { + if (locked.find(parname) != locked.end()) { + cci_report_handler::set_param_failed("Setting preset value failed (parameter locked)."); + return; + } + + std::map::const_iterator iter = + m_used_value_registry.find(parname); + if (iter != m_used_value_registry.end() ) { + m_used_value_registry[parname]=value; // kiss a zombee + /* here, one could build a broker that, e.g. allowed writes to a param + during elaboration. We choose not to, the user may reset the value at eoe + if they choose*/ + } else { + m_unused_value_registry[parname] = value; + } + + // Store originator of the preset value. Can't use index operator since + // null construction of an originator is prohibited outside the module hierarchy. + // m_preset_value_originator_map[parname] = originator; + std::map::iterator it; + it = m_preset_value_originator_map.find(parname); + if (it != m_preset_value_originator_map.end()) + it->second = originator; + else + m_preset_value_originator_map.insert( + std::pair(parname, originator)); + } + + std::vector consuming_broker::get_unconsumed_preset_values() const + { + std::vector unconsumed_preset_cci_values; + std::map::const_iterator iter; + std::vector::const_iterator pred; + + for( iter = m_unused_value_registry.begin(); iter != m_unused_value_registry.end(); ++iter ) { + for (pred = m_ignored_unconsumed_predicates.begin(); pred != m_ignored_unconsumed_predicates.end(); ++pred) { + const cci_preset_value_predicate &p=*pred; // get the actual predicate + if (p(std::make_pair(iter->first, iter->second))) { + break; + } + } + if (pred==m_ignored_unconsumed_predicates.end()) { + unconsumed_preset_cci_values.push_back(std::make_pair(iter->first, iter->second)); + } + } + return unconsumed_preset_cci_values; + } + + cci_preset_value_range consuming_broker::get_unconsumed_preset_values( + const cci_preset_value_predicate &pred) const + { + return cci_preset_value_range(pred, get_unconsumed_preset_values()); + } + + void consuming_broker::ignore_unconsumed_preset_values(const cci_preset_value_predicate &pred) + { + m_ignored_unconsumed_predicates.push_back(pred); + } + + cci_originator consuming_broker::get_value_origin(const std::string &parname) const + { + cci_param_if* p = get_orig_param(parname); + if (p) { + return p->get_value_origin(); + } + std::map::const_iterator it; + it = m_preset_value_originator_map.find(parname); + if (it != m_preset_value_originator_map.end()) { + return it->second; + } + // if the param doesn't exist, we should return 'unkown_originator' + return cci_broker_if::unknown_originator(); + } + + cci_originator consuming_broker::get_preset_value_origin(const std::string &parname) const + { + std::map::const_iterator it; + it = m_preset_value_originator_map.find(parname); + if (it != m_preset_value_originator_map.end()) + return it->second; + // if no preset value, return 'unknown originator' + return cci_broker_if::unknown_originator(); + } + + cci_value consuming_broker::get_preset_cci_value(const std::string &parname) const + { + { + std::map::const_iterator iter = + m_used_value_registry.find(parname); + if (iter != m_used_value_registry.end() ) { + return iter->second; + } + } + { + std::map::const_iterator iter = + m_unused_value_registry.find(parname); + if (iter != m_unused_value_registry.end() ) { + return iter->second; + } + } +// If there is nothing in the database, return NULL. + return cci_value(); + } + + void consuming_broker::lock_preset_value(const std::string &parname) + { + // no error is possible. Even if the parameter does not yet exist. + locked.insert(parname); + } + + cci_value consuming_broker::get_cci_value(const std::string &parname, + const cci_originator &originator) const + { + cci_param_if* p = get_orig_param(parname); + if(p) { + return p->get_cci_value(originator); + } else { + std::map::const_iterator iter = + m_unused_value_registry.find(parname); + if (iter != m_unused_value_registry.end() ) { + return iter->second; + } + cci_report_handler::get_param_failed("Unable to find the parameter to get value"); + return cci_value(); + } + } + + cci_param_if* consuming_broker::get_orig_param( + const std::string &parname) const + { + std::map::const_iterator iter = + m_param_registry.find(parname); + if( iter != m_param_registry.end() ) { + cci_param_if* ret = iter->second; + sc_assert(ret != NULL && "This param shall be a cci_param_if!"); + return ret; + } + else return NULL; + } + +/* + * This entire broker can be re-used as a 'greedy' private broker, the broker + * should remain the same, except for when a model asks for a param handle for a + * param that this broker has no knowledge of, at which point it should ask up + * the broker tree. This case is _NOT_ handled below. The intention is that a well + * behaved private broker can then 'wrap' this broker, passing 'public' params up + * the broker tree and bypassing this broker, while this broker will handle all + * 'private' params. To see the mechanism, see the private broker. + */ + + cci_param_untyped_handle consuming_broker::get_param_handle( + const std::string &parname, + const cci_originator& originator) const + { + cci_param_if* orig_param = get_orig_param(parname); + if (orig_param) { + return cci_param_untyped_handle(*orig_param, originator); + } + return cci_param_untyped_handle(originator); + } + + bool consuming_broker::has_preset_value(const std::string &parname) const + { + { + std::map::const_iterator iter = + m_used_value_registry.find(parname); + if (iter != m_used_value_registry.end() ) { + return true; + } + } + { + std::map::const_iterator iter = + m_unused_value_registry.find(parname); + if (iter != m_unused_value_registry.end() ) { + return true; + } + } + return false; + } + + cci_param_create_callback_handle + consuming_broker::register_create_callback( + const cci_param_create_callback &cb, + const cci_originator &orig) { + m_create_callbacks.push_back(create_callback_obj_t(cb, orig)); + return cb; + } + + bool + consuming_broker::unregister_create_callback( + const cci_param_create_callback_handle &cb, + const cci_originator &orig) { + std::vector::iterator it; + for(it=m_create_callbacks.begin() ; it < m_create_callbacks.end(); it++ ) + { + if(it->callback == cb && it->originator == orig) { + m_create_callbacks.erase(it); + return true; + } + } + return false; + } + + cci_param_destroy_callback_handle + consuming_broker::register_destroy_callback( + const cci_param_destroy_callback &cb, + const cci_originator& orig) { + m_destroy_callbacks.push_back(destroy_callback_obj_t(cb, orig)); + return cb; + } + + bool + consuming_broker::unregister_destroy_callback( + const cci_param_destroy_callback_handle &cb, + const cci_originator &orig) { + std::vector::iterator it; + for(it=m_destroy_callbacks.begin() ; it < m_destroy_callbacks.end(); it++ ) + { + if(it->callback == cb && it->originator == orig) { + m_destroy_callbacks.erase(it); + return true; + } + } + return false; + } + + bool consuming_broker::unregister_all_callbacks( + const cci_originator &orig) { + bool result = false; + std::vector::iterator it; + for(it=m_create_callbacks.begin() ; it < m_create_callbacks.end(); it++ ) + { + if(it->originator == orig) { + m_create_callbacks.erase(it); + result = true; + } + } + std::vector::iterator itt; + for (itt = m_destroy_callbacks.begin(); + itt < m_destroy_callbacks.end(); itt++) + { + if(itt->originator == orig) { + m_destroy_callbacks.erase(itt); + result = true; + } + } + return result; + } + + bool consuming_broker::has_callbacks() const { + return (!m_create_callbacks.empty() || + !m_destroy_callbacks.empty()); + } + + void consuming_broker::add_param(cci_param_if* par) { + sc_assert(par != NULL && "Unable to add a NULL parameter"); + const std::string &par_name = par->name(); + bool new_element = m_param_registry.insert( + std::pair(par_name, par)).second; + sc_assert(new_element && "The same parameter had been added twice!!"); + + std::map::iterator iter = + m_unused_value_registry.find(par_name); + if (iter != m_unused_value_registry.end() ) { + m_used_value_registry.insert(std::make_pair(iter->first, iter->second)); + m_unused_value_registry.erase(iter); + } + // Create callbacks + for (unsigned i = 0; i < m_create_callbacks.size(); ++i) { + m_create_callbacks[i].callback.invoke( + par->create_param_handle(par->get_originator())); + } + } + + void consuming_broker::remove_param(cci_param_if* par) { + sc_assert(par != NULL && "Unable to remove a NULL parameter"); + m_param_registry.erase(par->name()); + + // Destroy callbacks + for (unsigned i = 0; i < m_destroy_callbacks.size(); ++i) { + m_destroy_callbacks[i].callback.invoke( + par->create_param_handle(par->get_originator())); + } + + std::map::iterator iter = + m_used_value_registry.find(par->name()); + if (iter != m_used_value_registry.end() ) { + m_unused_value_registry.insert(std::make_pair(iter->first, iter->second)); + m_used_value_registry.erase(iter); + } + } + + std::vector + consuming_broker::get_param_handles(const cci_originator& originator) const + { + std::vector param_handles; + std::map::const_iterator it; + for (it=m_param_registry.begin(); it != m_param_registry.end(); ++it) { + cci_param_if* p = it->second; + param_handles.push_back(cci_param_untyped_handle(*p, originator)); + } + return param_handles; + } + + cci_param_range consuming_broker::get_param_handles( + cci_param_predicate& pred, + const cci_originator& originator) const + { + return cci_param_range(pred, + get_param_handles(originator)); + } + + bool consuming_broker::is_global_broker() const + { + return false; + } + +} diff --git a/third_party/cci-1.0.0/cci_utils/consuming_broker.h b/third_party/cci-1.0.0/cci_utils/consuming_broker.h new file mode 100644 index 000000000..be4d7c478 --- /dev/null +++ b/third_party/cci-1.0.0/cci_utils/consuming_broker.h @@ -0,0 +1,154 @@ +#ifndef CCI_UTILS_CONSUMING_BROKER_H_INCLUDED_ +#define CCI_UTILS_CONSUMING_BROKER_H_INCLUDED_ + +#include +#include + +#include "cci_configuration" + + +namespace cci_utils { + + /// (Non-private) consuming_broker implementation + /** + * + * Default Consuming_broker declaration + * See cci_broker_if for details of the implemented API. + * + * This broker consumes all parameters, and does not have any mechanism to + * pass parameters to a 'global' broker. It is therefore a good candidate for + * the global broker. + * + */ + class consuming_broker: public cci::cci_broker_if + { +protected: + // This consuming_broker is specialized as the normal 'broker' + // but can be used as a global broker if desired. + +public: + cci::cci_originator get_value_origin( + const std::string &parname) const; + + cci::cci_originator get_preset_value_origin( + const std::string &parname) const; + + /// Constructor + explicit consuming_broker(const std::string& name); + + /// Destructor + ~consuming_broker(); + + /// Return the name of the broker + const char* name() const; + + /// Return the preset value of a parameter (by name) + cci::cci_value get_preset_cci_value(const std::string &parname) const; + + /// Set the preset value of a parameter (by name, requires originator) + void set_preset_cci_value( + const std::string &parname, + const cci::cci_value &cci_value, + const cci::cci_originator& originator); + + /// Lock parameter + void lock_preset_value(const std::string &parname); + + /// Get a full list of unconsumed preset values. + std::vector get_unconsumed_preset_values() const; + + /// get vector of unconsumed preset values + cci::cci_preset_value_range get_unconsumed_preset_values( + const cci::cci_preset_value_predicate &pred) const; + + void ignore_unconsumed_preset_values( + const cci::cci_preset_value_predicate &pred); + + /// Get current cci_value + cci::cci_value get_cci_value(const std::string &parname, + const cci::cci_originator& originator = cci::cci_originator()) const; + + /// return a handle with which to access a parameter + cci::cci_param_untyped_handle get_param_handle( + const std::string &parname, + const cci::cci_originator& originator) const; + + std::vector get_param_handles( + const cci::cci_originator& originator) const; + + cci::cci_param_range get_param_handles(cci::cci_param_predicate& pred, + const cci::cci_originator& originator) const; + + bool has_preset_value(const std::string &parname) const; + + void add_param(cci::cci_param_if* par); + + void remove_param(cci::cci_param_if* par); + + virtual bool is_global_broker() const; + + cci::cci_param_create_callback_handle + register_create_callback(const cci::cci_param_create_callback& cb, + const cci::cci_originator& orig); + + bool + unregister_create_callback(const cci::cci_param_create_callback_handle& cb, + const cci::cci_originator& orig); + + cci::cci_param_destroy_callback_handle + register_destroy_callback(const cci::cci_param_destroy_callback& cb, + const cci::cci_originator& orig); + + bool + unregister_destroy_callback(const cci::cci_param_destroy_callback_handle& cb, + const cci::cci_originator& orig); + + bool unregister_all_callbacks(const cci::cci_originator& orig); + + bool has_callbacks() const; + + protected: + /// Get original parameter (internal method) + cci::cci_param_if* get_orig_param(const std::string &parname) const; + + std::string m_name; + + // These are used as a database of _preset_ values. + std::map m_param_registry; + std::map m_unused_value_registry; + std::map m_used_value_registry; + + // store the list of locked param's (guessing there are many fewer of these + // than actual params, so hopefully this is more efficient than adding a + // boolean above) + std::set locked; + + /// Map to save the latest write originator when preset values are set + std::map m_preset_value_originator_map; + + template + struct callback_obj { + callback_obj(T cb, const cci::cci_originator& orig): + callback(cb), originator(orig) {} + T callback; + cci::cci_originator originator; + }; + + typedef callback_obj + create_callback_obj_t; + + /// Create callbacks + std::vector m_create_callbacks; + + typedef callback_obj + destroy_callback_obj_t; + + /// Destroy callbacks + std::vector m_destroy_callbacks; + + /// Ignored unconsumed preset cci values + std::vector m_ignored_unconsumed_predicates; + }; + +} +#endif diff --git a/third_party/cci-1.0.0/cciapi-config.cmake.in b/third_party/cci-1.0.0/cciapi-config.cmake.in new file mode 100644 index 000000000..c6cd6a752 --- /dev/null +++ b/third_party/cci-1.0.0/cciapi-config.cmake.in @@ -0,0 +1,10 @@ +@PACKAGE_INIT@ +include(CMakeFindDependencyMacro) + +find_dependency(RapidJSON) +if(NOT TARGET cciapi::cciapi) + include("${CMAKE_CURRENT_LIST_DIR}/cciapi-targets.cmake") +endif() + +set(cciapi_INCLUDE_DIRS "${PACKAGE_PREFIX_DIR}/include") +set(cciapi_lIBRARIES cciapi::cciapi) From f991ec5200ae1cc7b5a23d09fa9316a08aa9f13f Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Wed, 4 Mar 2026 03:09:35 -0800 Subject: [PATCH 2/5] adds proper version setting for shared libraries --- src/common/CMakeLists.txt | 2 +- src/components/CMakeLists.txt | 2 +- src/interfaces/CMakeLists.txt | 2 +- src/sysc/CMakeLists.txt | 2 +- third_party/cci-1.0.0/CMakeLists.txt | 4 +++- third_party/cci-1.0.1/CMakeLists.txt | 3 +++ third_party/scv-tr/src/CMakeLists.txt | 2 +- 7 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index f14c5f06f..33981b5dd 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -1,4 +1,4 @@ -project(scc-util VERSION 0.0.1 LANGUAGES CXX) +project(scc-util VERSION ${scc_VERSION} LANGUAGES CXX) set(SRC util/io-redirector.cpp util/watchdog.cpp util/ihex.cpp) if(TARGET lz4::lz4) diff --git a/src/components/CMakeLists.txt b/src/components/CMakeLists.txt index 71880d469..964ef6ca0 100644 --- a/src/components/CMakeLists.txt +++ b/src/components/CMakeLists.txt @@ -1,4 +1,4 @@ -project(components VERSION 0.0.1 LANGUAGES CXX) +project(components VERSION ${scc_VERSION} LANGUAGES CXX) add_library(${PROJECT_NAME} INTERFACE) add_library(scc::${PROJECT_NAME} ALIAS ${PROJECT_NAME}) diff --git a/src/interfaces/CMakeLists.txt b/src/interfaces/CMakeLists.txt index ab2878a3e..d87e8f5f6 100644 --- a/src/interfaces/CMakeLists.txt +++ b/src/interfaces/CMakeLists.txt @@ -1,4 +1,4 @@ -project(interfaces VERSION 0.0.1 LANGUAGES CXX) +project(interfaces VERSION ${scc_VERSION} LANGUAGES CXX) set(LIB_SOURCES apb/apb_tlm.cpp diff --git a/src/sysc/CMakeLists.txt b/src/sysc/CMakeLists.txt index ed2fb3e72..5f65c1565 100644 --- a/src/sysc/CMakeLists.txt +++ b/src/sysc/CMakeLists.txt @@ -1,4 +1,4 @@ -project(scc-sysc VERSION 0.0.1 LANGUAGES CXX) +project(scc-sysc VERSION ${scc_VERSION} LANGUAGES CXX) find_package(Threads REQUIRED) find_package(Boost REQUIRED QUIET COMPONENTS date_time filesystem) diff --git a/third_party/cci-1.0.0/CMakeLists.txt b/third_party/cci-1.0.0/CMakeLists.txt index c4f2e2654..93bbb4b90 100644 --- a/third_party/cci-1.0.0/CMakeLists.txt +++ b/third_party/cci-1.0.0/CMakeLists.txt @@ -1,4 +1,4 @@ -project(SystemC-CCI VERSION "1.1.0" LANGUAGES CXX) +project(SystemC-CCI VERSION "1.0.0" LANGUAGES CXX) add_library(cciapi ${CMAKE_CURRENT_SOURCE_DIR}/cci_cfg/cci_broker_handle.cpp @@ -13,6 +13,8 @@ ${CMAKE_CURRENT_SOURCE_DIR}/cci_core/cci_value.cpp ${CMAKE_CURRENT_SOURCE_DIR}/cci_core/cci_value_converter.cpp ${CMAKE_CURRENT_SOURCE_DIR}/cci_utils/broker.cpp ${CMAKE_CURRENT_SOURCE_DIR}/cci_utils/consuming_broker.cpp) +#set_target_properties(cciapi PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION 1) + if(USE_NCSC_SYSTEMC OR USE_CWR_SYSTEMC) target_compile_definitions(cciapi PUBLIC SC_VERSION_CODE=200301) endif() diff --git a/third_party/cci-1.0.1/CMakeLists.txt b/third_party/cci-1.0.1/CMakeLists.txt index 16448a58e..ef943f268 100644 --- a/third_party/cci-1.0.1/CMakeLists.txt +++ b/third_party/cci-1.0.1/CMakeLists.txt @@ -41,9 +41,12 @@ target_link_libraries(cciapi PUBLIC RapidJSON) if(NOT TARGET systemc-cci::systemc-cci) add_library(systemc-cci::systemc-cci ALIAS cciapi) endif() +add_library (cci ALIAS cciapi) +add_library (SystemC::cci ALIAS cciapi) set_target_properties(cciapi PROPERTIES VERSION ${PROJECT_VERSION} + # SOVERSION 2 FRAMEWORK FALSE PUBLIC_HEADER ${CMAKE_CURRENT_SOURCE_DIR}/cci_configuration CXX_CLANG_TIDY "" diff --git a/third_party/scv-tr/src/CMakeLists.txt b/third_party/scv-tr/src/CMakeLists.txt index f18b5f209..608bd09c9 100644 --- a/third_party/scv-tr/src/CMakeLists.txt +++ b/third_party/scv-tr/src/CMakeLists.txt @@ -1,4 +1,4 @@ -project(scv-tr VERSION 0.0.1 LANGUAGES CXX) +project(scv-tr VERSION 1.0.0 LANGUAGES CXX) include(GNUInstallDirs) From 09a812ea1b7a14117371a5509aa712890edcaf33 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Fri, 13 Mar 2026 13:18:24 -0700 Subject: [PATCH 3/5] updates string_view implementation --- src/common/nonstd/string_view.hpp | 1954 ++++++++++++++++------------- 1 file changed, 1061 insertions(+), 893 deletions(-) diff --git a/src/common/nonstd/string_view.hpp b/src/common/nonstd/string_view.hpp index 807943be2..b5ccb6a2a 100644 --- a/src/common/nonstd/string_view.hpp +++ b/src/common/nonstd/string_view.hpp @@ -11,115 +11,116 @@ #ifndef NONSTD_SV_LITE_H_INCLUDED #define NONSTD_SV_LITE_H_INCLUDED -#define string_view_lite_MAJOR 1 -#define string_view_lite_MINOR 7 -#define string_view_lite_PATCH 0 +#define string_view_lite_MAJOR 1 +#define string_view_lite_MINOR 8 +#define string_view_lite_PATCH 0 -#define string_view_lite_VERSION \ - nssv_STRINGIFY(string_view_lite_MAJOR) "." nssv_STRINGIFY(string_view_lite_MINOR) "." nssv_STRINGIFY(string_view_lite_PATCH) +#define string_view_lite_VERSION nssv_STRINGIFY(string_view_lite_MAJOR) "." nssv_STRINGIFY(string_view_lite_MINOR) "." nssv_STRINGIFY(string_view_lite_PATCH) -#define nssv_STRINGIFY(x) nssv_STRINGIFY_(x) -#define nssv_STRINGIFY_(x) #x +#define nssv_STRINGIFY( x ) nssv_STRINGIFY_( x ) +#define nssv_STRINGIFY_( x ) #x // string-view lite configuration: -#define nssv_STRING_VIEW_DEFAULT 0 -#define nssv_STRING_VIEW_NONSTD 1 -#define nssv_STRING_VIEW_STD 2 +#define nssv_STRING_VIEW_DEFAULT 0 +#define nssv_STRING_VIEW_NONSTD 1 +#define nssv_STRING_VIEW_STD 2 // tweak header support: #ifdef __has_include -#if __has_include() -#include -#endif -#define nssv_HAVE_TWEAK_HEADER 1 +# if __has_include() +# include +# endif +#define nssv_HAVE_TWEAK_HEADER 1 #else -#define nssv_HAVE_TWEAK_HEADER 0 -// # pragma message("string_view.hpp: Note: Tweak header not supported.") +#define nssv_HAVE_TWEAK_HEADER 0 +//# pragma message("string_view.hpp: Note: Tweak header not supported.") #endif // string_view selection and configuration: -#if !defined(nssv_CONFIG_SELECT_STRING_VIEW) -#define nssv_CONFIG_SELECT_STRING_VIEW (nssv_HAVE_STD_STRING_VIEW ? nssv_STRING_VIEW_STD : nssv_STRING_VIEW_NONSTD) +#if !defined( nssv_CONFIG_SELECT_STRING_VIEW ) +# define nssv_CONFIG_SELECT_STRING_VIEW ( nssv_HAVE_STD_STRING_VIEW ? nssv_STRING_VIEW_STD : nssv_STRING_VIEW_NONSTD ) +#endif + +#ifndef nssv_CONFIG_STD_SV_OPERATOR +# define nssv_CONFIG_STD_SV_OPERATOR 0 #endif -#ifndef nssv_CONFIG_STD_SV_OPERATOR -#define nssv_CONFIG_STD_SV_OPERATOR 0 +#ifndef nssv_CONFIG_USR_SV_OPERATOR +# define nssv_CONFIG_USR_SV_OPERATOR 1 #endif -#ifndef nssv_CONFIG_USR_SV_OPERATOR -#define nssv_CONFIG_USR_SV_OPERATOR 1 +#ifdef nssv_CONFIG_CONVERSION_STD_STRING +# define nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS nssv_CONFIG_CONVERSION_STD_STRING +# define nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS nssv_CONFIG_CONVERSION_STD_STRING #endif -#ifdef nssv_CONFIG_CONVERSION_STD_STRING -#define nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS nssv_CONFIG_CONVERSION_STD_STRING -#define nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS nssv_CONFIG_CONVERSION_STD_STRING +#ifndef nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS +# define nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS 1 #endif -#ifndef nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS -#define nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS 1 +#ifndef nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS +# define nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS 1 #endif -#ifndef nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS -#define nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS 1 +#ifndef nssv_CONFIG_NO_STREAM_INSERTION +# define nssv_CONFIG_NO_STREAM_INSERTION 0 #endif -#ifndef nssv_CONFIG_NO_STREAM_INSERTION -#define nssv_CONFIG_NO_STREAM_INSERTION 0 +#ifndef nssv_CONFIG_CONSTEXPR11_STD_SEARCH +# define nssv_CONFIG_CONSTEXPR11_STD_SEARCH 1 #endif // Control presence of exception handling (try and auto discover): #ifndef nssv_CONFIG_NO_EXCEPTIONS -#if defined(_MSC_VER) -#include // for _HAS_EXCEPTIONS -#endif -#if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || (_HAS_EXCEPTIONS) -#define nssv_CONFIG_NO_EXCEPTIONS 0 -#else -#define nssv_CONFIG_NO_EXCEPTIONS 1 -#endif +# if defined(_MSC_VER) +# include // for _HAS_EXCEPTIONS +# endif +# if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || (_HAS_EXCEPTIONS) +# define nssv_CONFIG_NO_EXCEPTIONS 0 +# else +# define nssv_CONFIG_NO_EXCEPTIONS 1 +# endif #endif // C++ language version detection (C++23 is speculative): // Note: VC14.0/1900 (VS2015) lacks too much from C++14. -#ifndef nssv_CPLUSPLUS -#if defined(_MSVC_LANG) && !defined(__clang__) -#define nssv_CPLUSPLUS (_MSC_VER == 1900 ? 201103L : _MSVC_LANG) -#else -#define nssv_CPLUSPLUS __cplusplus -#endif +#ifndef nssv_CPLUSPLUS +# if defined(_MSVC_LANG ) && !defined(__clang__) +# define nssv_CPLUSPLUS (_MSC_VER == 1900 ? 201103L : _MSVC_LANG ) +# else +# define nssv_CPLUSPLUS __cplusplus +# endif #endif -#define nssv_CPP98_OR_GREATER (nssv_CPLUSPLUS >= 199711L) -#define nssv_CPP11_OR_GREATER (nssv_CPLUSPLUS >= 201103L) -#define nssv_CPP11_OR_GREATER_ (nssv_CPLUSPLUS >= 201103L) -#define nssv_CPP14_OR_GREATER (nssv_CPLUSPLUS >= 201402L) -#define nssv_CPP17_OR_GREATER (nssv_CPLUSPLUS >= 201703L) -#define nssv_CPP20_OR_GREATER (nssv_CPLUSPLUS >= 202002L) -#define nssv_CPP23_OR_GREATER (nssv_CPLUSPLUS >= 202300L) +#define nssv_CPP98_OR_GREATER ( nssv_CPLUSPLUS >= 199711L ) +#define nssv_CPP11_OR_GREATER ( nssv_CPLUSPLUS >= 201103L ) +#define nssv_CPP11_OR_GREATER_ ( nssv_CPLUSPLUS >= 201103L ) +#define nssv_CPP14_OR_GREATER ( nssv_CPLUSPLUS >= 201402L ) +#define nssv_CPP17_OR_GREATER ( nssv_CPLUSPLUS >= 201703L ) +#define nssv_CPP20_OR_GREATER ( nssv_CPLUSPLUS >= 202002L ) +#define nssv_CPP23_OR_GREATER ( nssv_CPLUSPLUS >= 202300L ) // use C++17 std::string_view if available and requested: -#if nssv_CPP17_OR_GREATER && defined(__has_include) -#if __has_include( ) -#define nssv_HAVE_STD_STRING_VIEW 1 +#if nssv_CPP17_OR_GREATER && defined(__has_include ) +# if __has_include( ) +# define nssv_HAVE_STD_STRING_VIEW 1 +# else +# define nssv_HAVE_STD_STRING_VIEW 0 +# endif #else -#define nssv_HAVE_STD_STRING_VIEW 0 -#endif -#else -#define nssv_HAVE_STD_STRING_VIEW 0 +# define nssv_HAVE_STD_STRING_VIEW 0 #endif -#define nssv_USES_STD_STRING_VIEW \ - ((nssv_CONFIG_SELECT_STRING_VIEW == nssv_STRING_VIEW_STD) || \ - ((nssv_CONFIG_SELECT_STRING_VIEW == nssv_STRING_VIEW_DEFAULT) && nssv_HAVE_STD_STRING_VIEW)) +#define nssv_USES_STD_STRING_VIEW ( (nssv_CONFIG_SELECT_STRING_VIEW == nssv_STRING_VIEW_STD) || ((nssv_CONFIG_SELECT_STRING_VIEW == nssv_STRING_VIEW_DEFAULT) && nssv_HAVE_STD_STRING_VIEW) ) -#define nssv_HAVE_STARTS_WITH (nssv_CPP20_OR_GREATER || !nssv_USES_STD_STRING_VIEW) -#define nssv_HAVE_ENDS_WITH nssv_HAVE_STARTS_WITH +#define nssv_HAVE_STARTS_WITH ( nssv_CPP20_OR_GREATER || !nssv_USES_STD_STRING_VIEW ) +#define nssv_HAVE_ENDS_WITH nssv_HAVE_STARTS_WITH // // Use C++17 std::string_view: @@ -133,16 +134,22 @@ #if nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS +#include + namespace nonstd { -template > -std::basic_string to_string(std::basic_string_view v, Allocator const& a = Allocator()) { - return std::basic_string(v.begin(), v.end(), a); +template< class CharT, class Traits, class Allocator = std::allocator > +std::basic_string +to_string( std::basic_string_view v, Allocator const & a = Allocator() ) +{ + return std::basic_string( v.begin(), v.end(), a ); } -template -std::basic_string_view to_string_view(std::basic_string const& s) { - return std::basic_string_view(s.data(), s.size()); +template< class CharT, class Traits, class Allocator > +std::basic_string_view +to_string_view( std::basic_string const & s ) +{ + return std::basic_string_view( s.data(), s.size() ); } // Literal operators sv and _sv: @@ -158,28 +165,28 @@ using namespace std::literals::string_view_literals; inline namespace literals { inline namespace string_view_literals { -constexpr std::string_view operator"" _sv(const char* str, size_t len) noexcept // (1) + +constexpr std::string_view operator""_sv( const char* str, size_t len ) noexcept // (1) { - return std::string_view{str, len}; + return std::string_view{ str, len }; } -constexpr std::u16string_view operator"" _sv(const char16_t* str, size_t len) noexcept // (2) +constexpr std::u16string_view operator""_sv( const char16_t* str, size_t len ) noexcept // (2) { - return std::u16string_view{str, len}; + return std::u16string_view{ str, len }; } -constexpr std::u32string_view operator"" _sv(const char32_t* str, size_t len) noexcept // (3) +constexpr std::u32string_view operator""_sv( const char32_t* str, size_t len ) noexcept // (3) { - return std::u32string_view{str, len}; + return std::u32string_view{ str, len }; } -constexpr std::wstring_view operator"" _sv(const wchar_t* str, size_t len) noexcept // (4) +constexpr std::wstring_view operator""_sv( const wchar_t* str, size_t len ) noexcept // (4) { - return std::wstring_view{str, len}; + return std::wstring_view{ str, len }; } -} // namespace string_view_literals -} // namespace literals +}} // namespace literals::string_view_literals #endif // nssv_CONFIG_USR_SV_OPERATOR @@ -189,11 +196,11 @@ constexpr std::wstring_view operator"" _sv(const wchar_t* str, size_t len) noexc namespace nonstd { -using std::basic_string_view; using std::string_view; +using std::wstring_view; using std::u16string_view; using std::u32string_view; -using std::wstring_view; +using std::basic_string_view; // literal "sv" and "_sv", see above @@ -228,93 +235,93 @@ using std::operator<<; // MSVC++ 14.1 _MSC_VER >= 1910 nssv_COMPILER_MSVC_VERSION == 141 (Visual Studio 2017) // MSVC++ 14.2 _MSC_VER >= 1920 nssv_COMPILER_MSVC_VERSION == 142 (Visual Studio 2019) -#if defined(_MSC_VER) && !defined(__clang__) -#define nssv_COMPILER_MSVC_VER (_MSC_VER) -#define nssv_COMPILER_MSVC_VERSION (_MSC_VER / 10 - 10 * (5 + (_MSC_VER < 1900))) +#if defined(_MSC_VER ) && !defined(__clang__) +# define nssv_COMPILER_MSVC_VER (_MSC_VER ) +# define nssv_COMPILER_MSVC_VERSION (_MSC_VER / 10 - 10 * ( 5 + (_MSC_VER < 1900 ) ) ) #else -#define nssv_COMPILER_MSVC_VER 0 -#define nssv_COMPILER_MSVC_VERSION 0 +# define nssv_COMPILER_MSVC_VER 0 +# define nssv_COMPILER_MSVC_VERSION 0 #endif -#define nssv_COMPILER_VERSION(major, minor, patch) (10 * (10 * (major) + (minor)) + (patch)) +#define nssv_COMPILER_VERSION( major, minor, patch ) ( 10 * ( 10 * (major) + (minor) ) + (patch) ) -#if defined(__apple_build_version__) -#define nssv_COMPILER_APPLECLANG_VERSION nssv_COMPILER_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__) -#define nssv_COMPILER_CLANG_VERSION 0 -#elif defined(__clang__) -#define nssv_COMPILER_APPLECLANG_VERSION 0 -#define nssv_COMPILER_CLANG_VERSION nssv_COMPILER_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__) +#if defined( __apple_build_version__ ) +# define nssv_COMPILER_APPLECLANG_VERSION nssv_COMPILER_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__) +# define nssv_COMPILER_CLANG_VERSION 0 +#elif defined( __clang__ ) +# define nssv_COMPILER_APPLECLANG_VERSION 0 +# define nssv_COMPILER_CLANG_VERSION nssv_COMPILER_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__) #else -#define nssv_COMPILER_APPLECLANG_VERSION 0 -#define nssv_COMPILER_CLANG_VERSION 0 +# define nssv_COMPILER_APPLECLANG_VERSION 0 +# define nssv_COMPILER_CLANG_VERSION 0 #endif #if defined(__GNUC__) && !defined(__clang__) -#define nssv_COMPILER_GNUC_VERSION nssv_COMPILER_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) +# define nssv_COMPILER_GNUC_VERSION nssv_COMPILER_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) #else -#define nssv_COMPILER_GNUC_VERSION 0 +# define nssv_COMPILER_GNUC_VERSION 0 #endif // half-open range [lo..hi): -#define nssv_BETWEEN(v, lo, hi) ((lo) <= (v) && (v) < (hi)) +#define nssv_BETWEEN( v, lo, hi ) ( (lo) <= (v) && (v) < (hi) ) // Presence of language and library features: #ifdef _HAS_CPP0X -#define nssv_HAS_CPP0X _HAS_CPP0X +# define nssv_HAS_CPP0X _HAS_CPP0X #else -#define nssv_HAS_CPP0X 0 +# define nssv_HAS_CPP0X 0 #endif -// Unless defined otherwise below, consider VC14 as C++11 for variant-lite: +// Unless defined otherwise below, consider VC14 as C++11 for string-view-lite: #if nssv_COMPILER_MSVC_VER >= 1900 -#undef nssv_CPP11_OR_GREATER -#define nssv_CPP11_OR_GREATER 1 +# undef nssv_CPP11_OR_GREATER +# define nssv_CPP11_OR_GREATER 1 #endif -#define nssv_CPP11_90 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1500) -#define nssv_CPP11_100 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1600) -#define nssv_CPP11_110 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1700) -#define nssv_CPP11_120 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1800) -#define nssv_CPP11_140 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1900) -#define nssv_CPP11_141 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1910) +#define nssv_CPP11_90 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1500) +#define nssv_CPP11_100 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1600) +#define nssv_CPP11_110 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1700) +#define nssv_CPP11_120 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1800) +#define nssv_CPP11_140 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1900) +#define nssv_CPP11_141 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1910) -#define nssv_CPP14_000 (nssv_CPP14_OR_GREATER) -#define nssv_CPP17_000 (nssv_CPP17_OR_GREATER) +#define nssv_CPP14_000 (nssv_CPP14_OR_GREATER) +#define nssv_CPP17_000 (nssv_CPP17_OR_GREATER) // Presence of C++11 language features: -#define nssv_HAVE_CONSTEXPR_11 nssv_CPP11_140 -#define nssv_HAVE_EXPLICIT_CONVERSION nssv_CPP11_140 -#define nssv_HAVE_INLINE_NAMESPACE nssv_CPP11_140 -#define nssv_HAVE_IS_DEFAULT nssv_CPP11_140 -#define nssv_HAVE_IS_DELETE nssv_CPP11_140 -#define nssv_HAVE_NOEXCEPT nssv_CPP11_140 -#define nssv_HAVE_NULLPTR nssv_CPP11_100 -#define nssv_HAVE_REF_QUALIFIER nssv_CPP11_140 -#define nssv_HAVE_UNICODE_LITERALS nssv_CPP11_140 +#define nssv_HAVE_CONSTEXPR_11 nssv_CPP11_140 +#define nssv_HAVE_EXPLICIT_CONVERSION nssv_CPP11_140 +#define nssv_HAVE_INLINE_NAMESPACE nssv_CPP11_140 +#define nssv_HAVE_IS_DEFAULT nssv_CPP11_140 +#define nssv_HAVE_IS_DELETE nssv_CPP11_140 +#define nssv_HAVE_NOEXCEPT nssv_CPP11_140 +#define nssv_HAVE_NULLPTR nssv_CPP11_100 +#define nssv_HAVE_REF_QUALIFIER nssv_CPP11_140 +#define nssv_HAVE_UNICODE_LITERALS nssv_CPP11_140 #define nssv_HAVE_USER_DEFINED_LITERALS nssv_CPP11_140 -#define nssv_HAVE_WCHAR16_T nssv_CPP11_100 -#define nssv_HAVE_WCHAR32_T nssv_CPP11_100 +#define nssv_HAVE_WCHAR16_T nssv_CPP11_100 +#define nssv_HAVE_WCHAR32_T nssv_CPP11_100 -#if !((nssv_CPP11_OR_GREATER && nssv_COMPILER_CLANG_VERSION) || nssv_BETWEEN(nssv_COMPILER_CLANG_VERSION, 300, 400)) -#define nssv_HAVE_STD_DEFINED_LITERALS nssv_CPP11_140 +#if ! ( ( nssv_CPP11_OR_GREATER && nssv_COMPILER_CLANG_VERSION ) || nssv_BETWEEN( nssv_COMPILER_CLANG_VERSION, 300, 400 ) ) +# define nssv_HAVE_STD_DEFINED_LITERALS nssv_CPP11_140 #else -#define nssv_HAVE_STD_DEFINED_LITERALS 0 +# define nssv_HAVE_STD_DEFINED_LITERALS 0 #endif // Presence of C++14 language features: -#define nssv_HAVE_CONSTEXPR_14 nssv_CPP14_000 +#define nssv_HAVE_CONSTEXPR_14 nssv_CPP14_000 // Presence of C++17 language features: -#define nssv_HAVE_NODISCARD nssv_CPP17_000 +#define nssv_HAVE_NODISCARD nssv_CPP17_000 // Presence of C++ library features: -#define nssv_HAVE_STD_HASH nssv_CPP11_120 +#define nssv_HAVE_STD_HASH nssv_CPP11_120 // Presence of compiler intrinsics: @@ -331,82 +338,80 @@ using std::operator<<; // | gcc | any (constexpr) | any (? ) | // | msvc | >= 14.2 C++17 (>= 14.2 ) | any (? ) | -#define nssv_HAVE_BUILTIN_VER \ - ((nssv_CPP17_000 && nssv_COMPILER_MSVC_VERSION >= 142) || nssv_COMPILER_GNUC_VERSION > 0 || nssv_COMPILER_CLANG_VERSION >= 400 || \ - nssv_COMPILER_APPLECLANG_VERSION >= 900) -#define nssv_HAVE_BUILTIN_CE (nssv_HAVE_BUILTIN_VER) +#define nssv_HAVE_BUILTIN_VER ( (nssv_CPP17_000 && nssv_COMPILER_MSVC_VERSION >= 142) || nssv_COMPILER_GNUC_VERSION > 0 || nssv_COMPILER_CLANG_VERSION >= 400 || nssv_COMPILER_APPLECLANG_VERSION >= 900 ) +#define nssv_HAVE_BUILTIN_CE ( nssv_HAVE_BUILTIN_VER ) -#define nssv_HAVE_BUILTIN_MEMCMP ((nssv_HAVE_CONSTEXPR_14 && nssv_HAVE_BUILTIN_CE) || !nssv_HAVE_CONSTEXPR_14) -#define nssv_HAVE_BUILTIN_STRLEN ((nssv_HAVE_CONSTEXPR_11 && nssv_HAVE_BUILTIN_CE) || !nssv_HAVE_CONSTEXPR_11) +#define nssv_HAVE_BUILTIN_MEMCMP ( (nssv_HAVE_CONSTEXPR_14 && nssv_HAVE_BUILTIN_CE) || !nssv_HAVE_CONSTEXPR_14 ) +#define nssv_HAVE_BUILTIN_STRLEN ( (nssv_HAVE_CONSTEXPR_11 && nssv_HAVE_BUILTIN_CE) || !nssv_HAVE_CONSTEXPR_11 ) #ifdef __has_builtin -#define nssv_HAVE_BUILTIN(x) __has_builtin(x) +# define nssv_HAVE_BUILTIN( x ) __has_builtin( x ) #else -#define nssv_HAVE_BUILTIN(x) 0 +# define nssv_HAVE_BUILTIN( x ) 0 #endif #if nssv_HAVE_BUILTIN(__builtin_memcmp) || nssv_HAVE_BUILTIN_VER -#define nssv_BUILTIN_MEMCMP __builtin_memcmp +# define nssv_BUILTIN_MEMCMP __builtin_memcmp #else -#define nssv_BUILTIN_MEMCMP memcmp +# define nssv_BUILTIN_MEMCMP memcmp #endif #if nssv_HAVE_BUILTIN(__builtin_strlen) || nssv_HAVE_BUILTIN_VER -#define nssv_BUILTIN_STRLEN __builtin_strlen +# define nssv_BUILTIN_STRLEN __builtin_strlen #else -#define nssv_BUILTIN_STRLEN strlen +# define nssv_BUILTIN_STRLEN strlen #endif // C++ feature usage: #if nssv_HAVE_CONSTEXPR_11 -#define nssv_constexpr constexpr +# define nssv_constexpr constexpr #else -#define nssv_constexpr /*constexpr*/ +# define nssv_constexpr /*constexpr*/ #endif -#if nssv_HAVE_CONSTEXPR_14 -#define nssv_constexpr14 constexpr +#if nssv_HAVE_CONSTEXPR_14 +# define nssv_constexpr14 constexpr #else -#define nssv_constexpr14 /*constexpr*/ +# define nssv_constexpr14 /*constexpr*/ #endif #if nssv_HAVE_EXPLICIT_CONVERSION -#define nssv_explicit explicit +# define nssv_explicit explicit #else -#define nssv_explicit /*explicit*/ +# define nssv_explicit /*explicit*/ #endif #if nssv_HAVE_INLINE_NAMESPACE -#define nssv_inline_ns inline +# define nssv_inline_ns inline #else -#define nssv_inline_ns /*inline*/ +# define nssv_inline_ns /*inline*/ #endif #if nssv_HAVE_NOEXCEPT -#define nssv_noexcept noexcept +# define nssv_noexcept noexcept #else -#define nssv_noexcept /*noexcept*/ +# define nssv_noexcept /*noexcept*/ #endif -// #if nssv_HAVE_REF_QUALIFIER -// # define nssv_ref_qual & -// # define nssv_refref_qual && -// #else -// # define nssv_ref_qual /*&*/ -// # define nssv_refref_qual /*&&*/ -// #endif +//#if nssv_HAVE_REF_QUALIFIER +//# define nssv_ref_qual & +//# define nssv_refref_qual && +//#else +//# define nssv_ref_qual /*&*/ +//# define nssv_refref_qual /*&&*/ +//#endif #if nssv_HAVE_NULLPTR -#define nssv_nullptr nullptr +# define nssv_nullptr nullptr #else -#define nssv_nullptr NULL +# define nssv_nullptr NULL #endif #if nssv_HAVE_NODISCARD -#define nssv_nodiscard [[nodiscard]] +# define nssv_nodiscard [[nodiscard]] #else -#define nssv_nodiscard /*[[nodiscard]]*/ +# define nssv_nodiscard /*[[nodiscard]]*/ #endif // Additional includes: @@ -415,49 +420,49 @@ using std::operator<<; #include #include #include -#include // std::char_traits<> +#include // std::char_traits<> -#if !nssv_CONFIG_NO_STREAM_INSERTION -#include +#if ! nssv_CONFIG_NO_STREAM_INSERTION +# include #endif -#if !nssv_CONFIG_NO_EXCEPTIONS -#include +#if ! nssv_CONFIG_NO_EXCEPTIONS +# include #endif #if nssv_CPP11_OR_GREATER -#include +# include #endif // Clang, GNUC, MSVC warning suppression macros: #if defined(__clang__) -#pragma clang diagnostic ignored "-Wreserved-user-defined-literal" -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wuser-defined-literals" +# pragma clang diagnostic ignored "-Wreserved-user-defined-literal" +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wuser-defined-literals" #elif nssv_COMPILER_GNUC_VERSION >= 480 -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wliteral-suffix" +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wliteral-suffix" #endif // __clang__ #if nssv_COMPILER_MSVC_VERSION >= 140 -#define nssv_SUPPRESS_MSGSL_WARNING(expr) [[gsl::suppress(expr)]] -#define nssv_SUPPRESS_MSVC_WARNING(code, descr) __pragma(warning(suppress : code)) -#define nssv_DISABLE_MSVC_WARNINGS(codes) __pragma(warning(push)) __pragma(warning(disable : codes)) +# define nssv_SUPPRESS_MSGSL_WARNING(expr) [[gsl::suppress(expr)]] +# define nssv_SUPPRESS_MSVC_WARNING(code, descr) __pragma(warning(suppress: code) ) +# define nssv_DISABLE_MSVC_WARNINGS(codes) __pragma(warning(push)) __pragma(warning(disable: codes)) #else -#define nssv_SUPPRESS_MSGSL_WARNING(expr) -#define nssv_SUPPRESS_MSVC_WARNING(code, descr) -#define nssv_DISABLE_MSVC_WARNINGS(codes) +# define nssv_SUPPRESS_MSGSL_WARNING(expr) +# define nssv_SUPPRESS_MSVC_WARNING(code, descr) +# define nssv_DISABLE_MSVC_WARNINGS(codes) #endif #if defined(__clang__) -#define nssv_RESTORE_WARNINGS() _Pragma("clang diagnostic pop") +# define nssv_RESTORE_WARNINGS() _Pragma("clang diagnostic pop") #elif nssv_COMPILER_GNUC_VERSION >= 480 -#define nssv_RESTORE_WARNINGS() _Pragma("GCC diagnostic pop") +# define nssv_RESTORE_WARNINGS() _Pragma("GCC diagnostic pop") #elif nssv_COMPILER_MSVC_VERSION >= 140 -#define nssv_RESTORE_WARNINGS() __pragma(warning(pop)) +# define nssv_RESTORE_WARNINGS() __pragma(warning(pop )) #else -#define nssv_RESTORE_WARNINGS() +# define nssv_RESTORE_WARNINGS() #endif // Suppress the following MSVC (GSL) warnings: @@ -467,892 +472,1033 @@ using std::operator<<; // use brace initialization, gsl::narrow_cast or gsl::narow // - C26481: gsl::b.1 : don't use pointer arithmetic. Use span instead -nssv_DISABLE_MSVC_WARNINGS(4455 26481 26472) - // nssv_DISABLE_CLANG_WARNINGS( "-Wuser-defined-literals" ) - // nssv_DISABLE_GNUC_WARNINGS( -Wliteral-suffix ) +nssv_DISABLE_MSVC_WARNINGS( 4455 26481 26472 ) +//nssv_DISABLE_CLANG_WARNINGS( "-Wuser-defined-literals" ) +//nssv_DISABLE_GNUC_WARNINGS( -Wliteral-suffix ) - namespace nonstd { - namespace sv_lite { +namespace nonstd { namespace sv_lite { - // - // basic_string_view declaration: - // +// +// basic_string_view declaration: +// - template > class basic_string_view; +template +< + class CharT, + class Traits = std::char_traits +> +class basic_string_view; - namespace detail { +namespace detail { - // support constexpr comparison in C++14; - // for C++17 and later, use provided traits: +// support constexpr comparison in C++14; +// for C++17 and later, use provided traits: - template inline nssv_constexpr14 int compare(CharT const* s1, CharT const* s2, std::size_t count) { - while(count-- != 0) { - if(*s1 < *s2) - return -1; - if(*s1 > *s2) - return +1; - ++s1; - ++s2; - } - return 0; +template< typename CharT > +inline nssv_constexpr14 int compare( CharT const * s1, CharT const * s2, std::size_t count ) +{ + while ( count-- != 0 ) + { + if ( *s1 < *s2 ) return -1; + if ( *s1 > *s2 ) return +1; + ++s1; ++s2; } + return 0; +} #if nssv_HAVE_BUILTIN_MEMCMP - // specialization of compare() for char, see also generic compare() above: +// specialization of compare() for char, see also generic compare() above: - inline nssv_constexpr14 int compare(char const* s1, char const* s2, std::size_t count) { return nssv_BUILTIN_MEMCMP(s1, s2, count); } +inline nssv_constexpr14 int compare( char const * s1, char const * s2, std::size_t count ) +{ + return nssv_BUILTIN_MEMCMP( s1, s2, count ); +} #endif #if nssv_HAVE_BUILTIN_STRLEN - // specialization of length() for char, see also generic length() further below: +// specialization of length() for char, see also generic length() further below: - inline nssv_constexpr std::size_t length(char const* s) { return nssv_BUILTIN_STRLEN(s); } +inline nssv_constexpr std::size_t length( char const * s ) +{ + return nssv_BUILTIN_STRLEN( s ); +} #endif #if defined(__OPTIMIZE__) - // gcc, clang provide __OPTIMIZE__ - // Expect tail call optimization to make length() non-recursive: +// gcc, clang provide __OPTIMIZE__ +// Expect tail call optimization to make length() non-recursive: - template inline nssv_constexpr std::size_t length(CharT* s, std::size_t result = 0) { - return *s == '\0' ? result : length(s + 1, result + 1); - } +template< typename CharT > +inline nssv_constexpr std::size_t length( CharT * s, std::size_t result = 0 ) +{ + return *s == '\0' ? result : length( s + 1, result + 1 ); +} #else // OPTIMIZE - // non-recursive: +// non-recursive: - template inline nssv_constexpr14 std::size_t length(CharT* s) { - std::size_t result = 0; - while(*s++ != '\0') { - ++result; - } - return result; +template< typename CharT > +inline nssv_constexpr14 std::size_t length( CharT * s ) +{ + std::size_t result = 0; + while ( *s++ != '\0' ) + { + ++result; } + return result; +} #endif // OPTIMIZE -#if nssv_CPP11_OR_GREATER && !nssv_CPP17_OR_GREATER +#if nssv_CPP11_OR_GREATER && ! nssv_CPP17_OR_GREATER #if defined(__OPTIMIZE__) - // gcc, clang provide __OPTIMIZE__ - // Expect tail call optimization to make search() non-recursive: +// gcc, clang provide __OPTIMIZE__ +// Expect tail call optimization to make search() non-recursive: - template > - constexpr const CharT* search(basic_string_view haystack, basic_string_view needle) { - return haystack.starts_with(needle) ? haystack.begin() : haystack.empty() ? haystack.end() : search(haystack.substr(1), needle); - } +template< class CharT, class Traits = std::char_traits > +constexpr const CharT* search( basic_string_view haystack, basic_string_view needle ) +{ + return haystack.starts_with( needle ) ? haystack.begin() : + haystack.empty() ? haystack.end() : search( haystack.substr(1), needle ); +} #else // OPTIMIZE - // non-recursive: +// non-recursive: + +#if nssv_CONFIG_CONSTEXPR11_STD_SEARCH - template > - constexpr const CharT* search(basic_string_view haystack, basic_string_view needle) { - return std::search(haystack.begin(), haystack.end(), needle.begin(), needle.end()); +template< class CharT, class Traits = std::char_traits > +constexpr const CharT* search( basic_string_view haystack, basic_string_view needle ) +{ + return std::search( haystack.begin(), haystack.end(), needle.begin(), needle.end() ); +} + +#else // nssv_CONFIG_CONSTEXPR11_STD_SEARCH + +template< class CharT, class Traits = std::char_traits > +nssv_constexpr14 const CharT* search( basic_string_view haystack, basic_string_view needle ) +{ + while ( needle.size() <= haystack.size() ) + { + if ( haystack.starts_with(needle) ) + { + return haystack.cbegin(); + } + haystack = basic_string_view{ haystack.begin() + 1, haystack.size() - 1U }; } + return haystack.cend(); +} +#endif // nssv_CONFIG_CONSTEXPR11_STD_SEARCH #endif // OPTIMIZE #endif // nssv_CPP11_OR_GREATER && ! nssv_CPP17_OR_GREATER - } // namespace detail +} // namespace detail - // - // basic_string_view: - // +// +// basic_string_view: +// - template */ - > - class basic_string_view { - public: - // Member types: +template +< + class CharT, + class Traits /* = std::char_traits */ +> +class basic_string_view +{ +public: + // Member types: - typedef Traits traits_type; - typedef CharT value_type; + typedef Traits traits_type; + typedef CharT value_type; - typedef CharT* pointer; - typedef CharT const* const_pointer; - typedef CharT& reference; - typedef CharT const& const_reference; + typedef CharT * pointer; + typedef CharT const * const_pointer; + typedef CharT & reference; + typedef CharT const & const_reference; - typedef const_pointer iterator; - typedef const_pointer const_iterator; - typedef std::reverse_iterator reverse_iterator; - typedef std::reverse_iterator const_reverse_iterator; + typedef const_pointer iterator; + typedef const_pointer const_iterator; + typedef std::reverse_iterator< const_iterator > reverse_iterator; + typedef std::reverse_iterator< const_iterator > const_reverse_iterator; - typedef std::size_t size_type; - typedef std::ptrdiff_t difference_type; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; - // 24.4.2.1 Construction and assignment: + // 24.4.2.1 Construction and assignment: - nssv_constexpr basic_string_view() nssv_noexcept : data_(nssv_nullptr), size_(0) {} + nssv_constexpr basic_string_view() nssv_noexcept + : data_( nssv_nullptr ) + , size_( 0 ) + {} #if nssv_CPP11_OR_GREATER - nssv_constexpr basic_string_view(basic_string_view const& other) nssv_noexcept = default; + nssv_constexpr basic_string_view( basic_string_view const & other ) nssv_noexcept = default; #else - nssv_constexpr basic_string_view(basic_string_view const& other) nssv_noexcept : data_(other.data_), size_(other.size_) {} + nssv_constexpr basic_string_view( basic_string_view const & other ) nssv_noexcept + : data_( other.data_) + , size_( other.size_) + {} #endif - nssv_constexpr basic_string_view(CharT const* s, size_type count) nssv_noexcept // non-standard noexcept - : data_(s), - size_(count) {} + nssv_constexpr basic_string_view( CharT const * s, size_type count ) nssv_noexcept // non-standard noexcept + : data_( s ) + , size_( count ) + {} - nssv_constexpr basic_string_view(CharT const* s) nssv_noexcept // non-standard noexcept - : data_(s) + nssv_constexpr basic_string_view( CharT const * s) nssv_noexcept // non-standard noexcept + : data_( s ) #if nssv_CPP17_OR_GREATER - , - size_(Traits::length(s)) + , size_( Traits::length(s) ) #elif nssv_CPP11_OR_GREATER - , - size_(detail::length(s)) + , size_( detail::length(s) ) #else - , - size_(Traits::length(s)) -#endif - { - } - -#if nssv_HAVE_NULLPTR -#if nssv_HAVE_IS_DELETE - nssv_constexpr basic_string_view(std::nullptr_t) nssv_noexcept = delete; -#else - private: - nssv_constexpr basic_string_view(std::nullptr_t) nssv_noexcept; - - public: + , size_( Traits::length(s) ) #endif + {} + +#if nssv_HAVE_NULLPTR +# if nssv_HAVE_IS_DELETE + nssv_constexpr basic_string_view( std::nullptr_t ) nssv_noexcept = delete; +# else + private: nssv_constexpr basic_string_view( std::nullptr_t ) nssv_noexcept; public: +# endif #endif - // Assignment: + // Assignment: #if nssv_CPP11_OR_GREATER - nssv_constexpr14 basic_string_view& operator=(basic_string_view const& other) nssv_noexcept = default; + nssv_constexpr14 basic_string_view & operator=( basic_string_view const & other ) nssv_noexcept = default; #else - nssv_constexpr14 basic_string_view& operator=(basic_string_view const& other) nssv_noexcept { - data_ = other.data_; - size_ = other.size_; - return *this; - } + nssv_constexpr14 basic_string_view & operator=( basic_string_view const & other ) nssv_noexcept + { + data_ = other.data_; + size_ = other.size_; + return *this; + } #endif - // 24.4.2.2 Iterator support: + // 24.4.2.2 Iterator support: - nssv_constexpr const_iterator begin() const nssv_noexcept { return data_; } - nssv_constexpr const_iterator end() const nssv_noexcept { return data_ + size_; } + nssv_constexpr const_iterator begin() const nssv_noexcept { return data_; } + nssv_constexpr const_iterator end() const nssv_noexcept { return data_ + size_; } - nssv_constexpr const_iterator cbegin() const nssv_noexcept { return begin(); } - nssv_constexpr const_iterator cend() const nssv_noexcept { return end(); } + nssv_constexpr const_iterator cbegin() const nssv_noexcept { return begin(); } + nssv_constexpr const_iterator cend() const nssv_noexcept { return end(); } - nssv_constexpr const_reverse_iterator rbegin() const nssv_noexcept { return const_reverse_iterator(end()); } - nssv_constexpr const_reverse_iterator rend() const nssv_noexcept { return const_reverse_iterator(begin()); } + nssv_constexpr const_reverse_iterator rbegin() const nssv_noexcept { return const_reverse_iterator( end() ); } + nssv_constexpr const_reverse_iterator rend() const nssv_noexcept { return const_reverse_iterator( begin() ); } - nssv_constexpr const_reverse_iterator crbegin() const nssv_noexcept { return rbegin(); } - nssv_constexpr const_reverse_iterator crend() const nssv_noexcept { return rend(); } + nssv_constexpr const_reverse_iterator crbegin() const nssv_noexcept { return rbegin(); } + nssv_constexpr const_reverse_iterator crend() const nssv_noexcept { return rend(); } - // 24.4.2.3 Capacity: + // 24.4.2.3 Capacity: - nssv_constexpr size_type size() const nssv_noexcept { return size_; } - nssv_constexpr size_type length() const nssv_noexcept { return size_; } - nssv_constexpr size_type max_size() const nssv_noexcept { return (std::numeric_limits::max)(); } + nssv_constexpr size_type size() const nssv_noexcept { return size_; } + nssv_constexpr size_type length() const nssv_noexcept { return size_; } + nssv_constexpr size_type max_size() const nssv_noexcept { return (std::numeric_limits< size_type >::max)(); } - // since C++20 - nssv_nodiscard nssv_constexpr bool empty() const nssv_noexcept { return 0 == size_; } + // since C++20 + nssv_nodiscard nssv_constexpr bool empty() const nssv_noexcept + { + return 0 == size_; + } - // 24.4.2.4 Element access: + // 24.4.2.4 Element access: - nssv_constexpr const_reference operator[](size_type pos) const { return data_at(pos); } + nssv_constexpr const_reference operator[]( size_type pos ) const + { + return data_at( pos ); + } - nssv_constexpr14 const_reference at(size_type pos) const { + nssv_constexpr14 const_reference at( size_type pos ) const + { #if nssv_CONFIG_NO_EXCEPTIONS - assert(pos < size()); + assert( pos < size() ); #else - if(pos >= size()) { - throw std::out_of_range("nonstd::string_view::at()"); - } -#endif - return data_at(pos); + if ( pos >= size() ) + { + throw std::out_of_range("nonstd::string_view::at()"); } +#endif + return data_at( pos ); + } - nssv_constexpr const_reference front() const { return data_at(0); } - nssv_constexpr const_reference back() const { return data_at(size() - 1); } + nssv_constexpr const_reference front() const { return data_at( 0 ); } + nssv_constexpr const_reference back() const { return data_at( size() - 1 ); } - nssv_constexpr const_pointer data() const nssv_noexcept { return data_; } + nssv_constexpr const_pointer data() const nssv_noexcept { return data_; } - // 24.4.2.5 Modifiers: + // 24.4.2.5 Modifiers: - nssv_constexpr14 void remove_prefix(size_type n) { - assert(n <= size()); - data_ += n; - size_ -= n; - } + nssv_constexpr14 void remove_prefix( size_type n ) + { + assert( n <= size() ); + data_ += n; + size_ -= n; + } - nssv_constexpr14 void remove_suffix(size_type n) { - assert(n <= size()); - size_ -= n; - } + nssv_constexpr14 void remove_suffix( size_type n ) + { + assert( n <= size() ); + size_ -= n; + } - nssv_constexpr14 void swap(basic_string_view& other) nssv_noexcept { - const basic_string_view tmp(other); - other = *this; - *this = tmp; - } + nssv_constexpr14 void swap( basic_string_view & other ) nssv_noexcept + { + const basic_string_view tmp(other); + other = *this; + *this = tmp; + } - // 24.4.2.6 String operations: + // 24.4.2.6 String operations: - size_type copy(CharT* dest, size_type n, size_type pos = 0) const { + size_type copy( CharT * dest, size_type n, size_type pos = 0 ) const + { #if nssv_CONFIG_NO_EXCEPTIONS - assert(pos <= size()); + assert( pos <= size() ); #else - if(pos > size()) { - throw std::out_of_range("nonstd::string_view::copy()"); - } + if ( pos > size() ) + { + throw std::out_of_range("nonstd::string_view::copy()"); + } #endif - const size_type rlen = (std::min)(n, size() - pos); + const size_type rlen = (std::min)( n, size() - pos ); - (void)Traits::copy(dest, data() + pos, rlen); + (void) Traits::copy( dest, data() + pos, rlen ); - return rlen; - } + return rlen; + } - nssv_constexpr14 basic_string_view substr(size_type pos = 0, size_type n = npos) const { + nssv_constexpr14 basic_string_view substr( size_type pos = 0, size_type n = npos ) const + { #if nssv_CONFIG_NO_EXCEPTIONS - assert(pos <= size()); + assert( pos <= size() ); #else - if(pos > size()) { - throw std::out_of_range("nonstd::string_view::substr()"); - } -#endif - return basic_string_view(data() + pos, (std::min)(n, size() - pos)); - } - - // compare(), 6x: - - nssv_constexpr14 int compare(basic_string_view other) const nssv_noexcept // (1) - { -#if nssv_CPP17_OR_GREATER - if(const int result = Traits::compare(data(), other.data(), (std::min)(size(), other.size()))) -#else - if(const int result = detail::compare(data(), other.data(), (std::min)(size(), other.size()))) -#endif - { - return result; - } - - return size() == other.size() ? 0 : size() < other.size() ? -1 : 1; - } - - nssv_constexpr int compare(size_type pos1, size_type n1, basic_string_view other) const // (2) - { - return substr(pos1, n1).compare(other); - } - - nssv_constexpr int compare(size_type pos1, size_type n1, basic_string_view other, size_type pos2, size_type n2) const // (3) - { - return substr(pos1, n1).compare(other.substr(pos2, n2)); - } - - nssv_constexpr int compare(CharT const* s) const // (4) - { - return compare(basic_string_view(s)); - } - - nssv_constexpr int compare(size_type pos1, size_type n1, CharT const* s) const // (5) - { - return substr(pos1, n1).compare(basic_string_view(s)); - } - - nssv_constexpr int compare(size_type pos1, size_type n1, CharT const* s, size_type n2) const // (6) - { - return substr(pos1, n1).compare(basic_string_view(s, n2)); - } - - // 24.4.2.7 Searching: - - // starts_with(), 3x, since C++20: - - nssv_constexpr bool starts_with(basic_string_view v) const nssv_noexcept // (1) - { - return size() >= v.size() && compare(0, v.size(), v) == 0; - } - - nssv_constexpr bool starts_with(CharT c) const nssv_noexcept // (2) + if ( pos > size() ) { - return starts_with(basic_string_view(&c, 1)); - } - - nssv_constexpr bool starts_with(CharT const* s) const // (3) - { - return starts_with(basic_string_view(s)); - } - - // ends_with(), 3x, since C++20: - - nssv_constexpr bool ends_with(basic_string_view v) const nssv_noexcept // (1) - { - return size() >= v.size() && compare(size() - v.size(), npos, v) == 0; - } - - nssv_constexpr bool ends_with(CharT c) const nssv_noexcept // (2) - { - return ends_with(basic_string_view(&c, 1)); - } - - nssv_constexpr bool ends_with(CharT const* s) const // (3) - { - return ends_with(basic_string_view(s)); + throw std::out_of_range("nonstd::string_view::substr()"); } +#endif + return basic_string_view( data() + pos, (std::min)( n, size() - pos ) ); + } - // find(), 4x: + // compare(), 6x: - nssv_constexpr14 size_type find(basic_string_view v, size_type pos = 0) const nssv_noexcept // (1) - { - return assert(v.size() == 0 || v.data() != nssv_nullptr), pos >= size() ? npos - : to_pos( -#if nssv_CPP11_OR_GREATER && !nssv_CPP17_OR_GREATER - detail::search(substr(pos), v) + nssv_constexpr14 int compare( basic_string_view other ) const nssv_noexcept // (1) + { +#if nssv_CPP17_OR_GREATER + if ( const int result = Traits::compare( data(), other.data(), (std::min)( size(), other.size() ) ) ) #else - std::search(cbegin() + pos, cend(), v.cbegin(), - v.cend(), Traits::eq) + if ( const int result = detail::compare( data(), other.data(), (std::min)( size(), other.size() ) ) ) #endif - ); - } - - nssv_constexpr size_type find(CharT c, size_type pos = 0) const nssv_noexcept // (2) - { - return find(basic_string_view(&c, 1), pos); - } - - nssv_constexpr size_type find(CharT const* s, size_type pos, size_type n) const // (3) - { - return find(basic_string_view(s, n), pos); - } - - nssv_constexpr size_type find(CharT const* s, size_type pos = 0) const // (4) - { - return find(basic_string_view(s), pos); - } - - // rfind(), 4x: - - nssv_constexpr14 size_type rfind(basic_string_view v, size_type pos = npos) const nssv_noexcept // (1) - { - if(size() < v.size()) { - return npos; - } - - if(v.empty()) { - return (std::min)(size(), pos); - } - - const_iterator last = cbegin() + (std::min)(size() - v.size(), pos) + v.size(); - const_iterator result = std::find_end(cbegin(), last, v.cbegin(), v.cend(), Traits::eq); - - return result != last ? size_type(result - cbegin()) : npos; - } - - nssv_constexpr14 size_type rfind(CharT c, size_type pos = npos) const nssv_noexcept // (2) - { - return rfind(basic_string_view(&c, 1), pos); - } - - nssv_constexpr14 size_type rfind(CharT const* s, size_type pos, size_type n) const // (3) - { - return rfind(basic_string_view(s, n), pos); - } - - nssv_constexpr14 size_type rfind(CharT const* s, size_type pos = npos) const // (4) - { - return rfind(basic_string_view(s), pos); - } - - // find_first_of(), 4x: - - nssv_constexpr size_type find_first_of(basic_string_view v, size_type pos = 0) const nssv_noexcept // (1) - { - return pos >= size() ? npos : to_pos(std::find_first_of(cbegin() + pos, cend(), v.cbegin(), v.cend(), Traits::eq)); - } - - nssv_constexpr size_type find_first_of(CharT c, size_type pos = 0) const nssv_noexcept // (2) - { - return find_first_of(basic_string_view(&c, 1), pos); - } - - nssv_constexpr size_type find_first_of(CharT const* s, size_type pos, size_type n) const // (3) - { - return find_first_of(basic_string_view(s, n), pos); - } - - nssv_constexpr size_type find_first_of(CharT const* s, size_type pos = 0) const // (4) - { - return find_first_of(basic_string_view(s), pos); - } - - // find_last_of(), 4x: - - nssv_constexpr size_type find_last_of(basic_string_view v, size_type pos = npos) const nssv_noexcept // (1) - { - return empty() ? npos - : pos >= size() - ? find_last_of(v, size() - 1) - : to_pos(std::find_first_of(const_reverse_iterator(cbegin() + pos + 1), crend(), v.cbegin(), v.cend(), Traits::eq)); - } - - nssv_constexpr size_type find_last_of(CharT c, size_type pos = npos) const nssv_noexcept // (2) - { - return find_last_of(basic_string_view(&c, 1), pos); - } - - nssv_constexpr size_type find_last_of(CharT const* s, size_type pos, size_type count) const // (3) - { - return find_last_of(basic_string_view(s, count), pos); - } - - nssv_constexpr size_type find_last_of(CharT const* s, size_type pos = npos) const // (4) { - return find_last_of(basic_string_view(s), pos); + return result; } - // find_first_not_of(), 4x: - - nssv_constexpr size_type find_first_not_of(basic_string_view v, size_type pos = 0) const nssv_noexcept // (1) - { - return pos >= size() ? npos : to_pos(std::find_if(cbegin() + pos, cend(), not_in_view(v))); - } + return size() == other.size() ? 0 : size() < other.size() ? -1 : 1; + } - nssv_constexpr size_type find_first_not_of(CharT c, size_type pos = 0) const nssv_noexcept // (2) - { - return find_first_not_of(basic_string_view(&c, 1), pos); - } + nssv_constexpr int compare( size_type pos1, size_type n1, basic_string_view other ) const // (2) + { + return substr( pos1, n1 ).compare( other ); + } - nssv_constexpr size_type find_first_not_of(CharT const* s, size_type pos, size_type count) const // (3) - { - return find_first_not_of(basic_string_view(s, count), pos); - } + nssv_constexpr int compare( size_type pos1, size_type n1, basic_string_view other, size_type pos2, size_type n2 ) const // (3) + { + return substr( pos1, n1 ).compare( other.substr( pos2, n2 ) ); + } - nssv_constexpr size_type find_first_not_of(CharT const* s, size_type pos = 0) const // (4) - { - return find_first_not_of(basic_string_view(s), pos); - } + nssv_constexpr int compare( CharT const * s ) const // (4) + { + return compare( basic_string_view( s ) ); + } - // find_last_not_of(), 4x: + nssv_constexpr int compare( size_type pos1, size_type n1, CharT const * s ) const // (5) + { + return substr( pos1, n1 ).compare( basic_string_view( s ) ); + } - nssv_constexpr size_type find_last_not_of(basic_string_view v, size_type pos = npos) const nssv_noexcept // (1) - { - return empty() ? npos - : pos >= size() ? find_last_not_of(v, size() - 1) - : to_pos(std::find_if(const_reverse_iterator(cbegin() + pos + 1), crend(), not_in_view(v))); - } + nssv_constexpr int compare( size_type pos1, size_type n1, CharT const * s, size_type n2 ) const // (6) + { + return substr( pos1, n1 ).compare( basic_string_view( s, n2 ) ); + } - nssv_constexpr size_type find_last_not_of(CharT c, size_type pos = npos) const nssv_noexcept // (2) - { - return find_last_not_of(basic_string_view(&c, 1), pos); - } + // 24.4.2.7 Searching: - nssv_constexpr size_type find_last_not_of(CharT const* s, size_type pos, size_type count) const // (3) - { - return find_last_not_of(basic_string_view(s, count), pos); - } + // starts_with(), 3x, since C++20: - nssv_constexpr size_type find_last_not_of(CharT const* s, size_type pos = npos) const // (4) - { - return find_last_not_of(basic_string_view(s), pos); - } + nssv_constexpr bool starts_with( basic_string_view v ) const nssv_noexcept // (1) + { + return size() >= v.size() && compare( 0, v.size(), v ) == 0; + } - // Constants: + nssv_constexpr bool starts_with( CharT c ) const nssv_noexcept // (2) + { + return starts_with( basic_string_view( &c, 1 ) ); + } -#if nssv_CPP17_OR_GREATER - static nssv_constexpr size_type npos = size_type(-1); -#elif nssv_CPP11_OR_GREATER - enum : size_type { npos = size_type(-1) }; -#else - enum { npos = size_type(-1) }; -#endif + nssv_constexpr bool starts_with( CharT const * s ) const // (3) + { + return starts_with( basic_string_view( s ) ); + } - private: - struct not_in_view { - const basic_string_view v; + // ends_with(), 3x, since C++20: - nssv_constexpr explicit not_in_view(basic_string_view v_) - : v(v_) {} + nssv_constexpr bool ends_with( basic_string_view v ) const nssv_noexcept // (1) + { + return size() >= v.size() && compare( size() - v.size(), npos, v ) == 0; + } - nssv_constexpr bool operator()(CharT c) const { return npos == v.find_first_of(c); } - }; + nssv_constexpr bool ends_with( CharT c ) const nssv_noexcept // (2) + { + return ends_with( basic_string_view( &c, 1 ) ); + } - nssv_constexpr size_type to_pos(const_iterator it) const { return it == cend() ? npos : size_type(it - cbegin()); } + nssv_constexpr bool ends_with( CharT const * s ) const // (3) + { + return ends_with( basic_string_view( s ) ); + } - nssv_constexpr size_type to_pos(const_reverse_iterator it) const { return it == crend() ? npos : size_type(crend() - it - 1); } + // find(), 4x: - nssv_constexpr const_reference data_at(size_type pos) const { -#if nssv_BETWEEN(nssv_COMPILER_GNUC_VERSION, 1, 500) - return data_[pos]; + nssv_constexpr14 size_type find( basic_string_view v, size_type pos = 0 ) const nssv_noexcept // (1) + { + return assert( v.size() == 0 || v.data() != nssv_nullptr ) + , pos >= size() + ? npos : to_pos( +#if nssv_CPP11_OR_GREATER && ! nssv_CPP17_OR_GREATER + detail::search( substr(pos), v ) #else - return assert(pos < size()), data_[pos]; + std::search( cbegin() + pos, cend(), v.cbegin(), v.cend(), Traits::eq ) #endif - } - - private: - const_pointer data_; - size_type size_; - - public: -#if nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS - - template - basic_string_view(std::basic_string const& s) nssv_noexcept : data_(s.data()), size_(s.size()) {} + ); + } -#if nssv_HAVE_EXPLICIT_CONVERSION + nssv_constexpr size_type find( CharT c, size_type pos = 0 ) const nssv_noexcept // (2) + { + return find( basic_string_view( &c, 1 ), pos ); + } - template explicit operator std::basic_string() const { return to_string(Allocator()); } + nssv_constexpr size_type find( CharT const * s, size_type pos, size_type n ) const // (3) + { + return find( basic_string_view( s, n ), pos ); + } -#endif // nssv_HAVE_EXPLICIT_CONVERSION + nssv_constexpr size_type find( CharT const * s, size_type pos = 0 ) const // (4) + { + return find( basic_string_view( s ), pos ); + } -#if nssv_CPP11_OR_GREATER + // rfind(), 4x: - template > - std::basic_string to_string(Allocator const& a = Allocator()) const { - return std::basic_string(begin(), end(), a); + nssv_constexpr14 size_type rfind( basic_string_view v, size_type pos = npos ) const nssv_noexcept // (1) + { + if ( size() < v.size() ) + { + return npos; } -#else - - std::basic_string to_string() const { return std::basic_string(begin(), end()); } - - template std::basic_string to_string(Allocator const& a) const { - return std::basic_string(begin(), end(), a); + if ( v.empty() ) + { + return (std::min)( size(), pos ); } -#endif // nssv_CPP11_OR_GREATER - -#endif // nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS - }; - - // - // Non-member functions: - // - - // 24.4.3 Non-member comparison functions: - // lexicographically compare two string views (function template): - - template - nssv_constexpr bool operator==(basic_string_view lhs, basic_string_view rhs) nssv_noexcept { - return lhs.size() == rhs.size() && lhs.compare(rhs) == 0; - } - - template - nssv_constexpr bool operator!=(basic_string_view lhs, basic_string_view rhs) nssv_noexcept { - return !(lhs == rhs); - } + const_iterator last = cbegin() + (std::min)( size() - v.size(), pos ) + v.size(); + const_iterator result = std::find_end( cbegin(), last, v.cbegin(), v.cend(), Traits::eq ); - template - nssv_constexpr bool operator<(basic_string_view lhs, basic_string_view rhs) nssv_noexcept { - return lhs.compare(rhs) < 0; + return result != last ? size_type( result - cbegin() ) : npos; } - template - nssv_constexpr bool operator<=(basic_string_view lhs, basic_string_view rhs) nssv_noexcept { - return lhs.compare(rhs) <= 0; + nssv_constexpr14 size_type rfind( CharT c, size_type pos = npos ) const nssv_noexcept // (2) + { + return rfind( basic_string_view( &c, 1 ), pos ); } - template - nssv_constexpr bool operator>(basic_string_view lhs, basic_string_view rhs) nssv_noexcept { - return lhs.compare(rhs) > 0; + nssv_constexpr14 size_type rfind( CharT const * s, size_type pos, size_type n ) const // (3) + { + return rfind( basic_string_view( s, n ), pos ); } - template - nssv_constexpr bool operator>=(basic_string_view lhs, basic_string_view rhs) nssv_noexcept { - return lhs.compare(rhs) >= 0; + nssv_constexpr14 size_type rfind( CharT const * s, size_type pos = npos ) const // (4) + { + return rfind( basic_string_view( s ), pos ); } - // Let S be basic_string_view, and sv be an instance of S. - // Implementations shall provide sufficient additional overloads marked - // constexpr and noexcept so that an object t with an implicit conversion - // to S can be compared according to Table 67. - -#if !nssv_CPP11_OR_GREATER || nssv_BETWEEN(nssv_COMPILER_MSVC_VERSION, 100, 141) - - // accommodate for older compilers: + // find_first_of(), 4x: - // == - - template - nssv_constexpr bool operator==(basic_string_view lhs, CharT const* rhs) nssv_noexcept { - return lhs.size() == detail::length(rhs) && lhs.compare(rhs) == 0; + nssv_constexpr size_type find_first_of( basic_string_view v, size_type pos = 0 ) const nssv_noexcept // (1) + { + return pos >= size() + ? npos + : to_pos( std::find_first_of( cbegin() + pos, cend(), v.cbegin(), v.cend(), Traits::eq ) ); } - template - nssv_constexpr bool operator==(CharT const* lhs, basic_string_view rhs) nssv_noexcept { - return detail::length(lhs) == rhs.size() && rhs.compare(lhs) == 0; + nssv_constexpr size_type find_first_of( CharT c, size_type pos = 0 ) const nssv_noexcept // (2) + { + return find_first_of( basic_string_view( &c, 1 ), pos ); } - template - nssv_constexpr bool operator==(basic_string_view lhs, std::basic_string rhs) nssv_noexcept { - return lhs.size() == rhs.size() && lhs.compare(rhs) == 0; + nssv_constexpr size_type find_first_of( CharT const * s, size_type pos, size_type n ) const // (3) + { + return find_first_of( basic_string_view( s, n ), pos ); } - template - nssv_constexpr bool operator==(std::basic_string rhs, basic_string_view lhs) nssv_noexcept { - return lhs.size() == rhs.size() && lhs.compare(rhs) == 0; + nssv_constexpr size_type find_first_of( CharT const * s, size_type pos = 0 ) const // (4) + { + return find_first_of( basic_string_view( s ), pos ); } - // != + // find_last_of(), 4x: - template - nssv_constexpr bool operator!=(basic_string_view lhs, CharT const* rhs) nssv_noexcept { - return !(lhs == rhs); + nssv_constexpr size_type find_last_of( basic_string_view v, size_type pos = npos ) const nssv_noexcept // (1) + { + return empty() + ? npos + : pos >= size() + ? find_last_of( v, size() - 1 ) + : to_pos( std::find_first_of( const_reverse_iterator( cbegin() + pos + 1 ), crend(), v.cbegin(), v.cend(), Traits::eq ) ); } - template - nssv_constexpr bool operator!=(CharT const* lhs, basic_string_view rhs) nssv_noexcept { - return !(lhs == rhs); + nssv_constexpr size_type find_last_of( CharT c, size_type pos = npos ) const nssv_noexcept // (2) + { + return find_last_of( basic_string_view( &c, 1 ), pos ); } - template - nssv_constexpr bool operator!=(basic_string_view lhs, std::basic_string rhs) nssv_noexcept { - return !(lhs == rhs); + nssv_constexpr size_type find_last_of( CharT const * s, size_type pos, size_type count ) const // (3) + { + return find_last_of( basic_string_view( s, count ), pos ); } - template - nssv_constexpr bool operator!=(std::basic_string rhs, basic_string_view lhs) nssv_noexcept { - return !(lhs == rhs); + nssv_constexpr size_type find_last_of( CharT const * s, size_type pos = npos ) const // (4) + { + return find_last_of( basic_string_view( s ), pos ); } - // < + // find_first_not_of(), 4x: - template - nssv_constexpr bool operator<(basic_string_view lhs, CharT const* rhs) nssv_noexcept { - return lhs.compare(rhs) < 0; + nssv_constexpr size_type find_first_not_of( basic_string_view v, size_type pos = 0 ) const nssv_noexcept // (1) + { + return pos >= size() + ? npos + : to_pos( std::find_if( cbegin() + pos, cend(), not_in_view( v ) ) ); } - template - nssv_constexpr bool operator<(CharT const* lhs, basic_string_view rhs) nssv_noexcept { - return rhs.compare(lhs) > 0; + nssv_constexpr size_type find_first_not_of( CharT c, size_type pos = 0 ) const nssv_noexcept // (2) + { + return find_first_not_of( basic_string_view( &c, 1 ), pos ); } - template - nssv_constexpr bool operator<(basic_string_view lhs, std::basic_string rhs) nssv_noexcept { - return lhs.compare(rhs) < 0; + nssv_constexpr size_type find_first_not_of( CharT const * s, size_type pos, size_type count ) const // (3) + { + return find_first_not_of( basic_string_view( s, count ), pos ); } - template - nssv_constexpr bool operator<(std::basic_string rhs, basic_string_view lhs) nssv_noexcept { - return rhs.compare(lhs) > 0; + nssv_constexpr size_type find_first_not_of( CharT const * s, size_type pos = 0 ) const // (4) + { + return find_first_not_of( basic_string_view( s ), pos ); } - // <= + // find_last_not_of(), 4x: - template - nssv_constexpr bool operator<=(basic_string_view lhs, CharT const* rhs) nssv_noexcept { - return lhs.compare(rhs) <= 0; + nssv_constexpr size_type find_last_not_of( basic_string_view v, size_type pos = npos ) const nssv_noexcept // (1) + { + return empty() + ? npos + : pos >= size() + ? find_last_not_of( v, size() - 1 ) + : to_pos( std::find_if( const_reverse_iterator( cbegin() + pos + 1 ), crend(), not_in_view( v ) ) ); } - template - nssv_constexpr bool operator<=(CharT const* lhs, basic_string_view rhs) nssv_noexcept { - return rhs.compare(lhs) >= 0; + nssv_constexpr size_type find_last_not_of( CharT c, size_type pos = npos ) const nssv_noexcept // (2) + { + return find_last_not_of( basic_string_view( &c, 1 ), pos ); } - template - nssv_constexpr bool operator<=(basic_string_view lhs, std::basic_string rhs) nssv_noexcept { - return lhs.compare(rhs) <= 0; + nssv_constexpr size_type find_last_not_of( CharT const * s, size_type pos, size_type count ) const // (3) + { + return find_last_not_of( basic_string_view( s, count ), pos ); } - template - nssv_constexpr bool operator<=(std::basic_string rhs, basic_string_view lhs) nssv_noexcept { - return rhs.compare(lhs) >= 0; + nssv_constexpr size_type find_last_not_of( CharT const * s, size_type pos = npos ) const // (4) + { + return find_last_not_of( basic_string_view( s ), pos ); } - // > - - template - nssv_constexpr bool operator>(basic_string_view lhs, CharT const* rhs) nssv_noexcept { - return lhs.compare(rhs) > 0; - } + // Constants: - template - nssv_constexpr bool operator>(CharT const* lhs, basic_string_view rhs) nssv_noexcept { - return rhs.compare(lhs) < 0; - } - - template - nssv_constexpr bool operator>(basic_string_view lhs, std::basic_string rhs) nssv_noexcept { - return lhs.compare(rhs) > 0; - } +#if nssv_CPP17_OR_GREATER + static nssv_constexpr size_type npos = size_type(-1); +#elif nssv_CPP11_OR_GREATER + enum : size_type { npos = size_type(-1) }; +#else + enum { npos = size_type(-1) }; +#endif - template - nssv_constexpr bool operator>(std::basic_string rhs, basic_string_view lhs) nssv_noexcept { - return rhs.compare(lhs) < 0; - } +private: + struct not_in_view + { + const basic_string_view v; - // >= + nssv_constexpr explicit not_in_view( basic_string_view v_ ) : v( v_ ) {} - template - nssv_constexpr bool operator>=(basic_string_view lhs, CharT const* rhs) nssv_noexcept { - return lhs.compare(rhs) >= 0; - } + nssv_constexpr bool operator()( CharT c ) const + { + return npos == v.find_first_of( c ); + } + }; - template - nssv_constexpr bool operator>=(CharT const* lhs, basic_string_view rhs) nssv_noexcept { - return rhs.compare(lhs) <= 0; + nssv_constexpr size_type to_pos( const_iterator it ) const + { + return it == cend() ? npos : size_type( it - cbegin() ); } - template - nssv_constexpr bool operator>=(basic_string_view lhs, std::basic_string rhs) nssv_noexcept { - return lhs.compare(rhs) >= 0; + nssv_constexpr size_type to_pos( const_reverse_iterator it ) const + { + return it == crend() ? npos : size_type( crend() - it - 1 ); } - template - nssv_constexpr bool operator>=(std::basic_string rhs, basic_string_view lhs) nssv_noexcept { - return rhs.compare(lhs) <= 0; + nssv_constexpr const_reference data_at( size_type pos ) const + { +#if nssv_BETWEEN( nssv_COMPILER_GNUC_VERSION, 1, 500 ) + return data_[pos]; +#else + return assert( pos < size() ), data_[pos]; +#endif } -#else // newer compilers: - -#define nssv_BASIC_STRING_VIEW_I(T, U) typename std::decay>::type +private: + const_pointer data_; + size_type size_; -#if defined(_MSC_VER) // issue 40 -#define nssv_MSVC_ORDER(x) , int = x -#else -#define nssv_MSVC_ORDER(x) /*, int=x*/ -#endif +public: +#if nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS - // == + template< class Allocator > + basic_string_view( std::basic_string const & s ) nssv_noexcept + : data_( s.data() ) + , size_( s.size() ) + {} - template - nssv_constexpr bool operator==(basic_string_view lhs, nssv_BASIC_STRING_VIEW_I(CharT, Traits) rhs) nssv_noexcept { - return lhs.size() == rhs.size() && lhs.compare(rhs) == 0; - } +#if nssv_HAVE_EXPLICIT_CONVERSION - template - nssv_constexpr bool operator==(nssv_BASIC_STRING_VIEW_I(CharT, Traits) lhs, basic_string_view rhs) nssv_noexcept { - return lhs.size() == rhs.size() && lhs.compare(rhs) == 0; + template< class Allocator > + explicit operator std::basic_string() const + { + return to_string( Allocator() ); } - // != +#endif // nssv_HAVE_EXPLICIT_CONVERSION - template - nssv_constexpr bool operator!=(basic_string_view lhs, nssv_BASIC_STRING_VIEW_I(CharT, Traits) rhs) nssv_noexcept { - return !(lhs == rhs); - } +#if nssv_CPP11_OR_GREATER - template - nssv_constexpr bool operator!=(nssv_BASIC_STRING_VIEW_I(CharT, Traits) lhs, basic_string_view rhs) nssv_noexcept { - return !(lhs == rhs); + template< class Allocator = std::allocator > + std::basic_string + to_string( Allocator const & a = Allocator() ) const + { + return std::basic_string( begin(), end(), a ); } - // < +#else - template - nssv_constexpr bool operator<(basic_string_view lhs, nssv_BASIC_STRING_VIEW_I(CharT, Traits) rhs) nssv_noexcept { - return lhs.compare(rhs) < 0; + std::basic_string + to_string() const + { + return std::basic_string( begin(), end() ); } - template - nssv_constexpr bool operator<(nssv_BASIC_STRING_VIEW_I(CharT, Traits) lhs, basic_string_view rhs) nssv_noexcept { - return lhs.compare(rhs) < 0; + template< class Allocator > + std::basic_string + to_string( Allocator const & a ) const + { + return std::basic_string( begin(), end(), a ); } - // <= - - template - nssv_constexpr bool operator<=(basic_string_view lhs, nssv_BASIC_STRING_VIEW_I(CharT, Traits) rhs) nssv_noexcept { - return lhs.compare(rhs) <= 0; - } +#endif // nssv_CPP11_OR_GREATER - template - nssv_constexpr bool operator<=(nssv_BASIC_STRING_VIEW_I(CharT, Traits) lhs, basic_string_view rhs) nssv_noexcept { - return lhs.compare(rhs) <= 0; - } +#endif // nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS +}; - // > +// +// Non-member functions: +// - template - nssv_constexpr bool operator>(basic_string_view lhs, nssv_BASIC_STRING_VIEW_I(CharT, Traits) rhs) nssv_noexcept { - return lhs.compare(rhs) > 0; - } +// 24.4.3 Non-member comparison functions: +// lexicographically compare two string views (function template): + +template< class CharT, class Traits > +nssv_constexpr bool operator== ( + basic_string_view lhs, + basic_string_view rhs ) nssv_noexcept +{ return lhs.size() == rhs.size() && lhs.compare( rhs ) == 0; } + +template< class CharT, class Traits > +nssv_constexpr bool operator!= ( + basic_string_view lhs, + basic_string_view rhs ) nssv_noexcept +{ return !( lhs == rhs ); } + +template< class CharT, class Traits > +nssv_constexpr bool operator< ( + basic_string_view lhs, + basic_string_view rhs ) nssv_noexcept +{ return lhs.compare( rhs ) < 0; } + +template< class CharT, class Traits > +nssv_constexpr bool operator<= ( + basic_string_view lhs, + basic_string_view rhs ) nssv_noexcept +{ return lhs.compare( rhs ) <= 0; } + +template< class CharT, class Traits > +nssv_constexpr bool operator> ( + basic_string_view lhs, + basic_string_view rhs ) nssv_noexcept +{ return lhs.compare( rhs ) > 0; } + +template< class CharT, class Traits > +nssv_constexpr bool operator>= ( + basic_string_view lhs, + basic_string_view rhs ) nssv_noexcept +{ return lhs.compare( rhs ) >= 0; } + +// Let S be basic_string_view, and sv be an instance of S. +// Implementations shall provide sufficient additional overloads marked +// constexpr and noexcept so that an object t with an implicit conversion +// to S can be compared according to Table 67. + +#if ! nssv_CPP11_OR_GREATER || nssv_BETWEEN( nssv_COMPILER_MSVC_VERSION, 100, 141 ) + +// accommodate for older compilers: + +// == + +template< class CharT, class Traits> +nssv_constexpr bool operator==( + basic_string_view lhs, + CharT const * rhs ) nssv_noexcept +{ return lhs.size() == detail::length( rhs ) && lhs.compare( rhs ) == 0; } + +template< class CharT, class Traits> +nssv_constexpr bool operator==( + CharT const * lhs, + basic_string_view rhs ) nssv_noexcept +{ return detail::length( lhs ) == rhs.size() && rhs.compare( lhs ) == 0; } + +template< class CharT, class Traits> +nssv_constexpr bool operator==( + basic_string_view lhs, + std::basic_string rhs ) nssv_noexcept +{ return lhs.size() == rhs.size() && lhs.compare( rhs ) == 0; } + +template< class CharT, class Traits> +nssv_constexpr bool operator==( + std::basic_string rhs, + basic_string_view lhs ) nssv_noexcept +{ return lhs.size() == rhs.size() && lhs.compare( rhs ) == 0; } + +// != + +template< class CharT, class Traits> +nssv_constexpr bool operator!=( + basic_string_view lhs, + CharT const * rhs ) nssv_noexcept +{ return !( lhs == rhs ); } + +template< class CharT, class Traits> +nssv_constexpr bool operator!=( + CharT const * lhs, + basic_string_view rhs ) nssv_noexcept +{ return !( lhs == rhs ); } + +template< class CharT, class Traits> +nssv_constexpr bool operator!=( + basic_string_view lhs, + std::basic_string rhs ) nssv_noexcept +{ return !( lhs == rhs ); } + +template< class CharT, class Traits> +nssv_constexpr bool operator!=( + std::basic_string rhs, + basic_string_view lhs ) nssv_noexcept +{ return !( lhs == rhs ); } + +// < + +template< class CharT, class Traits> +nssv_constexpr bool operator<( + basic_string_view lhs, + CharT const * rhs ) nssv_noexcept +{ return lhs.compare( rhs ) < 0; } + +template< class CharT, class Traits> +nssv_constexpr bool operator<( + CharT const * lhs, + basic_string_view rhs ) nssv_noexcept +{ return rhs.compare( lhs ) > 0; } + +template< class CharT, class Traits> +nssv_constexpr bool operator<( + basic_string_view lhs, + std::basic_string rhs ) nssv_noexcept +{ return lhs.compare( rhs ) < 0; } + +template< class CharT, class Traits> +nssv_constexpr bool operator<( + std::basic_string rhs, + basic_string_view lhs ) nssv_noexcept +{ return rhs.compare( lhs ) > 0; } + +// <= + +template< class CharT, class Traits> +nssv_constexpr bool operator<=( + basic_string_view lhs, + CharT const * rhs ) nssv_noexcept +{ return lhs.compare( rhs ) <= 0; } + +template< class CharT, class Traits> +nssv_constexpr bool operator<=( + CharT const * lhs, + basic_string_view rhs ) nssv_noexcept +{ return rhs.compare( lhs ) >= 0; } + +template< class CharT, class Traits> +nssv_constexpr bool operator<=( + basic_string_view lhs, + std::basic_string rhs ) nssv_noexcept +{ return lhs.compare( rhs ) <= 0; } + +template< class CharT, class Traits> +nssv_constexpr bool operator<=( + std::basic_string rhs, + basic_string_view lhs ) nssv_noexcept +{ return rhs.compare( lhs ) >= 0; } + +// > + +template< class CharT, class Traits> +nssv_constexpr bool operator>( + basic_string_view lhs, + CharT const * rhs ) nssv_noexcept +{ return lhs.compare( rhs ) > 0; } + +template< class CharT, class Traits> +nssv_constexpr bool operator>( + CharT const * lhs, + basic_string_view rhs ) nssv_noexcept +{ return rhs.compare( lhs ) < 0; } + +template< class CharT, class Traits> +nssv_constexpr bool operator>( + basic_string_view lhs, + std::basic_string rhs ) nssv_noexcept +{ return lhs.compare( rhs ) > 0; } + +template< class CharT, class Traits> +nssv_constexpr bool operator>( + std::basic_string rhs, + basic_string_view lhs ) nssv_noexcept +{ return rhs.compare( lhs ) < 0; } + +// >= + +template< class CharT, class Traits> +nssv_constexpr bool operator>=( + basic_string_view lhs, + CharT const * rhs ) nssv_noexcept +{ return lhs.compare( rhs ) >= 0; } + +template< class CharT, class Traits> +nssv_constexpr bool operator>=( + CharT const * lhs, + basic_string_view rhs ) nssv_noexcept +{ return rhs.compare( lhs ) <= 0; } + +template< class CharT, class Traits> +nssv_constexpr bool operator>=( + basic_string_view lhs, + std::basic_string rhs ) nssv_noexcept +{ return lhs.compare( rhs ) >= 0; } + +template< class CharT, class Traits> +nssv_constexpr bool operator>=( + std::basic_string rhs, + basic_string_view lhs ) nssv_noexcept +{ return rhs.compare( lhs ) <= 0; } - template - nssv_constexpr bool operator>(nssv_BASIC_STRING_VIEW_I(CharT, Traits) lhs, basic_string_view rhs) nssv_noexcept { - return lhs.compare(rhs) > 0; - } +#else // newer compilers: - // >= +#define nssv_BASIC_STRING_VIEW_I(T,U) typename std::decay< basic_string_view >::type - template - nssv_constexpr bool operator>=(basic_string_view lhs, nssv_BASIC_STRING_VIEW_I(CharT, Traits) rhs) nssv_noexcept { - return lhs.compare(rhs) >= 0; - } +#if defined(_MSC_VER) // issue 40 +# define nssv_MSVC_ORDER(x) , int=x +#else +# define nssv_MSVC_ORDER(x) /*, int=x*/ +#endif - template - nssv_constexpr bool operator>=(nssv_BASIC_STRING_VIEW_I(CharT, Traits) lhs, basic_string_view rhs) nssv_noexcept { - return lhs.compare(rhs) >= 0; - } +// == + +template< class CharT, class Traits nssv_MSVC_ORDER(1) > +nssv_constexpr bool operator==( + basic_string_view lhs, + nssv_BASIC_STRING_VIEW_I(CharT, Traits) rhs ) nssv_noexcept +{ return lhs.size() == rhs.size() && lhs.compare( rhs ) == 0; } + +template< class CharT, class Traits nssv_MSVC_ORDER(2) > +nssv_constexpr bool operator==( + nssv_BASIC_STRING_VIEW_I(CharT, Traits) lhs, + basic_string_view rhs ) nssv_noexcept +{ return lhs.size() == rhs.size() && lhs.compare( rhs ) == 0; } + +// != + +template< class CharT, class Traits nssv_MSVC_ORDER(1) > +nssv_constexpr bool operator!= ( + basic_string_view < CharT, Traits > lhs, + nssv_BASIC_STRING_VIEW_I( CharT, Traits ) rhs ) nssv_noexcept +{ return !( lhs == rhs ); } + +template< class CharT, class Traits nssv_MSVC_ORDER(2) > +nssv_constexpr bool operator!= ( + nssv_BASIC_STRING_VIEW_I( CharT, Traits ) lhs, + basic_string_view < CharT, Traits > rhs ) nssv_noexcept +{ return !( lhs == rhs ); } + +// < + +template< class CharT, class Traits nssv_MSVC_ORDER(1) > +nssv_constexpr bool operator< ( + basic_string_view < CharT, Traits > lhs, + nssv_BASIC_STRING_VIEW_I( CharT, Traits ) rhs ) nssv_noexcept +{ return lhs.compare( rhs ) < 0; } + +template< class CharT, class Traits nssv_MSVC_ORDER(2) > +nssv_constexpr bool operator< ( + nssv_BASIC_STRING_VIEW_I( CharT, Traits ) lhs, + basic_string_view < CharT, Traits > rhs ) nssv_noexcept +{ return lhs.compare( rhs ) < 0; } + +// <= + +template< class CharT, class Traits nssv_MSVC_ORDER(1) > +nssv_constexpr bool operator<= ( + basic_string_view < CharT, Traits > lhs, + nssv_BASIC_STRING_VIEW_I( CharT, Traits ) rhs ) nssv_noexcept +{ return lhs.compare( rhs ) <= 0; } + +template< class CharT, class Traits nssv_MSVC_ORDER(2) > +nssv_constexpr bool operator<= ( + nssv_BASIC_STRING_VIEW_I( CharT, Traits ) lhs, + basic_string_view < CharT, Traits > rhs ) nssv_noexcept +{ return lhs.compare( rhs ) <= 0; } + +// > + +template< class CharT, class Traits nssv_MSVC_ORDER(1) > +nssv_constexpr bool operator> ( + basic_string_view < CharT, Traits > lhs, + nssv_BASIC_STRING_VIEW_I( CharT, Traits ) rhs ) nssv_noexcept +{ return lhs.compare( rhs ) > 0; } + +template< class CharT, class Traits nssv_MSVC_ORDER(2) > +nssv_constexpr bool operator> ( + nssv_BASIC_STRING_VIEW_I( CharT, Traits ) lhs, + basic_string_view < CharT, Traits > rhs ) nssv_noexcept +{ return lhs.compare( rhs ) > 0; } + +// >= + +template< class CharT, class Traits nssv_MSVC_ORDER(1) > +nssv_constexpr bool operator>= ( + basic_string_view < CharT, Traits > lhs, + nssv_BASIC_STRING_VIEW_I( CharT, Traits ) rhs ) nssv_noexcept +{ return lhs.compare( rhs ) >= 0; } + +template< class CharT, class Traits nssv_MSVC_ORDER(2) > +nssv_constexpr bool operator>= ( + nssv_BASIC_STRING_VIEW_I( CharT, Traits ) lhs, + basic_string_view < CharT, Traits > rhs ) nssv_noexcept +{ return lhs.compare( rhs ) >= 0; } #undef nssv_MSVC_ORDER #undef nssv_BASIC_STRING_VIEW_I #endif // compiler-dependent approach to comparisons - // 24.4.4 Inserters and extractors: +// 24.4.4 Inserters and extractors: -#if !nssv_CONFIG_NO_STREAM_INSERTION +#if ! nssv_CONFIG_NO_STREAM_INSERTION - namespace detail { +namespace detail { - template void write_padding(Stream& os, std::streamsize n) { - for(std::streamsize i = 0; i < n; ++i) - os.rdbuf()->sputc(os.fill()); - } +template< class Stream > +void write_padding( Stream & os, std::streamsize n ) +{ + for ( std::streamsize i = 0; i < n; ++i ) + os.rdbuf()->sputc( os.fill() ); +} - template Stream& write_to_stream(Stream& os, View const& sv) { - typename Stream::sentry sentry(os); +template< class Stream, class View > +Stream & write_to_stream( Stream & os, View const & sv ) +{ + typename Stream::sentry sentry( os ); - if(!sentry) - return os; + if ( !sentry ) + return os; - const std::streamsize length = static_cast(sv.length()); + const std::streamsize length = static_cast( sv.length() ); - // Whether, and how, to pad: - const bool pad = (length < os.width()); - const bool left_pad = pad && (os.flags() & std::ios_base::adjustfield) == std::ios_base::right; + // Whether, and how, to pad: + const bool pad = ( length < os.width() ); + const bool left_pad = pad && ( os.flags() & std::ios_base::adjustfield ) == std::ios_base::right; - if(left_pad) - write_padding(os, os.width() - length); + if ( left_pad ) + write_padding( os, os.width() - length ); - // Write span characters: - os.rdbuf()->sputn(sv.begin(), length); + // Write span characters: + os.rdbuf()->sputn( sv.begin(), length ); - if(pad && !left_pad) - write_padding(os, os.width() - length); + if ( pad && !left_pad ) + write_padding( os, os.width() - length ); - // Reset output stream width: - os.width(0); + // Reset output stream width: + os.width( 0 ); - return os; - } + return os; +} - } // namespace detail +} // namespace detail - template - std::basic_ostream& operator<<(std::basic_ostream& os, basic_string_view sv) { - return detail::write_to_stream(os, sv); - } +template< class CharT, class Traits > +std::basic_ostream & +operator<<( + std::basic_ostream& os, + basic_string_view sv ) +{ + return detail::write_to_stream( os, sv ); +} #endif // nssv_CONFIG_NO_STREAM_INSERTION - // Several typedefs for common character types are provided: +// Several typedefs for common character types are provided: - typedef basic_string_view string_view; - typedef basic_string_view wstring_view; +typedef basic_string_view string_view; +typedef basic_string_view wstring_view; #if nssv_HAVE_WCHAR16_T - typedef basic_string_view u16string_view; - typedef basic_string_view u32string_view; +typedef basic_string_view u16string_view; +typedef basic_string_view u32string_view; #endif - } // namespace sv_lite -} // namespace nonstd::sv_lite +}} // namespace nonstd::sv_lite // // 24.4.6 Suffix for basic_string_view literals: @@ -1362,58 +1508,57 @@ nssv_DISABLE_MSVC_WARNINGS(4455 26481 26472) namespace nonstd { nssv_inline_ns namespace literals { - nssv_inline_ns namespace string_view_literals { +nssv_inline_ns namespace string_view_literals { #if nssv_CONFIG_STD_SV_OPERATOR && nssv_HAVE_STD_DEFINED_LITERALS - nssv_constexpr nonstd::sv_lite::string_view operator"" sv(const char* str, size_t len) nssv_noexcept // (1) - { - return nonstd::sv_lite::string_view{str, len}; - } +nssv_constexpr nonstd::sv_lite::string_view operator""sv( const char* str, size_t len ) nssv_noexcept // (1) +{ + return nonstd::sv_lite::string_view{ str, len }; +} - nssv_constexpr nonstd::sv_lite::u16string_view operator"" sv(const char16_t* str, size_t len) nssv_noexcept // (2) - { - return nonstd::sv_lite::u16string_view{str, len}; - } +nssv_constexpr nonstd::sv_lite::u16string_view operator""sv( const char16_t* str, size_t len ) nssv_noexcept // (2) +{ + return nonstd::sv_lite::u16string_view{ str, len }; +} - nssv_constexpr nonstd::sv_lite::u32string_view operator"" sv(const char32_t* str, size_t len) nssv_noexcept // (3) - { - return nonstd::sv_lite::u32string_view{str, len}; - } +nssv_constexpr nonstd::sv_lite::u32string_view operator""sv( const char32_t* str, size_t len ) nssv_noexcept // (3) +{ + return nonstd::sv_lite::u32string_view{ str, len }; +} - nssv_constexpr nonstd::sv_lite::wstring_view operator"" sv(const wchar_t* str, size_t len) nssv_noexcept // (4) - { - return nonstd::sv_lite::wstring_view{str, len}; - } +nssv_constexpr nonstd::sv_lite::wstring_view operator""sv( const wchar_t* str, size_t len ) nssv_noexcept // (4) +{ + return nonstd::sv_lite::wstring_view{ str, len }; +} #endif // nssv_CONFIG_STD_SV_OPERATOR && nssv_HAVE_STD_DEFINED_LITERALS #if nssv_CONFIG_USR_SV_OPERATOR - nssv_constexpr nonstd::sv_lite::string_view operator"" _sv(const char* str, size_t len) nssv_noexcept // (1) - { - return nonstd::sv_lite::string_view{str, len}; - } +nssv_constexpr nonstd::sv_lite::string_view operator""_sv( const char* str, size_t len ) nssv_noexcept // (1) +{ + return nonstd::sv_lite::string_view{ str, len }; +} - nssv_constexpr nonstd::sv_lite::u16string_view operator"" _sv(const char16_t* str, size_t len) nssv_noexcept // (2) - { - return nonstd::sv_lite::u16string_view{str, len}; - } +nssv_constexpr nonstd::sv_lite::u16string_view operator""_sv( const char16_t* str, size_t len ) nssv_noexcept // (2) +{ + return nonstd::sv_lite::u16string_view{ str, len }; +} - nssv_constexpr nonstd::sv_lite::u32string_view operator"" _sv(const char32_t* str, size_t len) nssv_noexcept // (3) - { - return nonstd::sv_lite::u32string_view{str, len}; - } +nssv_constexpr nonstd::sv_lite::u32string_view operator""_sv( const char32_t* str, size_t len ) nssv_noexcept // (3) +{ + return nonstd::sv_lite::u32string_view{ str, len }; +} - nssv_constexpr nonstd::sv_lite::wstring_view operator"" _sv(const wchar_t* str, size_t len) nssv_noexcept // (4) - { - return nonstd::sv_lite::wstring_view{str, len}; - } +nssv_constexpr nonstd::sv_lite::wstring_view operator""_sv( const wchar_t* str, size_t len ) nssv_noexcept // (4) +{ + return nonstd::sv_lite::wstring_view{ str, len }; +} #endif // nssv_CONFIG_USR_SV_OPERATOR - } -} -} // namespace nonstd + +}}} // namespace nonstd::literals::string_view_literals #endif @@ -1430,31 +1575,39 @@ namespace sv_lite { #if nssv_CPP11_OR_GREATER && nssv_COMPILER_MSVC_VERSION != 140 -template > -std::basic_string to_string(basic_string_view v, Allocator const& a = Allocator()) { - return std::basic_string(v.begin(), v.end(), a); +template< class CharT, class Traits, class Allocator = std::allocator > +std::basic_string +to_string( basic_string_view v, Allocator const & a = Allocator() ) +{ + return std::basic_string( v.begin(), v.end(), a ); } #else -template std::basic_string to_string(basic_string_view v) { - return std::basic_string(v.begin(), v.end()); +template< class CharT, class Traits > +std::basic_string +to_string( basic_string_view v ) +{ + return std::basic_string( v.begin(), v.end() ); } -template -std::basic_string to_string(basic_string_view v, Allocator const& a) { - return std::basic_string(v.begin(), v.end(), a); +template< class CharT, class Traits, class Allocator > +std::basic_string +to_string( basic_string_view v, Allocator const & a ) +{ + return std::basic_string( v.begin(), v.end(), a ); } #endif // nssv_CPP11_OR_GREATER -template -basic_string_view to_string_view(std::basic_string const& s) { - return basic_string_view(s.data(), s.size()); +template< class CharT, class Traits, class Allocator > +basic_string_view +to_string_view( std::basic_string const & s ) +{ + return basic_string_view( s.data(), s.size() ); } -} // namespace sv_lite -} // namespace nonstd +}} // namespace nonstd::sv_lite #endif // nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS @@ -1484,7 +1637,7 @@ using sv_lite::operator<=; using sv_lite::operator>; using sv_lite::operator>=; -#if !nssv_CONFIG_NO_STREAM_INSERTION +#if ! nssv_CONFIG_NO_STREAM_INSERTION using sv_lite::operator<<; #endif @@ -1506,29 +1659,43 @@ using sv_lite::to_string_view; namespace std { -template <> struct hash { +template<> +struct hash< nonstd::string_view > +{ public: - std::size_t operator()(nonstd::string_view v) const nssv_noexcept { return std::hash()(std::string(v.data(), v.size())); } + std::size_t operator()( nonstd::string_view v ) const nssv_noexcept + { + return std::hash()( std::string( v.data(), v.size() ) ); + } }; -template <> struct hash { +template<> +struct hash< nonstd::wstring_view > +{ public: - std::size_t operator()(nonstd::wstring_view v) const nssv_noexcept { - return std::hash()(std::wstring(v.data(), v.size())); + std::size_t operator()( nonstd::wstring_view v ) const nssv_noexcept + { + return std::hash()( std::wstring( v.data(), v.size() ) ); } }; -template <> struct hash { +template<> +struct hash< nonstd::u16string_view > +{ public: - std::size_t operator()(nonstd::u16string_view v) const nssv_noexcept { - return std::hash()(std::u16string(v.data(), v.size())); + std::size_t operator()( nonstd::u16string_view v ) const nssv_noexcept + { + return std::hash()( std::u16string( v.data(), v.size() ) ); } }; -template <> struct hash { +template<> +struct hash< nonstd::u32string_view > +{ public: - std::size_t operator()(nonstd::u32string_view v) const nssv_noexcept { - return std::hash()(std::u32string(v.data(), v.size())); + std::size_t operator()( nonstd::u32string_view v ) const nssv_noexcept + { + return std::hash()( std::u32string( v.data(), v.size() ) ); } }; @@ -1540,3 +1707,4 @@ nssv_RESTORE_WARNINGS() #endif // nssv_HAVE_STD_STRING_VIEW #endif // NONSTD_SV_LITE_H_INCLUDED + From 70f6c1d3bf44cbf3e771e9c3d60c3e2fe243b5f3 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Fri, 13 Mar 2026 14:04:08 -0700 Subject: [PATCH 4/5] applies clang-format --- src/common/nonstd/string_view.hpp | 1938 +++++++++++++---------------- third_party/scp4scc/scp/report.h | 10 +- 2 files changed, 901 insertions(+), 1047 deletions(-) diff --git a/src/common/nonstd/string_view.hpp b/src/common/nonstd/string_view.hpp index b5ccb6a2a..a2970f410 100644 --- a/src/common/nonstd/string_view.hpp +++ b/src/common/nonstd/string_view.hpp @@ -11,116 +11,119 @@ #ifndef NONSTD_SV_LITE_H_INCLUDED #define NONSTD_SV_LITE_H_INCLUDED -#define string_view_lite_MAJOR 1 -#define string_view_lite_MINOR 8 -#define string_view_lite_PATCH 0 +#define string_view_lite_MAJOR 1 +#define string_view_lite_MINOR 8 +#define string_view_lite_PATCH 0 -#define string_view_lite_VERSION nssv_STRINGIFY(string_view_lite_MAJOR) "." nssv_STRINGIFY(string_view_lite_MINOR) "." nssv_STRINGIFY(string_view_lite_PATCH) +#define string_view_lite_VERSION \ + nssv_STRINGIFY(string_view_lite_MAJOR) "." nssv_STRINGIFY(string_view_lite_MINOR) "." nssv_STRINGIFY(string_view_lite_PATCH) -#define nssv_STRINGIFY( x ) nssv_STRINGIFY_( x ) -#define nssv_STRINGIFY_( x ) #x +#define nssv_STRINGIFY(x) nssv_STRINGIFY_(x) +#define nssv_STRINGIFY_(x) #x // string-view lite configuration: -#define nssv_STRING_VIEW_DEFAULT 0 -#define nssv_STRING_VIEW_NONSTD 1 -#define nssv_STRING_VIEW_STD 2 +#define nssv_STRING_VIEW_DEFAULT 0 +#define nssv_STRING_VIEW_NONSTD 1 +#define nssv_STRING_VIEW_STD 2 // tweak header support: #ifdef __has_include -# if __has_include() -# include -# endif -#define nssv_HAVE_TWEAK_HEADER 1 +#if __has_include() +#include +#endif +#define nssv_HAVE_TWEAK_HEADER 1 #else -#define nssv_HAVE_TWEAK_HEADER 0 +#define nssv_HAVE_TWEAK_HEADER 0 //# pragma message("string_view.hpp: Note: Tweak header not supported.") #endif // string_view selection and configuration: -#if !defined( nssv_CONFIG_SELECT_STRING_VIEW ) -# define nssv_CONFIG_SELECT_STRING_VIEW ( nssv_HAVE_STD_STRING_VIEW ? nssv_STRING_VIEW_STD : nssv_STRING_VIEW_NONSTD ) +#if !defined(nssv_CONFIG_SELECT_STRING_VIEW) +#define nssv_CONFIG_SELECT_STRING_VIEW (nssv_HAVE_STD_STRING_VIEW ? nssv_STRING_VIEW_STD : nssv_STRING_VIEW_NONSTD) #endif -#ifndef nssv_CONFIG_STD_SV_OPERATOR -# define nssv_CONFIG_STD_SV_OPERATOR 0 +#ifndef nssv_CONFIG_STD_SV_OPERATOR +#define nssv_CONFIG_STD_SV_OPERATOR 0 #endif -#ifndef nssv_CONFIG_USR_SV_OPERATOR -# define nssv_CONFIG_USR_SV_OPERATOR 1 +#ifndef nssv_CONFIG_USR_SV_OPERATOR +#define nssv_CONFIG_USR_SV_OPERATOR 1 #endif -#ifdef nssv_CONFIG_CONVERSION_STD_STRING -# define nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS nssv_CONFIG_CONVERSION_STD_STRING -# define nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS nssv_CONFIG_CONVERSION_STD_STRING +#ifdef nssv_CONFIG_CONVERSION_STD_STRING +#define nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS nssv_CONFIG_CONVERSION_STD_STRING +#define nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS nssv_CONFIG_CONVERSION_STD_STRING #endif -#ifndef nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS -# define nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS 1 +#ifndef nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS +#define nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS 1 #endif -#ifndef nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS -# define nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS 1 +#ifndef nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS +#define nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS 1 #endif -#ifndef nssv_CONFIG_NO_STREAM_INSERTION -# define nssv_CONFIG_NO_STREAM_INSERTION 0 +#ifndef nssv_CONFIG_NO_STREAM_INSERTION +#define nssv_CONFIG_NO_STREAM_INSERTION 0 #endif -#ifndef nssv_CONFIG_CONSTEXPR11_STD_SEARCH -# define nssv_CONFIG_CONSTEXPR11_STD_SEARCH 1 +#ifndef nssv_CONFIG_CONSTEXPR11_STD_SEARCH +#define nssv_CONFIG_CONSTEXPR11_STD_SEARCH 1 #endif // Control presence of exception handling (try and auto discover): #ifndef nssv_CONFIG_NO_EXCEPTIONS -# if defined(_MSC_VER) -# include // for _HAS_EXCEPTIONS -# endif -# if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || (_HAS_EXCEPTIONS) -# define nssv_CONFIG_NO_EXCEPTIONS 0 -# else -# define nssv_CONFIG_NO_EXCEPTIONS 1 -# endif +#if defined(_MSC_VER) +#include // for _HAS_EXCEPTIONS +#endif +#if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || (_HAS_EXCEPTIONS) +#define nssv_CONFIG_NO_EXCEPTIONS 0 +#else +#define nssv_CONFIG_NO_EXCEPTIONS 1 +#endif #endif // C++ language version detection (C++23 is speculative): // Note: VC14.0/1900 (VS2015) lacks too much from C++14. -#ifndef nssv_CPLUSPLUS -# if defined(_MSVC_LANG ) && !defined(__clang__) -# define nssv_CPLUSPLUS (_MSC_VER == 1900 ? 201103L : _MSVC_LANG ) -# else -# define nssv_CPLUSPLUS __cplusplus -# endif +#ifndef nssv_CPLUSPLUS +#if defined(_MSVC_LANG) && !defined(__clang__) +#define nssv_CPLUSPLUS (_MSC_VER == 1900 ? 201103L : _MSVC_LANG) +#else +#define nssv_CPLUSPLUS __cplusplus +#endif #endif -#define nssv_CPP98_OR_GREATER ( nssv_CPLUSPLUS >= 199711L ) -#define nssv_CPP11_OR_GREATER ( nssv_CPLUSPLUS >= 201103L ) -#define nssv_CPP11_OR_GREATER_ ( nssv_CPLUSPLUS >= 201103L ) -#define nssv_CPP14_OR_GREATER ( nssv_CPLUSPLUS >= 201402L ) -#define nssv_CPP17_OR_GREATER ( nssv_CPLUSPLUS >= 201703L ) -#define nssv_CPP20_OR_GREATER ( nssv_CPLUSPLUS >= 202002L ) -#define nssv_CPP23_OR_GREATER ( nssv_CPLUSPLUS >= 202300L ) +#define nssv_CPP98_OR_GREATER (nssv_CPLUSPLUS >= 199711L) +#define nssv_CPP11_OR_GREATER (nssv_CPLUSPLUS >= 201103L) +#define nssv_CPP11_OR_GREATER_ (nssv_CPLUSPLUS >= 201103L) +#define nssv_CPP14_OR_GREATER (nssv_CPLUSPLUS >= 201402L) +#define nssv_CPP17_OR_GREATER (nssv_CPLUSPLUS >= 201703L) +#define nssv_CPP20_OR_GREATER (nssv_CPLUSPLUS >= 202002L) +#define nssv_CPP23_OR_GREATER (nssv_CPLUSPLUS >= 202300L) // use C++17 std::string_view if available and requested: -#if nssv_CPP17_OR_GREATER && defined(__has_include ) -# if __has_include( ) -# define nssv_HAVE_STD_STRING_VIEW 1 -# else -# define nssv_HAVE_STD_STRING_VIEW 0 -# endif +#if nssv_CPP17_OR_GREATER && defined(__has_include) +#if __has_include( ) +#define nssv_HAVE_STD_STRING_VIEW 1 #else -# define nssv_HAVE_STD_STRING_VIEW 0 +#define nssv_HAVE_STD_STRING_VIEW 0 +#endif +#else +#define nssv_HAVE_STD_STRING_VIEW 0 #endif -#define nssv_USES_STD_STRING_VIEW ( (nssv_CONFIG_SELECT_STRING_VIEW == nssv_STRING_VIEW_STD) || ((nssv_CONFIG_SELECT_STRING_VIEW == nssv_STRING_VIEW_DEFAULT) && nssv_HAVE_STD_STRING_VIEW) ) +#define nssv_USES_STD_STRING_VIEW \ + ((nssv_CONFIG_SELECT_STRING_VIEW == nssv_STRING_VIEW_STD) || \ + ((nssv_CONFIG_SELECT_STRING_VIEW == nssv_STRING_VIEW_DEFAULT) && nssv_HAVE_STD_STRING_VIEW)) -#define nssv_HAVE_STARTS_WITH ( nssv_CPP20_OR_GREATER || !nssv_USES_STD_STRING_VIEW ) -#define nssv_HAVE_ENDS_WITH nssv_HAVE_STARTS_WITH +#define nssv_HAVE_STARTS_WITH (nssv_CPP20_OR_GREATER || !nssv_USES_STD_STRING_VIEW) +#define nssv_HAVE_ENDS_WITH nssv_HAVE_STARTS_WITH // // Use C++17 std::string_view: @@ -138,18 +141,14 @@ namespace nonstd { -template< class CharT, class Traits, class Allocator = std::allocator > -std::basic_string -to_string( std::basic_string_view v, Allocator const & a = Allocator() ) -{ - return std::basic_string( v.begin(), v.end(), a ); +template > +std::basic_string to_string(std::basic_string_view v, Allocator const& a = Allocator()) { + return std::basic_string(v.begin(), v.end(), a); } -template< class CharT, class Traits, class Allocator > -std::basic_string_view -to_string_view( std::basic_string const & s ) -{ - return std::basic_string_view( s.data(), s.size() ); +template +std::basic_string_view to_string_view(std::basic_string const& s) { + return std::basic_string_view(s.data(), s.size()); } // Literal operators sv and _sv: @@ -165,28 +164,28 @@ using namespace std::literals::string_view_literals; inline namespace literals { inline namespace string_view_literals { - -constexpr std::string_view operator""_sv( const char* str, size_t len ) noexcept // (1) +constexpr std::string_view operator""_sv(const char* str, size_t len) noexcept // (1) { - return std::string_view{ str, len }; + return std::string_view{str, len}; } -constexpr std::u16string_view operator""_sv( const char16_t* str, size_t len ) noexcept // (2) +constexpr std::u16string_view operator""_sv(const char16_t* str, size_t len) noexcept // (2) { - return std::u16string_view{ str, len }; + return std::u16string_view{str, len}; } -constexpr std::u32string_view operator""_sv( const char32_t* str, size_t len ) noexcept // (3) +constexpr std::u32string_view operator""_sv(const char32_t* str, size_t len) noexcept // (3) { - return std::u32string_view{ str, len }; + return std::u32string_view{str, len}; } -constexpr std::wstring_view operator""_sv( const wchar_t* str, size_t len ) noexcept // (4) +constexpr std::wstring_view operator""_sv(const wchar_t* str, size_t len) noexcept // (4) { - return std::wstring_view{ str, len }; + return std::wstring_view{str, len}; } -}} // namespace literals::string_view_literals +} // namespace string_view_literals +} // namespace literals #endif // nssv_CONFIG_USR_SV_OPERATOR @@ -196,11 +195,11 @@ constexpr std::wstring_view operator""_sv( const wchar_t* str, size_t len ) noex namespace nonstd { +using std::basic_string_view; using std::string_view; -using std::wstring_view; using std::u16string_view; using std::u32string_view; -using std::basic_string_view; +using std::wstring_view; // literal "sv" and "_sv", see above @@ -235,93 +234,93 @@ using std::operator<<; // MSVC++ 14.1 _MSC_VER >= 1910 nssv_COMPILER_MSVC_VERSION == 141 (Visual Studio 2017) // MSVC++ 14.2 _MSC_VER >= 1920 nssv_COMPILER_MSVC_VERSION == 142 (Visual Studio 2019) -#if defined(_MSC_VER ) && !defined(__clang__) -# define nssv_COMPILER_MSVC_VER (_MSC_VER ) -# define nssv_COMPILER_MSVC_VERSION (_MSC_VER / 10 - 10 * ( 5 + (_MSC_VER < 1900 ) ) ) +#if defined(_MSC_VER) && !defined(__clang__) +#define nssv_COMPILER_MSVC_VER (_MSC_VER) +#define nssv_COMPILER_MSVC_VERSION (_MSC_VER / 10 - 10 * (5 + (_MSC_VER < 1900))) #else -# define nssv_COMPILER_MSVC_VER 0 -# define nssv_COMPILER_MSVC_VERSION 0 +#define nssv_COMPILER_MSVC_VER 0 +#define nssv_COMPILER_MSVC_VERSION 0 #endif -#define nssv_COMPILER_VERSION( major, minor, patch ) ( 10 * ( 10 * (major) + (minor) ) + (patch) ) +#define nssv_COMPILER_VERSION(major, minor, patch) (10 * (10 * (major) + (minor)) + (patch)) -#if defined( __apple_build_version__ ) -# define nssv_COMPILER_APPLECLANG_VERSION nssv_COMPILER_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__) -# define nssv_COMPILER_CLANG_VERSION 0 -#elif defined( __clang__ ) -# define nssv_COMPILER_APPLECLANG_VERSION 0 -# define nssv_COMPILER_CLANG_VERSION nssv_COMPILER_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__) +#if defined(__apple_build_version__) +#define nssv_COMPILER_APPLECLANG_VERSION nssv_COMPILER_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__) +#define nssv_COMPILER_CLANG_VERSION 0 +#elif defined(__clang__) +#define nssv_COMPILER_APPLECLANG_VERSION 0 +#define nssv_COMPILER_CLANG_VERSION nssv_COMPILER_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__) #else -# define nssv_COMPILER_APPLECLANG_VERSION 0 -# define nssv_COMPILER_CLANG_VERSION 0 +#define nssv_COMPILER_APPLECLANG_VERSION 0 +#define nssv_COMPILER_CLANG_VERSION 0 #endif #if defined(__GNUC__) && !defined(__clang__) -# define nssv_COMPILER_GNUC_VERSION nssv_COMPILER_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) +#define nssv_COMPILER_GNUC_VERSION nssv_COMPILER_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) #else -# define nssv_COMPILER_GNUC_VERSION 0 +#define nssv_COMPILER_GNUC_VERSION 0 #endif // half-open range [lo..hi): -#define nssv_BETWEEN( v, lo, hi ) ( (lo) <= (v) && (v) < (hi) ) +#define nssv_BETWEEN(v, lo, hi) ((lo) <= (v) && (v) < (hi)) // Presence of language and library features: #ifdef _HAS_CPP0X -# define nssv_HAS_CPP0X _HAS_CPP0X +#define nssv_HAS_CPP0X _HAS_CPP0X #else -# define nssv_HAS_CPP0X 0 +#define nssv_HAS_CPP0X 0 #endif // Unless defined otherwise below, consider VC14 as C++11 for string-view-lite: #if nssv_COMPILER_MSVC_VER >= 1900 -# undef nssv_CPP11_OR_GREATER -# define nssv_CPP11_OR_GREATER 1 +#undef nssv_CPP11_OR_GREATER +#define nssv_CPP11_OR_GREATER 1 #endif -#define nssv_CPP11_90 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1500) -#define nssv_CPP11_100 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1600) -#define nssv_CPP11_110 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1700) -#define nssv_CPP11_120 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1800) -#define nssv_CPP11_140 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1900) -#define nssv_CPP11_141 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1910) +#define nssv_CPP11_90 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1500) +#define nssv_CPP11_100 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1600) +#define nssv_CPP11_110 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1700) +#define nssv_CPP11_120 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1800) +#define nssv_CPP11_140 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1900) +#define nssv_CPP11_141 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1910) -#define nssv_CPP14_000 (nssv_CPP14_OR_GREATER) -#define nssv_CPP17_000 (nssv_CPP17_OR_GREATER) +#define nssv_CPP14_000 (nssv_CPP14_OR_GREATER) +#define nssv_CPP17_000 (nssv_CPP17_OR_GREATER) // Presence of C++11 language features: -#define nssv_HAVE_CONSTEXPR_11 nssv_CPP11_140 -#define nssv_HAVE_EXPLICIT_CONVERSION nssv_CPP11_140 -#define nssv_HAVE_INLINE_NAMESPACE nssv_CPP11_140 -#define nssv_HAVE_IS_DEFAULT nssv_CPP11_140 -#define nssv_HAVE_IS_DELETE nssv_CPP11_140 -#define nssv_HAVE_NOEXCEPT nssv_CPP11_140 -#define nssv_HAVE_NULLPTR nssv_CPP11_100 -#define nssv_HAVE_REF_QUALIFIER nssv_CPP11_140 -#define nssv_HAVE_UNICODE_LITERALS nssv_CPP11_140 +#define nssv_HAVE_CONSTEXPR_11 nssv_CPP11_140 +#define nssv_HAVE_EXPLICIT_CONVERSION nssv_CPP11_140 +#define nssv_HAVE_INLINE_NAMESPACE nssv_CPP11_140 +#define nssv_HAVE_IS_DEFAULT nssv_CPP11_140 +#define nssv_HAVE_IS_DELETE nssv_CPP11_140 +#define nssv_HAVE_NOEXCEPT nssv_CPP11_140 +#define nssv_HAVE_NULLPTR nssv_CPP11_100 +#define nssv_HAVE_REF_QUALIFIER nssv_CPP11_140 +#define nssv_HAVE_UNICODE_LITERALS nssv_CPP11_140 #define nssv_HAVE_USER_DEFINED_LITERALS nssv_CPP11_140 -#define nssv_HAVE_WCHAR16_T nssv_CPP11_100 -#define nssv_HAVE_WCHAR32_T nssv_CPP11_100 +#define nssv_HAVE_WCHAR16_T nssv_CPP11_100 +#define nssv_HAVE_WCHAR32_T nssv_CPP11_100 -#if ! ( ( nssv_CPP11_OR_GREATER && nssv_COMPILER_CLANG_VERSION ) || nssv_BETWEEN( nssv_COMPILER_CLANG_VERSION, 300, 400 ) ) -# define nssv_HAVE_STD_DEFINED_LITERALS nssv_CPP11_140 +#if !((nssv_CPP11_OR_GREATER && nssv_COMPILER_CLANG_VERSION) || nssv_BETWEEN(nssv_COMPILER_CLANG_VERSION, 300, 400)) +#define nssv_HAVE_STD_DEFINED_LITERALS nssv_CPP11_140 #else -# define nssv_HAVE_STD_DEFINED_LITERALS 0 +#define nssv_HAVE_STD_DEFINED_LITERALS 0 #endif // Presence of C++14 language features: -#define nssv_HAVE_CONSTEXPR_14 nssv_CPP14_000 +#define nssv_HAVE_CONSTEXPR_14 nssv_CPP14_000 // Presence of C++17 language features: -#define nssv_HAVE_NODISCARD nssv_CPP17_000 +#define nssv_HAVE_NODISCARD nssv_CPP17_000 // Presence of C++ library features: -#define nssv_HAVE_STD_HASH nssv_CPP11_120 +#define nssv_HAVE_STD_HASH nssv_CPP11_120 // Presence of compiler intrinsics: @@ -338,60 +337,62 @@ using std::operator<<; // | gcc | any (constexpr) | any (? ) | // | msvc | >= 14.2 C++17 (>= 14.2 ) | any (? ) | -#define nssv_HAVE_BUILTIN_VER ( (nssv_CPP17_000 && nssv_COMPILER_MSVC_VERSION >= 142) || nssv_COMPILER_GNUC_VERSION > 0 || nssv_COMPILER_CLANG_VERSION >= 400 || nssv_COMPILER_APPLECLANG_VERSION >= 900 ) -#define nssv_HAVE_BUILTIN_CE ( nssv_HAVE_BUILTIN_VER ) +#define nssv_HAVE_BUILTIN_VER \ + ((nssv_CPP17_000 && nssv_COMPILER_MSVC_VERSION >= 142) || nssv_COMPILER_GNUC_VERSION > 0 || nssv_COMPILER_CLANG_VERSION >= 400 || \ + nssv_COMPILER_APPLECLANG_VERSION >= 900) +#define nssv_HAVE_BUILTIN_CE (nssv_HAVE_BUILTIN_VER) -#define nssv_HAVE_BUILTIN_MEMCMP ( (nssv_HAVE_CONSTEXPR_14 && nssv_HAVE_BUILTIN_CE) || !nssv_HAVE_CONSTEXPR_14 ) -#define nssv_HAVE_BUILTIN_STRLEN ( (nssv_HAVE_CONSTEXPR_11 && nssv_HAVE_BUILTIN_CE) || !nssv_HAVE_CONSTEXPR_11 ) +#define nssv_HAVE_BUILTIN_MEMCMP ((nssv_HAVE_CONSTEXPR_14 && nssv_HAVE_BUILTIN_CE) || !nssv_HAVE_CONSTEXPR_14) +#define nssv_HAVE_BUILTIN_STRLEN ((nssv_HAVE_CONSTEXPR_11 && nssv_HAVE_BUILTIN_CE) || !nssv_HAVE_CONSTEXPR_11) #ifdef __has_builtin -# define nssv_HAVE_BUILTIN( x ) __has_builtin( x ) +#define nssv_HAVE_BUILTIN(x) __has_builtin(x) #else -# define nssv_HAVE_BUILTIN( x ) 0 +#define nssv_HAVE_BUILTIN(x) 0 #endif #if nssv_HAVE_BUILTIN(__builtin_memcmp) || nssv_HAVE_BUILTIN_VER -# define nssv_BUILTIN_MEMCMP __builtin_memcmp +#define nssv_BUILTIN_MEMCMP __builtin_memcmp #else -# define nssv_BUILTIN_MEMCMP memcmp +#define nssv_BUILTIN_MEMCMP memcmp #endif #if nssv_HAVE_BUILTIN(__builtin_strlen) || nssv_HAVE_BUILTIN_VER -# define nssv_BUILTIN_STRLEN __builtin_strlen +#define nssv_BUILTIN_STRLEN __builtin_strlen #else -# define nssv_BUILTIN_STRLEN strlen +#define nssv_BUILTIN_STRLEN strlen #endif // C++ feature usage: #if nssv_HAVE_CONSTEXPR_11 -# define nssv_constexpr constexpr +#define nssv_constexpr constexpr #else -# define nssv_constexpr /*constexpr*/ +#define nssv_constexpr /*constexpr*/ #endif -#if nssv_HAVE_CONSTEXPR_14 -# define nssv_constexpr14 constexpr +#if nssv_HAVE_CONSTEXPR_14 +#define nssv_constexpr14 constexpr #else -# define nssv_constexpr14 /*constexpr*/ +#define nssv_constexpr14 /*constexpr*/ #endif #if nssv_HAVE_EXPLICIT_CONVERSION -# define nssv_explicit explicit +#define nssv_explicit explicit #else -# define nssv_explicit /*explicit*/ +#define nssv_explicit /*explicit*/ #endif #if nssv_HAVE_INLINE_NAMESPACE -# define nssv_inline_ns inline +#define nssv_inline_ns inline #else -# define nssv_inline_ns /*inline*/ +#define nssv_inline_ns /*inline*/ #endif #if nssv_HAVE_NOEXCEPT -# define nssv_noexcept noexcept +#define nssv_noexcept noexcept #else -# define nssv_noexcept /*noexcept*/ +#define nssv_noexcept /*noexcept*/ #endif //#if nssv_HAVE_REF_QUALIFIER @@ -403,15 +404,15 @@ using std::operator<<; //#endif #if nssv_HAVE_NULLPTR -# define nssv_nullptr nullptr +#define nssv_nullptr nullptr #else -# define nssv_nullptr NULL +#define nssv_nullptr NULL #endif #if nssv_HAVE_NODISCARD -# define nssv_nodiscard [[nodiscard]] +#define nssv_nodiscard [[nodiscard]] #else -# define nssv_nodiscard /*[[nodiscard]]*/ +#define nssv_nodiscard /*[[nodiscard]]*/ #endif // Additional includes: @@ -420,49 +421,49 @@ using std::operator<<; #include #include #include -#include // std::char_traits<> +#include // std::char_traits<> -#if ! nssv_CONFIG_NO_STREAM_INSERTION -# include +#if !nssv_CONFIG_NO_STREAM_INSERTION +#include #endif -#if ! nssv_CONFIG_NO_EXCEPTIONS -# include +#if !nssv_CONFIG_NO_EXCEPTIONS +#include #endif #if nssv_CPP11_OR_GREATER -# include +#include #endif // Clang, GNUC, MSVC warning suppression macros: #if defined(__clang__) -# pragma clang diagnostic ignored "-Wreserved-user-defined-literal" -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wuser-defined-literals" +#pragma clang diagnostic ignored "-Wreserved-user-defined-literal" +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wuser-defined-literals" #elif nssv_COMPILER_GNUC_VERSION >= 480 -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wliteral-suffix" +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wliteral-suffix" #endif // __clang__ #if nssv_COMPILER_MSVC_VERSION >= 140 -# define nssv_SUPPRESS_MSGSL_WARNING(expr) [[gsl::suppress(expr)]] -# define nssv_SUPPRESS_MSVC_WARNING(code, descr) __pragma(warning(suppress: code) ) -# define nssv_DISABLE_MSVC_WARNINGS(codes) __pragma(warning(push)) __pragma(warning(disable: codes)) +#define nssv_SUPPRESS_MSGSL_WARNING(expr) [[gsl::suppress(expr)]] +#define nssv_SUPPRESS_MSVC_WARNING(code, descr) __pragma(warning(suppress : code)) +#define nssv_DISABLE_MSVC_WARNINGS(codes) __pragma(warning(push)) __pragma(warning(disable : codes)) #else -# define nssv_SUPPRESS_MSGSL_WARNING(expr) -# define nssv_SUPPRESS_MSVC_WARNING(code, descr) -# define nssv_DISABLE_MSVC_WARNINGS(codes) +#define nssv_SUPPRESS_MSGSL_WARNING(expr) +#define nssv_SUPPRESS_MSVC_WARNING(code, descr) +#define nssv_DISABLE_MSVC_WARNINGS(codes) #endif #if defined(__clang__) -# define nssv_RESTORE_WARNINGS() _Pragma("clang diagnostic pop") +#define nssv_RESTORE_WARNINGS() _Pragma("clang diagnostic pop") #elif nssv_COMPILER_GNUC_VERSION >= 480 -# define nssv_RESTORE_WARNINGS() _Pragma("GCC diagnostic pop") +#define nssv_RESTORE_WARNINGS() _Pragma("GCC diagnostic pop") #elif nssv_COMPILER_MSVC_VERSION >= 140 -# define nssv_RESTORE_WARNINGS() __pragma(warning(pop )) +#define nssv_RESTORE_WARNINGS() __pragma(warning(pop)) #else -# define nssv_RESTORE_WARNINGS() +#define nssv_RESTORE_WARNINGS() #endif // Suppress the following MSVC (GSL) warnings: @@ -472,1033 +473,908 @@ using std::operator<<; // use brace initialization, gsl::narrow_cast or gsl::narow // - C26481: gsl::b.1 : don't use pointer arithmetic. Use span instead -nssv_DISABLE_MSVC_WARNINGS( 4455 26481 26472 ) -//nssv_DISABLE_CLANG_WARNINGS( "-Wuser-defined-literals" ) -//nssv_DISABLE_GNUC_WARNINGS( -Wliteral-suffix ) +nssv_DISABLE_MSVC_WARNINGS(4455 26481 26472) + // nssv_DISABLE_CLANG_WARNINGS( "-Wuser-defined-literals" ) + // nssv_DISABLE_GNUC_WARNINGS( -Wliteral-suffix ) -namespace nonstd { namespace sv_lite { + namespace nonstd { + namespace sv_lite { -// -// basic_string_view declaration: -// + // + // basic_string_view declaration: + // -template -< - class CharT, - class Traits = std::char_traits -> -class basic_string_view; + template > class basic_string_view; -namespace detail { + namespace detail { -// support constexpr comparison in C++14; -// for C++17 and later, use provided traits: + // support constexpr comparison in C++14; + // for C++17 and later, use provided traits: -template< typename CharT > -inline nssv_constexpr14 int compare( CharT const * s1, CharT const * s2, std::size_t count ) -{ - while ( count-- != 0 ) - { - if ( *s1 < *s2 ) return -1; - if ( *s1 > *s2 ) return +1; - ++s1; ++s2; + template inline nssv_constexpr14 int compare(CharT const* s1, CharT const* s2, std::size_t count) { + while(count-- != 0) { + if(*s1 < *s2) + return -1; + if(*s1 > *s2) + return +1; + ++s1; + ++s2; + } + return 0; } - return 0; -} #if nssv_HAVE_BUILTIN_MEMCMP -// specialization of compare() for char, see also generic compare() above: + // specialization of compare() for char, see also generic compare() above: -inline nssv_constexpr14 int compare( char const * s1, char const * s2, std::size_t count ) -{ - return nssv_BUILTIN_MEMCMP( s1, s2, count ); -} + inline nssv_constexpr14 int compare(char const* s1, char const* s2, std::size_t count) { return nssv_BUILTIN_MEMCMP(s1, s2, count); } #endif #if nssv_HAVE_BUILTIN_STRLEN -// specialization of length() for char, see also generic length() further below: + // specialization of length() for char, see also generic length() further below: -inline nssv_constexpr std::size_t length( char const * s ) -{ - return nssv_BUILTIN_STRLEN( s ); -} + inline nssv_constexpr std::size_t length(char const* s) { return nssv_BUILTIN_STRLEN(s); } #endif #if defined(__OPTIMIZE__) -// gcc, clang provide __OPTIMIZE__ -// Expect tail call optimization to make length() non-recursive: + // gcc, clang provide __OPTIMIZE__ + // Expect tail call optimization to make length() non-recursive: -template< typename CharT > -inline nssv_constexpr std::size_t length( CharT * s, std::size_t result = 0 ) -{ - return *s == '\0' ? result : length( s + 1, result + 1 ); -} + template inline nssv_constexpr std::size_t length(CharT* s, std::size_t result = 0) { + return *s == '\0' ? result : length(s + 1, result + 1); + } #else // OPTIMIZE -// non-recursive: + // non-recursive: -template< typename CharT > -inline nssv_constexpr14 std::size_t length( CharT * s ) -{ - std::size_t result = 0; - while ( *s++ != '\0' ) - { - ++result; + template inline nssv_constexpr14 std::size_t length(CharT* s) { + std::size_t result = 0; + while(*s++ != '\0') { + ++result; + } + return result; } - return result; -} #endif // OPTIMIZE -#if nssv_CPP11_OR_GREATER && ! nssv_CPP17_OR_GREATER +#if nssv_CPP11_OR_GREATER && !nssv_CPP17_OR_GREATER #if defined(__OPTIMIZE__) -// gcc, clang provide __OPTIMIZE__ -// Expect tail call optimization to make search() non-recursive: + // gcc, clang provide __OPTIMIZE__ + // Expect tail call optimization to make search() non-recursive: -template< class CharT, class Traits = std::char_traits > -constexpr const CharT* search( basic_string_view haystack, basic_string_view needle ) -{ - return haystack.starts_with( needle ) ? haystack.begin() : - haystack.empty() ? haystack.end() : search( haystack.substr(1), needle ); -} + template > + constexpr const CharT* search(basic_string_view haystack, basic_string_view needle) { + return haystack.starts_with(needle) ? haystack.begin() : haystack.empty() ? haystack.end() : search(haystack.substr(1), needle); + } #else // OPTIMIZE -// non-recursive: + // non-recursive: #if nssv_CONFIG_CONSTEXPR11_STD_SEARCH -template< class CharT, class Traits = std::char_traits > -constexpr const CharT* search( basic_string_view haystack, basic_string_view needle ) -{ - return std::search( haystack.begin(), haystack.end(), needle.begin(), needle.end() ); -} + template > + constexpr const CharT* search(basic_string_view haystack, basic_string_view needle) { + return std::search(haystack.begin(), haystack.end(), needle.begin(), needle.end()); + } -#else // nssv_CONFIG_CONSTEXPR11_STD_SEARCH +#else // nssv_CONFIG_CONSTEXPR11_STD_SEARCH -template< class CharT, class Traits = std::char_traits > -nssv_constexpr14 const CharT* search( basic_string_view haystack, basic_string_view needle ) -{ - while ( needle.size() <= haystack.size() ) - { - if ( haystack.starts_with(needle) ) - { - return haystack.cbegin(); + template > + nssv_constexpr14 const CharT* search(basic_string_view haystack, basic_string_view needle) { + while(needle.size() <= haystack.size()) { + if(haystack.starts_with(needle)) { + return haystack.cbegin(); + } + haystack = basic_string_view{haystack.begin() + 1, haystack.size() - 1U}; } - haystack = basic_string_view{ haystack.begin() + 1, haystack.size() - 1U }; + return haystack.cend(); } - return haystack.cend(); -} #endif // nssv_CONFIG_CONSTEXPR11_STD_SEARCH #endif // OPTIMIZE #endif // nssv_CPP11_OR_GREATER && ! nssv_CPP17_OR_GREATER -} // namespace detail + } // namespace detail -// -// basic_string_view: -// + // + // basic_string_view: + // -template -< - class CharT, - class Traits /* = std::char_traits */ -> -class basic_string_view -{ -public: - // Member types: + template */ + > + class basic_string_view { + public: + // Member types: - typedef Traits traits_type; - typedef CharT value_type; + typedef Traits traits_type; + typedef CharT value_type; - typedef CharT * pointer; - typedef CharT const * const_pointer; - typedef CharT & reference; - typedef CharT const & const_reference; + typedef CharT* pointer; + typedef CharT const* const_pointer; + typedef CharT& reference; + typedef CharT const& const_reference; - typedef const_pointer iterator; - typedef const_pointer const_iterator; - typedef std::reverse_iterator< const_iterator > reverse_iterator; - typedef std::reverse_iterator< const_iterator > const_reverse_iterator; + typedef const_pointer iterator; + typedef const_pointer const_iterator; + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; - typedef std::size_t size_type; - typedef std::ptrdiff_t difference_type; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; - // 24.4.2.1 Construction and assignment: + // 24.4.2.1 Construction and assignment: - nssv_constexpr basic_string_view() nssv_noexcept - : data_( nssv_nullptr ) - , size_( 0 ) - {} + nssv_constexpr basic_string_view() nssv_noexcept : data_(nssv_nullptr), size_(0) {} #if nssv_CPP11_OR_GREATER - nssv_constexpr basic_string_view( basic_string_view const & other ) nssv_noexcept = default; + nssv_constexpr basic_string_view(basic_string_view const& other) nssv_noexcept = default; #else - nssv_constexpr basic_string_view( basic_string_view const & other ) nssv_noexcept - : data_( other.data_) - , size_( other.size_) - {} + nssv_constexpr basic_string_view(basic_string_view const& other) nssv_noexcept : data_(other.data_), size_(other.size_) {} #endif - nssv_constexpr basic_string_view( CharT const * s, size_type count ) nssv_noexcept // non-standard noexcept - : data_( s ) - , size_( count ) - {} + nssv_constexpr basic_string_view(CharT const* s, size_type count) nssv_noexcept // non-standard noexcept + : data_(s), + size_(count) {} - nssv_constexpr basic_string_view( CharT const * s) nssv_noexcept // non-standard noexcept - : data_( s ) + nssv_constexpr basic_string_view(CharT const* s) nssv_noexcept // non-standard noexcept + : data_(s) #if nssv_CPP17_OR_GREATER - , size_( Traits::length(s) ) + , + size_(Traits::length(s)) #elif nssv_CPP11_OR_GREATER - , size_( detail::length(s) ) + , + size_(detail::length(s)) #else - , size_( Traits::length(s) ) + , + size_(Traits::length(s)) +#endif + { + } + +#if nssv_HAVE_NULLPTR +#if nssv_HAVE_IS_DELETE + nssv_constexpr basic_string_view(std::nullptr_t) nssv_noexcept = delete; +#else + private: + nssv_constexpr basic_string_view(std::nullptr_t) nssv_noexcept; + + public: #endif - {} - -#if nssv_HAVE_NULLPTR -# if nssv_HAVE_IS_DELETE - nssv_constexpr basic_string_view( std::nullptr_t ) nssv_noexcept = delete; -# else - private: nssv_constexpr basic_string_view( std::nullptr_t ) nssv_noexcept; public: -# endif #endif - // Assignment: + // Assignment: #if nssv_CPP11_OR_GREATER - nssv_constexpr14 basic_string_view & operator=( basic_string_view const & other ) nssv_noexcept = default; + nssv_constexpr14 basic_string_view& operator=(basic_string_view const& other) nssv_noexcept = default; #else - nssv_constexpr14 basic_string_view & operator=( basic_string_view const & other ) nssv_noexcept - { - data_ = other.data_; - size_ = other.size_; - return *this; - } + nssv_constexpr14 basic_string_view& operator=(basic_string_view const& other) nssv_noexcept { + data_ = other.data_; + size_ = other.size_; + return *this; + } #endif - // 24.4.2.2 Iterator support: + // 24.4.2.2 Iterator support: - nssv_constexpr const_iterator begin() const nssv_noexcept { return data_; } - nssv_constexpr const_iterator end() const nssv_noexcept { return data_ + size_; } + nssv_constexpr const_iterator begin() const nssv_noexcept { return data_; } + nssv_constexpr const_iterator end() const nssv_noexcept { return data_ + size_; } - nssv_constexpr const_iterator cbegin() const nssv_noexcept { return begin(); } - nssv_constexpr const_iterator cend() const nssv_noexcept { return end(); } + nssv_constexpr const_iterator cbegin() const nssv_noexcept { return begin(); } + nssv_constexpr const_iterator cend() const nssv_noexcept { return end(); } - nssv_constexpr const_reverse_iterator rbegin() const nssv_noexcept { return const_reverse_iterator( end() ); } - nssv_constexpr const_reverse_iterator rend() const nssv_noexcept { return const_reverse_iterator( begin() ); } + nssv_constexpr const_reverse_iterator rbegin() const nssv_noexcept { return const_reverse_iterator(end()); } + nssv_constexpr const_reverse_iterator rend() const nssv_noexcept { return const_reverse_iterator(begin()); } - nssv_constexpr const_reverse_iterator crbegin() const nssv_noexcept { return rbegin(); } - nssv_constexpr const_reverse_iterator crend() const nssv_noexcept { return rend(); } + nssv_constexpr const_reverse_iterator crbegin() const nssv_noexcept { return rbegin(); } + nssv_constexpr const_reverse_iterator crend() const nssv_noexcept { return rend(); } - // 24.4.2.3 Capacity: + // 24.4.2.3 Capacity: - nssv_constexpr size_type size() const nssv_noexcept { return size_; } - nssv_constexpr size_type length() const nssv_noexcept { return size_; } - nssv_constexpr size_type max_size() const nssv_noexcept { return (std::numeric_limits< size_type >::max)(); } + nssv_constexpr size_type size() const nssv_noexcept { return size_; } + nssv_constexpr size_type length() const nssv_noexcept { return size_; } + nssv_constexpr size_type max_size() const nssv_noexcept { return (std::numeric_limits::max)(); } - // since C++20 - nssv_nodiscard nssv_constexpr bool empty() const nssv_noexcept - { - return 0 == size_; - } + // since C++20 + nssv_nodiscard nssv_constexpr bool empty() const nssv_noexcept { return 0 == size_; } - // 24.4.2.4 Element access: + // 24.4.2.4 Element access: - nssv_constexpr const_reference operator[]( size_type pos ) const - { - return data_at( pos ); - } + nssv_constexpr const_reference operator[](size_type pos) const { return data_at(pos); } - nssv_constexpr14 const_reference at( size_type pos ) const - { + nssv_constexpr14 const_reference at(size_type pos) const { #if nssv_CONFIG_NO_EXCEPTIONS - assert( pos < size() ); + assert(pos < size()); #else - if ( pos >= size() ) - { - throw std::out_of_range("nonstd::string_view::at()"); - } + if(pos >= size()) { + throw std::out_of_range("nonstd::string_view::at()"); + } #endif - return data_at( pos ); - } + return data_at(pos); + } - nssv_constexpr const_reference front() const { return data_at( 0 ); } - nssv_constexpr const_reference back() const { return data_at( size() - 1 ); } + nssv_constexpr const_reference front() const { return data_at(0); } + nssv_constexpr const_reference back() const { return data_at(size() - 1); } - nssv_constexpr const_pointer data() const nssv_noexcept { return data_; } + nssv_constexpr const_pointer data() const nssv_noexcept { return data_; } - // 24.4.2.5 Modifiers: + // 24.4.2.5 Modifiers: - nssv_constexpr14 void remove_prefix( size_type n ) - { - assert( n <= size() ); - data_ += n; - size_ -= n; - } + nssv_constexpr14 void remove_prefix(size_type n) { + assert(n <= size()); + data_ += n; + size_ -= n; + } - nssv_constexpr14 void remove_suffix( size_type n ) - { - assert( n <= size() ); - size_ -= n; - } + nssv_constexpr14 void remove_suffix(size_type n) { + assert(n <= size()); + size_ -= n; + } - nssv_constexpr14 void swap( basic_string_view & other ) nssv_noexcept - { - const basic_string_view tmp(other); - other = *this; - *this = tmp; - } + nssv_constexpr14 void swap(basic_string_view& other) nssv_noexcept { + const basic_string_view tmp(other); + other = *this; + *this = tmp; + } - // 24.4.2.6 String operations: + // 24.4.2.6 String operations: - size_type copy( CharT * dest, size_type n, size_type pos = 0 ) const - { + size_type copy(CharT* dest, size_type n, size_type pos = 0) const { #if nssv_CONFIG_NO_EXCEPTIONS - assert( pos <= size() ); + assert(pos <= size()); #else - if ( pos > size() ) - { - throw std::out_of_range("nonstd::string_view::copy()"); - } + if(pos > size()) { + throw std::out_of_range("nonstd::string_view::copy()"); + } #endif - const size_type rlen = (std::min)( n, size() - pos ); + const size_type rlen = (std::min)(n, size() - pos); - (void) Traits::copy( dest, data() + pos, rlen ); + (void)Traits::copy(dest, data() + pos, rlen); - return rlen; - } + return rlen; + } - nssv_constexpr14 basic_string_view substr( size_type pos = 0, size_type n = npos ) const - { + nssv_constexpr14 basic_string_view substr(size_type pos = 0, size_type n = npos) const { #if nssv_CONFIG_NO_EXCEPTIONS - assert( pos <= size() ); + assert(pos <= size()); #else - if ( pos > size() ) - { - throw std::out_of_range("nonstd::string_view::substr()"); - } + if(pos > size()) { + throw std::out_of_range("nonstd::string_view::substr()"); + } #endif - return basic_string_view( data() + pos, (std::min)( n, size() - pos ) ); - } + return basic_string_view(data() + pos, (std::min)(n, size() - pos)); + } - // compare(), 6x: + // compare(), 6x: - nssv_constexpr14 int compare( basic_string_view other ) const nssv_noexcept // (1) - { + nssv_constexpr14 int compare(basic_string_view other) const nssv_noexcept // (1) + { #if nssv_CPP17_OR_GREATER - if ( const int result = Traits::compare( data(), other.data(), (std::min)( size(), other.size() ) ) ) + if(const int result = Traits::compare(data(), other.data(), (std::min)(size(), other.size()))) #else - if ( const int result = detail::compare( data(), other.data(), (std::min)( size(), other.size() ) ) ) + if(const int result = detail::compare(data(), other.data(), (std::min)(size(), other.size()))) #endif - { - return result; - } + { + return result; + } - return size() == other.size() ? 0 : size() < other.size() ? -1 : 1; - } + return size() == other.size() ? 0 : size() < other.size() ? -1 : 1; + } - nssv_constexpr int compare( size_type pos1, size_type n1, basic_string_view other ) const // (2) - { - return substr( pos1, n1 ).compare( other ); - } + nssv_constexpr int compare(size_type pos1, size_type n1, basic_string_view other) const // (2) + { + return substr(pos1, n1).compare(other); + } - nssv_constexpr int compare( size_type pos1, size_type n1, basic_string_view other, size_type pos2, size_type n2 ) const // (3) - { - return substr( pos1, n1 ).compare( other.substr( pos2, n2 ) ); - } + nssv_constexpr int compare(size_type pos1, size_type n1, basic_string_view other, size_type pos2, size_type n2) const // (3) + { + return substr(pos1, n1).compare(other.substr(pos2, n2)); + } - nssv_constexpr int compare( CharT const * s ) const // (4) - { - return compare( basic_string_view( s ) ); - } + nssv_constexpr int compare(CharT const* s) const // (4) + { + return compare(basic_string_view(s)); + } - nssv_constexpr int compare( size_type pos1, size_type n1, CharT const * s ) const // (5) - { - return substr( pos1, n1 ).compare( basic_string_view( s ) ); - } + nssv_constexpr int compare(size_type pos1, size_type n1, CharT const* s) const // (5) + { + return substr(pos1, n1).compare(basic_string_view(s)); + } - nssv_constexpr int compare( size_type pos1, size_type n1, CharT const * s, size_type n2 ) const // (6) - { - return substr( pos1, n1 ).compare( basic_string_view( s, n2 ) ); - } + nssv_constexpr int compare(size_type pos1, size_type n1, CharT const* s, size_type n2) const // (6) + { + return substr(pos1, n1).compare(basic_string_view(s, n2)); + } - // 24.4.2.7 Searching: + // 24.4.2.7 Searching: - // starts_with(), 3x, since C++20: + // starts_with(), 3x, since C++20: - nssv_constexpr bool starts_with( basic_string_view v ) const nssv_noexcept // (1) - { - return size() >= v.size() && compare( 0, v.size(), v ) == 0; - } + nssv_constexpr bool starts_with(basic_string_view v) const nssv_noexcept // (1) + { + return size() >= v.size() && compare(0, v.size(), v) == 0; + } - nssv_constexpr bool starts_with( CharT c ) const nssv_noexcept // (2) - { - return starts_with( basic_string_view( &c, 1 ) ); - } + nssv_constexpr bool starts_with(CharT c) const nssv_noexcept // (2) + { + return starts_with(basic_string_view(&c, 1)); + } - nssv_constexpr bool starts_with( CharT const * s ) const // (3) - { - return starts_with( basic_string_view( s ) ); - } + nssv_constexpr bool starts_with(CharT const* s) const // (3) + { + return starts_with(basic_string_view(s)); + } - // ends_with(), 3x, since C++20: + // ends_with(), 3x, since C++20: - nssv_constexpr bool ends_with( basic_string_view v ) const nssv_noexcept // (1) - { - return size() >= v.size() && compare( size() - v.size(), npos, v ) == 0; - } + nssv_constexpr bool ends_with(basic_string_view v) const nssv_noexcept // (1) + { + return size() >= v.size() && compare(size() - v.size(), npos, v) == 0; + } - nssv_constexpr bool ends_with( CharT c ) const nssv_noexcept // (2) - { - return ends_with( basic_string_view( &c, 1 ) ); - } + nssv_constexpr bool ends_with(CharT c) const nssv_noexcept // (2) + { + return ends_with(basic_string_view(&c, 1)); + } - nssv_constexpr bool ends_with( CharT const * s ) const // (3) - { - return ends_with( basic_string_view( s ) ); - } + nssv_constexpr bool ends_with(CharT const* s) const // (3) + { + return ends_with(basic_string_view(s)); + } - // find(), 4x: + // find(), 4x: - nssv_constexpr14 size_type find( basic_string_view v, size_type pos = 0 ) const nssv_noexcept // (1) - { - return assert( v.size() == 0 || v.data() != nssv_nullptr ) - , pos >= size() - ? npos : to_pos( -#if nssv_CPP11_OR_GREATER && ! nssv_CPP17_OR_GREATER - detail::search( substr(pos), v ) + nssv_constexpr14 size_type find(basic_string_view v, size_type pos = 0) const nssv_noexcept // (1) + { + return assert(v.size() == 0 || v.data() != nssv_nullptr), pos >= size() ? npos + : to_pos( +#if nssv_CPP11_OR_GREATER && !nssv_CPP17_OR_GREATER + detail::search(substr(pos), v) #else - std::search( cbegin() + pos, cend(), v.cbegin(), v.cend(), Traits::eq ) + std::search(cbegin() + pos, cend(), v.cbegin(), + v.cend(), Traits::eq) #endif - ); - } + ); + } - nssv_constexpr size_type find( CharT c, size_type pos = 0 ) const nssv_noexcept // (2) - { - return find( basic_string_view( &c, 1 ), pos ); - } + nssv_constexpr size_type find(CharT c, size_type pos = 0) const nssv_noexcept // (2) + { + return find(basic_string_view(&c, 1), pos); + } - nssv_constexpr size_type find( CharT const * s, size_type pos, size_type n ) const // (3) - { - return find( basic_string_view( s, n ), pos ); - } + nssv_constexpr size_type find(CharT const* s, size_type pos, size_type n) const // (3) + { + return find(basic_string_view(s, n), pos); + } - nssv_constexpr size_type find( CharT const * s, size_type pos = 0 ) const // (4) - { - return find( basic_string_view( s ), pos ); - } + nssv_constexpr size_type find(CharT const* s, size_type pos = 0) const // (4) + { + return find(basic_string_view(s), pos); + } + + // rfind(), 4x: + + nssv_constexpr14 size_type rfind(basic_string_view v, size_type pos = npos) const nssv_noexcept // (1) + { + if(size() < v.size()) { + return npos; + } + + if(v.empty()) { + return (std::min)(size(), pos); + } + + const_iterator last = cbegin() + (std::min)(size() - v.size(), pos) + v.size(); + const_iterator result = std::find_end(cbegin(), last, v.cbegin(), v.cend(), Traits::eq); + + return result != last ? size_type(result - cbegin()) : npos; + } + + nssv_constexpr14 size_type rfind(CharT c, size_type pos = npos) const nssv_noexcept // (2) + { + return rfind(basic_string_view(&c, 1), pos); + } + + nssv_constexpr14 size_type rfind(CharT const* s, size_type pos, size_type n) const // (3) + { + return rfind(basic_string_view(s, n), pos); + } + + nssv_constexpr14 size_type rfind(CharT const* s, size_type pos = npos) const // (4) + { + return rfind(basic_string_view(s), pos); + } + + // find_first_of(), 4x: + + nssv_constexpr size_type find_first_of(basic_string_view v, size_type pos = 0) const nssv_noexcept // (1) + { + return pos >= size() ? npos : to_pos(std::find_first_of(cbegin() + pos, cend(), v.cbegin(), v.cend(), Traits::eq)); + } + + nssv_constexpr size_type find_first_of(CharT c, size_type pos = 0) const nssv_noexcept // (2) + { + return find_first_of(basic_string_view(&c, 1), pos); + } + + nssv_constexpr size_type find_first_of(CharT const* s, size_type pos, size_type n) const // (3) + { + return find_first_of(basic_string_view(s, n), pos); + } + + nssv_constexpr size_type find_first_of(CharT const* s, size_type pos = 0) const // (4) + { + return find_first_of(basic_string_view(s), pos); + } + + // find_last_of(), 4x: + + nssv_constexpr size_type find_last_of(basic_string_view v, size_type pos = npos) const nssv_noexcept // (1) + { + return empty() ? npos + : pos >= size() + ? find_last_of(v, size() - 1) + : to_pos(std::find_first_of(const_reverse_iterator(cbegin() + pos + 1), crend(), v.cbegin(), v.cend(), Traits::eq)); + } + + nssv_constexpr size_type find_last_of(CharT c, size_type pos = npos) const nssv_noexcept // (2) + { + return find_last_of(basic_string_view(&c, 1), pos); + } + + nssv_constexpr size_type find_last_of(CharT const* s, size_type pos, size_type count) const // (3) + { + return find_last_of(basic_string_view(s, count), pos); + } + + nssv_constexpr size_type find_last_of(CharT const* s, size_type pos = npos) const // (4) + { + return find_last_of(basic_string_view(s), pos); + } + + // find_first_not_of(), 4x: - // rfind(), 4x: + nssv_constexpr size_type find_first_not_of(basic_string_view v, size_type pos = 0) const nssv_noexcept // (1) + { + return pos >= size() ? npos : to_pos(std::find_if(cbegin() + pos, cend(), not_in_view(v))); + } + + nssv_constexpr size_type find_first_not_of(CharT c, size_type pos = 0) const nssv_noexcept // (2) + { + return find_first_not_of(basic_string_view(&c, 1), pos); + } - nssv_constexpr14 size_type rfind( basic_string_view v, size_type pos = npos ) const nssv_noexcept // (1) - { - if ( size() < v.size() ) + nssv_constexpr size_type find_first_not_of(CharT const* s, size_type pos, size_type count) const // (3) { - return npos; + return find_first_not_of(basic_string_view(s, count), pos); } - if ( v.empty() ) + nssv_constexpr size_type find_first_not_of(CharT const* s, size_type pos = 0) const // (4) { - return (std::min)( size(), pos ); + return find_first_not_of(basic_string_view(s), pos); + } + + // find_last_not_of(), 4x: + + nssv_constexpr size_type find_last_not_of(basic_string_view v, size_type pos = npos) const nssv_noexcept // (1) + { + return empty() ? npos + : pos >= size() ? find_last_not_of(v, size() - 1) + : to_pos(std::find_if(const_reverse_iterator(cbegin() + pos + 1), crend(), not_in_view(v))); + } + + nssv_constexpr size_type find_last_not_of(CharT c, size_type pos = npos) const nssv_noexcept // (2) + { + return find_last_not_of(basic_string_view(&c, 1), pos); + } + + nssv_constexpr size_type find_last_not_of(CharT const* s, size_type pos, size_type count) const // (3) + { + return find_last_not_of(basic_string_view(s, count), pos); + } + + nssv_constexpr size_type find_last_not_of(CharT const* s, size_type pos = npos) const // (4) + { + return find_last_not_of(basic_string_view(s), pos); + } + + // Constants: + +#if nssv_CPP17_OR_GREATER + static nssv_constexpr size_type npos = size_type(-1); +#elif nssv_CPP11_OR_GREATER + enum : size_type { npos = size_type(-1) }; +#else + enum { npos = size_type(-1) }; +#endif + + private: + struct not_in_view { + const basic_string_view v; + + nssv_constexpr explicit not_in_view(basic_string_view v_) + : v(v_) {} + + nssv_constexpr bool operator()(CharT c) const { return npos == v.find_first_of(c); } + }; + + nssv_constexpr size_type to_pos(const_iterator it) const { return it == cend() ? npos : size_type(it - cbegin()); } + + nssv_constexpr size_type to_pos(const_reverse_iterator it) const { return it == crend() ? npos : size_type(crend() - it - 1); } + + nssv_constexpr const_reference data_at(size_type pos) const { +#if nssv_BETWEEN(nssv_COMPILER_GNUC_VERSION, 1, 500) + return data_[pos]; +#else + return assert(pos < size()), data_[pos]; +#endif } - const_iterator last = cbegin() + (std::min)( size() - v.size(), pos ) + v.size(); - const_iterator result = std::find_end( cbegin(), last, v.cbegin(), v.cend(), Traits::eq ); + private: + const_pointer data_; + size_type size_; + + public: +#if nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS + + template + basic_string_view(std::basic_string const& s) nssv_noexcept : data_(s.data()), size_(s.size()) {} + +#if nssv_HAVE_EXPLICIT_CONVERSION + + template explicit operator std::basic_string() const { return to_string(Allocator()); } - return result != last ? size_type( result - cbegin() ) : npos; +#endif // nssv_HAVE_EXPLICIT_CONVERSION + +#if nssv_CPP11_OR_GREATER + + template > + std::basic_string to_string(Allocator const& a = Allocator()) const { + return std::basic_string(begin(), end(), a); + } + +#else + + std::basic_string to_string() const { return std::basic_string(begin(), end()); } + + template std::basic_string to_string(Allocator const& a) const { + return std::basic_string(begin(), end(), a); + } + +#endif // nssv_CPP11_OR_GREATER + +#endif // nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS + }; + + // + // Non-member functions: + // + + // 24.4.3 Non-member comparison functions: + // lexicographically compare two string views (function template): + + template + nssv_constexpr bool operator==(basic_string_view lhs, basic_string_view rhs) nssv_noexcept { + return lhs.size() == rhs.size() && lhs.compare(rhs) == 0; } - nssv_constexpr14 size_type rfind( CharT c, size_type pos = npos ) const nssv_noexcept // (2) - { - return rfind( basic_string_view( &c, 1 ), pos ); + template + nssv_constexpr bool operator!=(basic_string_view lhs, basic_string_view rhs) nssv_noexcept { + return !(lhs == rhs); } - nssv_constexpr14 size_type rfind( CharT const * s, size_type pos, size_type n ) const // (3) - { - return rfind( basic_string_view( s, n ), pos ); + template + nssv_constexpr bool operator<(basic_string_view lhs, basic_string_view rhs) nssv_noexcept { + return lhs.compare(rhs) < 0; } - nssv_constexpr14 size_type rfind( CharT const * s, size_type pos = npos ) const // (4) - { - return rfind( basic_string_view( s ), pos ); + template + nssv_constexpr bool operator<=(basic_string_view lhs, basic_string_view rhs) nssv_noexcept { + return lhs.compare(rhs) <= 0; } - // find_first_of(), 4x: + template + nssv_constexpr bool operator>(basic_string_view lhs, basic_string_view rhs) nssv_noexcept { + return lhs.compare(rhs) > 0; + } - nssv_constexpr size_type find_first_of( basic_string_view v, size_type pos = 0 ) const nssv_noexcept // (1) - { - return pos >= size() - ? npos - : to_pos( std::find_first_of( cbegin() + pos, cend(), v.cbegin(), v.cend(), Traits::eq ) ); + template + nssv_constexpr bool operator>=(basic_string_view lhs, basic_string_view rhs) nssv_noexcept { + return lhs.compare(rhs) >= 0; } - nssv_constexpr size_type find_first_of( CharT c, size_type pos = 0 ) const nssv_noexcept // (2) - { - return find_first_of( basic_string_view( &c, 1 ), pos ); + // Let S be basic_string_view, and sv be an instance of S. + // Implementations shall provide sufficient additional overloads marked + // constexpr and noexcept so that an object t with an implicit conversion + // to S can be compared according to Table 67. + +#if !nssv_CPP11_OR_GREATER || nssv_BETWEEN(nssv_COMPILER_MSVC_VERSION, 100, 141) + + // accommodate for older compilers: + + // == + + template + nssv_constexpr bool operator==(basic_string_view lhs, CharT const* rhs) nssv_noexcept { + return lhs.size() == detail::length(rhs) && lhs.compare(rhs) == 0; } - nssv_constexpr size_type find_first_of( CharT const * s, size_type pos, size_type n ) const // (3) - { - return find_first_of( basic_string_view( s, n ), pos ); + template + nssv_constexpr bool operator==(CharT const* lhs, basic_string_view rhs) nssv_noexcept { + return detail::length(lhs) == rhs.size() && rhs.compare(lhs) == 0; } - nssv_constexpr size_type find_first_of( CharT const * s, size_type pos = 0 ) const // (4) - { - return find_first_of( basic_string_view( s ), pos ); + template + nssv_constexpr bool operator==(basic_string_view lhs, std::basic_string rhs) nssv_noexcept { + return lhs.size() == rhs.size() && lhs.compare(rhs) == 0; } - // find_last_of(), 4x: + template + nssv_constexpr bool operator==(std::basic_string rhs, basic_string_view lhs) nssv_noexcept { + return lhs.size() == rhs.size() && lhs.compare(rhs) == 0; + } - nssv_constexpr size_type find_last_of( basic_string_view v, size_type pos = npos ) const nssv_noexcept // (1) - { - return empty() - ? npos - : pos >= size() - ? find_last_of( v, size() - 1 ) - : to_pos( std::find_first_of( const_reverse_iterator( cbegin() + pos + 1 ), crend(), v.cbegin(), v.cend(), Traits::eq ) ); + // != + + template + nssv_constexpr bool operator!=(basic_string_view lhs, CharT const* rhs) nssv_noexcept { + return !(lhs == rhs); } - nssv_constexpr size_type find_last_of( CharT c, size_type pos = npos ) const nssv_noexcept // (2) - { - return find_last_of( basic_string_view( &c, 1 ), pos ); + template + nssv_constexpr bool operator!=(CharT const* lhs, basic_string_view rhs) nssv_noexcept { + return !(lhs == rhs); } - nssv_constexpr size_type find_last_of( CharT const * s, size_type pos, size_type count ) const // (3) - { - return find_last_of( basic_string_view( s, count ), pos ); + template + nssv_constexpr bool operator!=(basic_string_view lhs, std::basic_string rhs) nssv_noexcept { + return !(lhs == rhs); } - nssv_constexpr size_type find_last_of( CharT const * s, size_type pos = npos ) const // (4) - { - return find_last_of( basic_string_view( s ), pos ); + template + nssv_constexpr bool operator!=(std::basic_string rhs, basic_string_view lhs) nssv_noexcept { + return !(lhs == rhs); } - // find_first_not_of(), 4x: + // < - nssv_constexpr size_type find_first_not_of( basic_string_view v, size_type pos = 0 ) const nssv_noexcept // (1) - { - return pos >= size() - ? npos - : to_pos( std::find_if( cbegin() + pos, cend(), not_in_view( v ) ) ); + template + nssv_constexpr bool operator<(basic_string_view lhs, CharT const* rhs) nssv_noexcept { + return lhs.compare(rhs) < 0; } - nssv_constexpr size_type find_first_not_of( CharT c, size_type pos = 0 ) const nssv_noexcept // (2) - { - return find_first_not_of( basic_string_view( &c, 1 ), pos ); + template + nssv_constexpr bool operator<(CharT const* lhs, basic_string_view rhs) nssv_noexcept { + return rhs.compare(lhs) > 0; } - nssv_constexpr size_type find_first_not_of( CharT const * s, size_type pos, size_type count ) const // (3) - { - return find_first_not_of( basic_string_view( s, count ), pos ); + template + nssv_constexpr bool operator<(basic_string_view lhs, std::basic_string rhs) nssv_noexcept { + return lhs.compare(rhs) < 0; } - nssv_constexpr size_type find_first_not_of( CharT const * s, size_type pos = 0 ) const // (4) - { - return find_first_not_of( basic_string_view( s ), pos ); + template + nssv_constexpr bool operator<(std::basic_string rhs, basic_string_view lhs) nssv_noexcept { + return rhs.compare(lhs) > 0; } - // find_last_not_of(), 4x: + // <= - nssv_constexpr size_type find_last_not_of( basic_string_view v, size_type pos = npos ) const nssv_noexcept // (1) - { - return empty() - ? npos - : pos >= size() - ? find_last_not_of( v, size() - 1 ) - : to_pos( std::find_if( const_reverse_iterator( cbegin() + pos + 1 ), crend(), not_in_view( v ) ) ); + template + nssv_constexpr bool operator<=(basic_string_view lhs, CharT const* rhs) nssv_noexcept { + return lhs.compare(rhs) <= 0; } - nssv_constexpr size_type find_last_not_of( CharT c, size_type pos = npos ) const nssv_noexcept // (2) - { - return find_last_not_of( basic_string_view( &c, 1 ), pos ); + template + nssv_constexpr bool operator<=(CharT const* lhs, basic_string_view rhs) nssv_noexcept { + return rhs.compare(lhs) >= 0; } - nssv_constexpr size_type find_last_not_of( CharT const * s, size_type pos, size_type count ) const // (3) - { - return find_last_not_of( basic_string_view( s, count ), pos ); + template + nssv_constexpr bool operator<=(basic_string_view lhs, std::basic_string rhs) nssv_noexcept { + return lhs.compare(rhs) <= 0; } - nssv_constexpr size_type find_last_not_of( CharT const * s, size_type pos = npos ) const // (4) - { - return find_last_not_of( basic_string_view( s ), pos ); + template + nssv_constexpr bool operator<=(std::basic_string rhs, basic_string_view lhs) nssv_noexcept { + return rhs.compare(lhs) >= 0; } - // Constants: + // > -#if nssv_CPP17_OR_GREATER - static nssv_constexpr size_type npos = size_type(-1); -#elif nssv_CPP11_OR_GREATER - enum : size_type { npos = size_type(-1) }; -#else - enum { npos = size_type(-1) }; -#endif + template + nssv_constexpr bool operator>(basic_string_view lhs, CharT const* rhs) nssv_noexcept { + return lhs.compare(rhs) > 0; + } -private: - struct not_in_view - { - const basic_string_view v; + template + nssv_constexpr bool operator>(CharT const* lhs, basic_string_view rhs) nssv_noexcept { + return rhs.compare(lhs) < 0; + } - nssv_constexpr explicit not_in_view( basic_string_view v_ ) : v( v_ ) {} + template + nssv_constexpr bool operator>(basic_string_view lhs, std::basic_string rhs) nssv_noexcept { + return lhs.compare(rhs) > 0; + } - nssv_constexpr bool operator()( CharT c ) const - { - return npos == v.find_first_of( c ); - } - }; + template + nssv_constexpr bool operator>(std::basic_string rhs, basic_string_view lhs) nssv_noexcept { + return rhs.compare(lhs) < 0; + } + + // >= - nssv_constexpr size_type to_pos( const_iterator it ) const - { - return it == cend() ? npos : size_type( it - cbegin() ); + template + nssv_constexpr bool operator>=(basic_string_view lhs, CharT const* rhs) nssv_noexcept { + return lhs.compare(rhs) >= 0; } - nssv_constexpr size_type to_pos( const_reverse_iterator it ) const - { - return it == crend() ? npos : size_type( crend() - it - 1 ); + template + nssv_constexpr bool operator>=(CharT const* lhs, basic_string_view rhs) nssv_noexcept { + return rhs.compare(lhs) <= 0; } - nssv_constexpr const_reference data_at( size_type pos ) const - { -#if nssv_BETWEEN( nssv_COMPILER_GNUC_VERSION, 1, 500 ) - return data_[pos]; -#else - return assert( pos < size() ), data_[pos]; -#endif + template + nssv_constexpr bool operator>=(basic_string_view lhs, std::basic_string rhs) nssv_noexcept { + return lhs.compare(rhs) >= 0; } -private: - const_pointer data_; - size_type size_; + template + nssv_constexpr bool operator>=(std::basic_string rhs, basic_string_view lhs) nssv_noexcept { + return rhs.compare(lhs) <= 0; + } -public: -#if nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS +#else // newer compilers: - template< class Allocator > - basic_string_view( std::basic_string const & s ) nssv_noexcept - : data_( s.data() ) - , size_( s.size() ) - {} +#define nssv_BASIC_STRING_VIEW_I(T, U) typename std::decay>::type -#if nssv_HAVE_EXPLICIT_CONVERSION +#if defined(_MSC_VER) // issue 40 +#define nssv_MSVC_ORDER(x) , int = x +#else +#define nssv_MSVC_ORDER(x) /*, int=x*/ +#endif + + // == - template< class Allocator > - explicit operator std::basic_string() const - { - return to_string( Allocator() ); + template + nssv_constexpr bool operator==(basic_string_view lhs, nssv_BASIC_STRING_VIEW_I(CharT, Traits) rhs) nssv_noexcept { + return lhs.size() == rhs.size() && lhs.compare(rhs) == 0; } -#endif // nssv_HAVE_EXPLICIT_CONVERSION + template + nssv_constexpr bool operator==(nssv_BASIC_STRING_VIEW_I(CharT, Traits) lhs, basic_string_view rhs) nssv_noexcept { + return lhs.size() == rhs.size() && lhs.compare(rhs) == 0; + } -#if nssv_CPP11_OR_GREATER + // != - template< class Allocator = std::allocator > - std::basic_string - to_string( Allocator const & a = Allocator() ) const - { - return std::basic_string( begin(), end(), a ); + template + nssv_constexpr bool operator!=(basic_string_view lhs, nssv_BASIC_STRING_VIEW_I(CharT, Traits) rhs) nssv_noexcept { + return !(lhs == rhs); } -#else + template + nssv_constexpr bool operator!=(nssv_BASIC_STRING_VIEW_I(CharT, Traits) lhs, basic_string_view rhs) nssv_noexcept { + return !(lhs == rhs); + } + + // < - std::basic_string - to_string() const - { - return std::basic_string( begin(), end() ); + template + nssv_constexpr bool operator<(basic_string_view lhs, nssv_BASIC_STRING_VIEW_I(CharT, Traits) rhs) nssv_noexcept { + return lhs.compare(rhs) < 0; } - template< class Allocator > - std::basic_string - to_string( Allocator const & a ) const - { - return std::basic_string( begin(), end(), a ); + template + nssv_constexpr bool operator<(nssv_BASIC_STRING_VIEW_I(CharT, Traits) lhs, basic_string_view rhs) nssv_noexcept { + return lhs.compare(rhs) < 0; } -#endif // nssv_CPP11_OR_GREATER + // <= -#endif // nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS -}; + template + nssv_constexpr bool operator<=(basic_string_view lhs, nssv_BASIC_STRING_VIEW_I(CharT, Traits) rhs) nssv_noexcept { + return lhs.compare(rhs) <= 0; + } -// -// Non-member functions: -// + template + nssv_constexpr bool operator<=(nssv_BASIC_STRING_VIEW_I(CharT, Traits) lhs, basic_string_view rhs) nssv_noexcept { + return lhs.compare(rhs) <= 0; + } -// 24.4.3 Non-member comparison functions: -// lexicographically compare two string views (function template): - -template< class CharT, class Traits > -nssv_constexpr bool operator== ( - basic_string_view lhs, - basic_string_view rhs ) nssv_noexcept -{ return lhs.size() == rhs.size() && lhs.compare( rhs ) == 0; } - -template< class CharT, class Traits > -nssv_constexpr bool operator!= ( - basic_string_view lhs, - basic_string_view rhs ) nssv_noexcept -{ return !( lhs == rhs ); } - -template< class CharT, class Traits > -nssv_constexpr bool operator< ( - basic_string_view lhs, - basic_string_view rhs ) nssv_noexcept -{ return lhs.compare( rhs ) < 0; } - -template< class CharT, class Traits > -nssv_constexpr bool operator<= ( - basic_string_view lhs, - basic_string_view rhs ) nssv_noexcept -{ return lhs.compare( rhs ) <= 0; } - -template< class CharT, class Traits > -nssv_constexpr bool operator> ( - basic_string_view lhs, - basic_string_view rhs ) nssv_noexcept -{ return lhs.compare( rhs ) > 0; } - -template< class CharT, class Traits > -nssv_constexpr bool operator>= ( - basic_string_view lhs, - basic_string_view rhs ) nssv_noexcept -{ return lhs.compare( rhs ) >= 0; } - -// Let S be basic_string_view, and sv be an instance of S. -// Implementations shall provide sufficient additional overloads marked -// constexpr and noexcept so that an object t with an implicit conversion -// to S can be compared according to Table 67. - -#if ! nssv_CPP11_OR_GREATER || nssv_BETWEEN( nssv_COMPILER_MSVC_VERSION, 100, 141 ) - -// accommodate for older compilers: - -// == - -template< class CharT, class Traits> -nssv_constexpr bool operator==( - basic_string_view lhs, - CharT const * rhs ) nssv_noexcept -{ return lhs.size() == detail::length( rhs ) && lhs.compare( rhs ) == 0; } - -template< class CharT, class Traits> -nssv_constexpr bool operator==( - CharT const * lhs, - basic_string_view rhs ) nssv_noexcept -{ return detail::length( lhs ) == rhs.size() && rhs.compare( lhs ) == 0; } - -template< class CharT, class Traits> -nssv_constexpr bool operator==( - basic_string_view lhs, - std::basic_string rhs ) nssv_noexcept -{ return lhs.size() == rhs.size() && lhs.compare( rhs ) == 0; } - -template< class CharT, class Traits> -nssv_constexpr bool operator==( - std::basic_string rhs, - basic_string_view lhs ) nssv_noexcept -{ return lhs.size() == rhs.size() && lhs.compare( rhs ) == 0; } - -// != - -template< class CharT, class Traits> -nssv_constexpr bool operator!=( - basic_string_view lhs, - CharT const * rhs ) nssv_noexcept -{ return !( lhs == rhs ); } - -template< class CharT, class Traits> -nssv_constexpr bool operator!=( - CharT const * lhs, - basic_string_view rhs ) nssv_noexcept -{ return !( lhs == rhs ); } - -template< class CharT, class Traits> -nssv_constexpr bool operator!=( - basic_string_view lhs, - std::basic_string rhs ) nssv_noexcept -{ return !( lhs == rhs ); } - -template< class CharT, class Traits> -nssv_constexpr bool operator!=( - std::basic_string rhs, - basic_string_view lhs ) nssv_noexcept -{ return !( lhs == rhs ); } - -// < - -template< class CharT, class Traits> -nssv_constexpr bool operator<( - basic_string_view lhs, - CharT const * rhs ) nssv_noexcept -{ return lhs.compare( rhs ) < 0; } - -template< class CharT, class Traits> -nssv_constexpr bool operator<( - CharT const * lhs, - basic_string_view rhs ) nssv_noexcept -{ return rhs.compare( lhs ) > 0; } - -template< class CharT, class Traits> -nssv_constexpr bool operator<( - basic_string_view lhs, - std::basic_string rhs ) nssv_noexcept -{ return lhs.compare( rhs ) < 0; } - -template< class CharT, class Traits> -nssv_constexpr bool operator<( - std::basic_string rhs, - basic_string_view lhs ) nssv_noexcept -{ return rhs.compare( lhs ) > 0; } - -// <= - -template< class CharT, class Traits> -nssv_constexpr bool operator<=( - basic_string_view lhs, - CharT const * rhs ) nssv_noexcept -{ return lhs.compare( rhs ) <= 0; } - -template< class CharT, class Traits> -nssv_constexpr bool operator<=( - CharT const * lhs, - basic_string_view rhs ) nssv_noexcept -{ return rhs.compare( lhs ) >= 0; } - -template< class CharT, class Traits> -nssv_constexpr bool operator<=( - basic_string_view lhs, - std::basic_string rhs ) nssv_noexcept -{ return lhs.compare( rhs ) <= 0; } - -template< class CharT, class Traits> -nssv_constexpr bool operator<=( - std::basic_string rhs, - basic_string_view lhs ) nssv_noexcept -{ return rhs.compare( lhs ) >= 0; } - -// > - -template< class CharT, class Traits> -nssv_constexpr bool operator>( - basic_string_view lhs, - CharT const * rhs ) nssv_noexcept -{ return lhs.compare( rhs ) > 0; } - -template< class CharT, class Traits> -nssv_constexpr bool operator>( - CharT const * lhs, - basic_string_view rhs ) nssv_noexcept -{ return rhs.compare( lhs ) < 0; } - -template< class CharT, class Traits> -nssv_constexpr bool operator>( - basic_string_view lhs, - std::basic_string rhs ) nssv_noexcept -{ return lhs.compare( rhs ) > 0; } - -template< class CharT, class Traits> -nssv_constexpr bool operator>( - std::basic_string rhs, - basic_string_view lhs ) nssv_noexcept -{ return rhs.compare( lhs ) < 0; } - -// >= - -template< class CharT, class Traits> -nssv_constexpr bool operator>=( - basic_string_view lhs, - CharT const * rhs ) nssv_noexcept -{ return lhs.compare( rhs ) >= 0; } - -template< class CharT, class Traits> -nssv_constexpr bool operator>=( - CharT const * lhs, - basic_string_view rhs ) nssv_noexcept -{ return rhs.compare( lhs ) <= 0; } - -template< class CharT, class Traits> -nssv_constexpr bool operator>=( - basic_string_view lhs, - std::basic_string rhs ) nssv_noexcept -{ return lhs.compare( rhs ) >= 0; } - -template< class CharT, class Traits> -nssv_constexpr bool operator>=( - std::basic_string rhs, - basic_string_view lhs ) nssv_noexcept -{ return rhs.compare( lhs ) <= 0; } + // > -#else // newer compilers: + template + nssv_constexpr bool operator>(basic_string_view lhs, nssv_BASIC_STRING_VIEW_I(CharT, Traits) rhs) nssv_noexcept { + return lhs.compare(rhs) > 0; + } -#define nssv_BASIC_STRING_VIEW_I(T,U) typename std::decay< basic_string_view >::type + template + nssv_constexpr bool operator>(nssv_BASIC_STRING_VIEW_I(CharT, Traits) lhs, basic_string_view rhs) nssv_noexcept { + return lhs.compare(rhs) > 0; + } -#if defined(_MSC_VER) // issue 40 -# define nssv_MSVC_ORDER(x) , int=x -#else -# define nssv_MSVC_ORDER(x) /*, int=x*/ -#endif + // >= -// == - -template< class CharT, class Traits nssv_MSVC_ORDER(1) > -nssv_constexpr bool operator==( - basic_string_view lhs, - nssv_BASIC_STRING_VIEW_I(CharT, Traits) rhs ) nssv_noexcept -{ return lhs.size() == rhs.size() && lhs.compare( rhs ) == 0; } - -template< class CharT, class Traits nssv_MSVC_ORDER(2) > -nssv_constexpr bool operator==( - nssv_BASIC_STRING_VIEW_I(CharT, Traits) lhs, - basic_string_view rhs ) nssv_noexcept -{ return lhs.size() == rhs.size() && lhs.compare( rhs ) == 0; } - -// != - -template< class CharT, class Traits nssv_MSVC_ORDER(1) > -nssv_constexpr bool operator!= ( - basic_string_view < CharT, Traits > lhs, - nssv_BASIC_STRING_VIEW_I( CharT, Traits ) rhs ) nssv_noexcept -{ return !( lhs == rhs ); } - -template< class CharT, class Traits nssv_MSVC_ORDER(2) > -nssv_constexpr bool operator!= ( - nssv_BASIC_STRING_VIEW_I( CharT, Traits ) lhs, - basic_string_view < CharT, Traits > rhs ) nssv_noexcept -{ return !( lhs == rhs ); } - -// < - -template< class CharT, class Traits nssv_MSVC_ORDER(1) > -nssv_constexpr bool operator< ( - basic_string_view < CharT, Traits > lhs, - nssv_BASIC_STRING_VIEW_I( CharT, Traits ) rhs ) nssv_noexcept -{ return lhs.compare( rhs ) < 0; } - -template< class CharT, class Traits nssv_MSVC_ORDER(2) > -nssv_constexpr bool operator< ( - nssv_BASIC_STRING_VIEW_I( CharT, Traits ) lhs, - basic_string_view < CharT, Traits > rhs ) nssv_noexcept -{ return lhs.compare( rhs ) < 0; } - -// <= - -template< class CharT, class Traits nssv_MSVC_ORDER(1) > -nssv_constexpr bool operator<= ( - basic_string_view < CharT, Traits > lhs, - nssv_BASIC_STRING_VIEW_I( CharT, Traits ) rhs ) nssv_noexcept -{ return lhs.compare( rhs ) <= 0; } - -template< class CharT, class Traits nssv_MSVC_ORDER(2) > -nssv_constexpr bool operator<= ( - nssv_BASIC_STRING_VIEW_I( CharT, Traits ) lhs, - basic_string_view < CharT, Traits > rhs ) nssv_noexcept -{ return lhs.compare( rhs ) <= 0; } - -// > - -template< class CharT, class Traits nssv_MSVC_ORDER(1) > -nssv_constexpr bool operator> ( - basic_string_view < CharT, Traits > lhs, - nssv_BASIC_STRING_VIEW_I( CharT, Traits ) rhs ) nssv_noexcept -{ return lhs.compare( rhs ) > 0; } - -template< class CharT, class Traits nssv_MSVC_ORDER(2) > -nssv_constexpr bool operator> ( - nssv_BASIC_STRING_VIEW_I( CharT, Traits ) lhs, - basic_string_view < CharT, Traits > rhs ) nssv_noexcept -{ return lhs.compare( rhs ) > 0; } - -// >= - -template< class CharT, class Traits nssv_MSVC_ORDER(1) > -nssv_constexpr bool operator>= ( - basic_string_view < CharT, Traits > lhs, - nssv_BASIC_STRING_VIEW_I( CharT, Traits ) rhs ) nssv_noexcept -{ return lhs.compare( rhs ) >= 0; } - -template< class CharT, class Traits nssv_MSVC_ORDER(2) > -nssv_constexpr bool operator>= ( - nssv_BASIC_STRING_VIEW_I( CharT, Traits ) lhs, - basic_string_view < CharT, Traits > rhs ) nssv_noexcept -{ return lhs.compare( rhs ) >= 0; } + template + nssv_constexpr bool operator>=(basic_string_view lhs, nssv_BASIC_STRING_VIEW_I(CharT, Traits) rhs) nssv_noexcept { + return lhs.compare(rhs) >= 0; + } + + template + nssv_constexpr bool operator>=(nssv_BASIC_STRING_VIEW_I(CharT, Traits) lhs, basic_string_view rhs) nssv_noexcept { + return lhs.compare(rhs) >= 0; + } #undef nssv_MSVC_ORDER #undef nssv_BASIC_STRING_VIEW_I #endif // compiler-dependent approach to comparisons -// 24.4.4 Inserters and extractors: + // 24.4.4 Inserters and extractors: -#if ! nssv_CONFIG_NO_STREAM_INSERTION +#if !nssv_CONFIG_NO_STREAM_INSERTION -namespace detail { + namespace detail { -template< class Stream > -void write_padding( Stream & os, std::streamsize n ) -{ - for ( std::streamsize i = 0; i < n; ++i ) - os.rdbuf()->sputc( os.fill() ); -} + template void write_padding(Stream& os, std::streamsize n) { + for(std::streamsize i = 0; i < n; ++i) + os.rdbuf()->sputc(os.fill()); + } -template< class Stream, class View > -Stream & write_to_stream( Stream & os, View const & sv ) -{ - typename Stream::sentry sentry( os ); + template Stream& write_to_stream(Stream& os, View const& sv) { + typename Stream::sentry sentry(os); - if ( !sentry ) - return os; + if(!sentry) + return os; - const std::streamsize length = static_cast( sv.length() ); + const std::streamsize length = static_cast(sv.length()); - // Whether, and how, to pad: - const bool pad = ( length < os.width() ); - const bool left_pad = pad && ( os.flags() & std::ios_base::adjustfield ) == std::ios_base::right; + // Whether, and how, to pad: + const bool pad = (length < os.width()); + const bool left_pad = pad && (os.flags() & std::ios_base::adjustfield) == std::ios_base::right; - if ( left_pad ) - write_padding( os, os.width() - length ); + if(left_pad) + write_padding(os, os.width() - length); - // Write span characters: - os.rdbuf()->sputn( sv.begin(), length ); + // Write span characters: + os.rdbuf()->sputn(sv.begin(), length); - if ( pad && !left_pad ) - write_padding( os, os.width() - length ); + if(pad && !left_pad) + write_padding(os, os.width() - length); - // Reset output stream width: - os.width( 0 ); + // Reset output stream width: + os.width(0); - return os; -} + return os; + } -} // namespace detail + } // namespace detail -template< class CharT, class Traits > -std::basic_ostream & -operator<<( - std::basic_ostream& os, - basic_string_view sv ) -{ - return detail::write_to_stream( os, sv ); -} + template + std::basic_ostream& operator<<(std::basic_ostream& os, basic_string_view sv) { + return detail::write_to_stream(os, sv); + } #endif // nssv_CONFIG_NO_STREAM_INSERTION -// Several typedefs for common character types are provided: + // Several typedefs for common character types are provided: -typedef basic_string_view string_view; -typedef basic_string_view wstring_view; + typedef basic_string_view string_view; + typedef basic_string_view wstring_view; #if nssv_HAVE_WCHAR16_T -typedef basic_string_view u16string_view; -typedef basic_string_view u32string_view; + typedef basic_string_view u16string_view; + typedef basic_string_view u32string_view; #endif -}} // namespace nonstd::sv_lite + } // namespace sv_lite +} // namespace nonstd::sv_lite // // 24.4.6 Suffix for basic_string_view literals: @@ -1508,57 +1384,58 @@ typedef basic_string_view u32string_view; namespace nonstd { nssv_inline_ns namespace literals { -nssv_inline_ns namespace string_view_literals { + nssv_inline_ns namespace string_view_literals { #if nssv_CONFIG_STD_SV_OPERATOR && nssv_HAVE_STD_DEFINED_LITERALS -nssv_constexpr nonstd::sv_lite::string_view operator""sv( const char* str, size_t len ) nssv_noexcept // (1) -{ - return nonstd::sv_lite::string_view{ str, len }; -} + nssv_constexpr nonstd::sv_lite::string_view operator""sv(const char* str, size_t len)nssv_noexcept // (1) + { + return nonstd::sv_lite::string_view{str, len}; + } -nssv_constexpr nonstd::sv_lite::u16string_view operator""sv( const char16_t* str, size_t len ) nssv_noexcept // (2) -{ - return nonstd::sv_lite::u16string_view{ str, len }; -} + nssv_constexpr nonstd::sv_lite::u16string_view operator""sv(const char16_t* str, size_t len)nssv_noexcept // (2) + { + return nonstd::sv_lite::u16string_view{str, len}; + } -nssv_constexpr nonstd::sv_lite::u32string_view operator""sv( const char32_t* str, size_t len ) nssv_noexcept // (3) -{ - return nonstd::sv_lite::u32string_view{ str, len }; -} + nssv_constexpr nonstd::sv_lite::u32string_view operator""sv(const char32_t* str, size_t len)nssv_noexcept // (3) + { + return nonstd::sv_lite::u32string_view{str, len}; + } -nssv_constexpr nonstd::sv_lite::wstring_view operator""sv( const wchar_t* str, size_t len ) nssv_noexcept // (4) -{ - return nonstd::sv_lite::wstring_view{ str, len }; -} + nssv_constexpr nonstd::sv_lite::wstring_view operator""sv(const wchar_t* str, size_t len)nssv_noexcept // (4) + { + return nonstd::sv_lite::wstring_view{str, len}; + } #endif // nssv_CONFIG_STD_SV_OPERATOR && nssv_HAVE_STD_DEFINED_LITERALS #if nssv_CONFIG_USR_SV_OPERATOR -nssv_constexpr nonstd::sv_lite::string_view operator""_sv( const char* str, size_t len ) nssv_noexcept // (1) -{ - return nonstd::sv_lite::string_view{ str, len }; -} + nssv_constexpr nonstd::sv_lite::string_view operator""_sv(const char* str, size_t len)nssv_noexcept // (1) + { + return nonstd::sv_lite::string_view{str, len}; + } -nssv_constexpr nonstd::sv_lite::u16string_view operator""_sv( const char16_t* str, size_t len ) nssv_noexcept // (2) -{ - return nonstd::sv_lite::u16string_view{ str, len }; -} + nssv_constexpr nonstd::sv_lite::u16string_view operator""_sv(const char16_t* str, size_t len)nssv_noexcept // (2) + { + return nonstd::sv_lite::u16string_view{str, len}; + } -nssv_constexpr nonstd::sv_lite::u32string_view operator""_sv( const char32_t* str, size_t len ) nssv_noexcept // (3) -{ - return nonstd::sv_lite::u32string_view{ str, len }; -} + nssv_constexpr nonstd::sv_lite::u32string_view operator""_sv(const char32_t* str, size_t len)nssv_noexcept // (3) + { + return nonstd::sv_lite::u32string_view{str, len}; + } -nssv_constexpr nonstd::sv_lite::wstring_view operator""_sv( const wchar_t* str, size_t len ) nssv_noexcept // (4) -{ - return nonstd::sv_lite::wstring_view{ str, len }; -} + nssv_constexpr nonstd::sv_lite::wstring_view operator""_sv(const wchar_t* str, size_t len)nssv_noexcept // (4) + { + return nonstd::sv_lite::wstring_view{str, len}; + } #endif // nssv_CONFIG_USR_SV_OPERATOR - -}}} // namespace nonstd::literals::string_view_literals + } +} +} // namespace nonstd #endif @@ -1575,39 +1452,31 @@ namespace sv_lite { #if nssv_CPP11_OR_GREATER && nssv_COMPILER_MSVC_VERSION != 140 -template< class CharT, class Traits, class Allocator = std::allocator > -std::basic_string -to_string( basic_string_view v, Allocator const & a = Allocator() ) -{ - return std::basic_string( v.begin(), v.end(), a ); +template > +std::basic_string to_string(basic_string_view v, Allocator const& a = Allocator()) { + return std::basic_string(v.begin(), v.end(), a); } #else -template< class CharT, class Traits > -std::basic_string -to_string( basic_string_view v ) -{ - return std::basic_string( v.begin(), v.end() ); +template std::basic_string to_string(basic_string_view v) { + return std::basic_string(v.begin(), v.end()); } -template< class CharT, class Traits, class Allocator > -std::basic_string -to_string( basic_string_view v, Allocator const & a ) -{ - return std::basic_string( v.begin(), v.end(), a ); +template +std::basic_string to_string(basic_string_view v, Allocator const& a) { + return std::basic_string(v.begin(), v.end(), a); } #endif // nssv_CPP11_OR_GREATER -template< class CharT, class Traits, class Allocator > -basic_string_view -to_string_view( std::basic_string const & s ) -{ - return basic_string_view( s.data(), s.size() ); +template +basic_string_view to_string_view(std::basic_string const& s) { + return basic_string_view(s.data(), s.size()); } -}} // namespace nonstd::sv_lite +} // namespace sv_lite +} // namespace nonstd #endif // nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS @@ -1637,7 +1506,7 @@ using sv_lite::operator<=; using sv_lite::operator>; using sv_lite::operator>=; -#if ! nssv_CONFIG_NO_STREAM_INSERTION +#if !nssv_CONFIG_NO_STREAM_INSERTION using sv_lite::operator<<; #endif @@ -1659,43 +1528,29 @@ using sv_lite::to_string_view; namespace std { -template<> -struct hash< nonstd::string_view > -{ +template <> struct hash { public: - std::size_t operator()( nonstd::string_view v ) const nssv_noexcept - { - return std::hash()( std::string( v.data(), v.size() ) ); - } + std::size_t operator()(nonstd::string_view v) const nssv_noexcept { return std::hash()(std::string(v.data(), v.size())); } }; -template<> -struct hash< nonstd::wstring_view > -{ +template <> struct hash { public: - std::size_t operator()( nonstd::wstring_view v ) const nssv_noexcept - { - return std::hash()( std::wstring( v.data(), v.size() ) ); + std::size_t operator()(nonstd::wstring_view v) const nssv_noexcept { + return std::hash()(std::wstring(v.data(), v.size())); } }; -template<> -struct hash< nonstd::u16string_view > -{ +template <> struct hash { public: - std::size_t operator()( nonstd::u16string_view v ) const nssv_noexcept - { - return std::hash()( std::u16string( v.data(), v.size() ) ); + std::size_t operator()(nonstd::u16string_view v) const nssv_noexcept { + return std::hash()(std::u16string(v.data(), v.size())); } }; -template<> -struct hash< nonstd::u32string_view > -{ +template <> struct hash { public: - std::size_t operator()( nonstd::u32string_view v ) const nssv_noexcept - { - return std::hash()( std::u32string( v.data(), v.size() ) ); + std::size_t operator()(nonstd::u32string_view v) const nssv_noexcept { + return std::hash()(std::u32string(v.data(), v.size())); } }; @@ -1707,4 +1562,3 @@ nssv_RESTORE_WARNINGS() #endif // nssv_HAVE_STD_STRING_VIEW #endif // NONSTD_SV_LITE_H_INCLUDED - diff --git a/third_party/scp4scc/scp/report.h b/third_party/scp4scc/scp/report.h index feccd384a..9b7b042e5 100644 --- a/third_party/scp4scc/scp/report.h +++ b/third_party/scp4scc/scp/report.h @@ -266,13 +266,13 @@ class call_sc_name_fn { #define SCP_VBSTY_CHECK_UNCACHED(lvl, ...) (::scp::get_log_verbosity(__VA_ARGS__) >= lvl) #define SCP_VBSTY_CHECK(lvl, ...) \ - IIF(IS_PAREN(FIRST_ARG(__VA_ARGS__)))( \ - SCP_VBSTY_CHECK_CACHED(lvl, FIRST_ARG(__VA_ARGS__), SCP_LOGGER_NAME(EXPAND(FIRST_ARG FIRST_ARG(__VA_ARGS__)))), \ - SCP_VBSTY_CHECK_UNCACHED(lvl, ##__VA_ARGS__)) + IIF(IS_PAREN(FIRST_ARG(__VA_ARGS__))) \ + (SCP_VBSTY_CHECK_CACHED(lvl, FIRST_ARG(__VA_ARGS__), SCP_LOGGER_NAME(EXPAND(FIRST_ARG FIRST_ARG(__VA_ARGS__)))), \ + SCP_VBSTY_CHECK_UNCACHED(lvl, ##__VA_ARGS__)) #define SCP_GET_FEATURES(...) \ - IIF(IS_PAREN(FIRST_ARG(__VA_ARGS__)))( \ - FIRST_ARG EXPAND((POP_ARG(__VA_ARGS__, SCP_LOGGER_NAME(EXPAND(FIRST_ARG FIRST_ARG(__VA_ARGS__))).type))), __VA_ARGS__) + IIF(IS_PAREN(FIRST_ARG(__VA_ARGS__))) \ + (FIRST_ARG EXPAND((POP_ARG(__VA_ARGS__, SCP_LOGGER_NAME(EXPAND(FIRST_ARG FIRST_ARG(__VA_ARGS__))).type))), __VA_ARGS__) #ifdef FMT_SHARED #define _SCP_FMT_EMPTY_STR(...) fmt::format(__VA_ARGS__) From 709237bcbbf8fd119c7c88fc46865ac02fb113b8 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Fri, 13 Mar 2026 14:10:27 -0700 Subject: [PATCH 5/5] applies clang-format in C++11 mode --- src/common/nonstd/string_view.hpp | 4 ++-- third_party/axi_chi | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/common/nonstd/string_view.hpp b/src/common/nonstd/string_view.hpp index a2970f410..48d02b21f 100644 --- a/src/common/nonstd/string_view.hpp +++ b/src/common/nonstd/string_view.hpp @@ -837,8 +837,8 @@ nssv_DISABLE_MSVC_WARNINGS(4455 26481 26472) #if nssv_CPP11_OR_GREATER && !nssv_CPP17_OR_GREATER detail::search(substr(pos), v) #else - std::search(cbegin() + pos, cend(), v.cbegin(), - v.cend(), Traits::eq) + std::search(cbegin() + pos, cend(), v.cbegin(), + v.cend(), Traits::eq) #endif ); } diff --git a/third_party/axi_chi b/third_party/axi_chi index 1d527dd4f..a19719154 160000 --- a/third_party/axi_chi +++ b/third_party/axi_chi @@ -1 +1 @@ -Subproject commit 1d527dd4f62b7b3157e93463adc4b2902da65602 +Subproject commit a19719154bed4b3858605a4b3d76086dbaaa593e