diff --git a/CMakeLists.txt b/CMakeLists.txt index 5b5971036b88..1f8b24d17e24 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,652 +1,659 @@ # See www/CMake.html for instructions on how to build libcxx with CMake. #=============================================================================== # Setup Project #=============================================================================== cmake_minimum_required(VERSION 3.4.3) if(POLICY CMP0042) cmake_policy(SET CMP0042 NEW) # Set MACOSX_RPATH=YES by default endif() if(POLICY CMP0022) cmake_policy(SET CMP0022 NEW) # Required when interacting with LLVM and Clang endif() # Add path for custom modules set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules" ${CMAKE_MODULE_PATH} ) if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) project(libcxx CXX C) set(PACKAGE_NAME libcxx) set(PACKAGE_VERSION 5.0.0svn) set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}") set(PACKAGE_BUGREPORT "llvm-bugs@lists.llvm.org") # Find the LLVM sources and simulate LLVM CMake options. include(HandleOutOfTreeLLVM) endif() if (LIBCXX_STANDALONE_BUILD) include(FindPythonInterp) if( NOT PYTHONINTERP_FOUND ) message(WARNING "Failed to find python interpreter. " "The libc++ test suite will be disabled.") set(LLVM_INCLUDE_TESTS OFF) endif() endif() # Require out of source build. include(MacroEnsureOutOfSourceBuild) MACRO_ENSURE_OUT_OF_SOURCE_BUILD( "${PROJECT_NAME} requires an out of source build. Please create a separate build directory and run 'cmake /path/to/${PROJECT_NAME} [options]' there." ) if (MSVC) set(LIBCXX_TARGETING_MSVC ON) else() set(LIBCXX_TARGETING_MSVC OFF) endif() #=============================================================================== # Setup CMake Options #=============================================================================== include(CMakeDependentOption) include(HandleCompilerRT) # Basic options --------------------------------------------------------------- option(LIBCXX_ENABLE_ASSERTIONS "Enable assertions independent of build mode." OFF) option(LIBCXX_ENABLE_SHARED "Build libc++ as a shared library." ON) option(LIBCXX_ENABLE_STATIC "Build libc++ as a static library." ON) option(LIBCXX_ENABLE_EXPERIMENTAL_LIBRARY "Build libc++experimental.a" ON) set(ENABLE_FILESYSTEM_DEFAULT ${LIBCXX_ENABLE_EXPERIMENTAL_LIBRARY}) if (WIN32) set(ENABLE_FILESYSTEM_DEFAULT OFF) endif() option(LIBCXX_ENABLE_FILESYSTEM "Build filesystem as part of libc++experimental.a" ${ENABLE_FILESYSTEM_DEFAULT}) option(LIBCXX_INCLUDE_TESTS "Build the libc++ tests." ${LLVM_INCLUDE_TESTS}) # Benchmark options ----------------------------------------------------------- option(LIBCXX_INCLUDE_BENCHMARKS "Build the libc++ benchmarks and their dependancies" ON) set(LIBCXX_BENCHMARK_NATIVE_STDLIB "" CACHE STRING "Build the benchmarks against the specified native STL. The value must be one of libc++/libstdc++") set(LIBCXX_BENCHMARK_NATIVE_GCC_TOOLCHAIN "" CACHE STRING "Use alternate GCC toolchain when building the native benchmarks") if (LIBCXX_BENCHMARK_NATIVE_STDLIB) if (NOT (LIBCXX_BENCHMARK_NATIVE_STDLIB STREQUAL "libc++" OR LIBCXX_BENCHMARK_NATIVE_STDLIB STREQUAL "libstdc++")) message(FATAL_ERROR "Invalid value for LIBCXX_BENCHMARK_NATIVE_STDLIB: " "'${LIBCXX_BENCHMARK_NATIVE_STDLIB}'") endif() endif() option(LIBCXX_INCLUDE_DOCS "Build the libc++ documentation." ${LLVM_INCLUDE_DOCS}) set(LIBCXX_LIBDIR_SUFFIX "${LLVM_LIBDIR_SUFFIX}" CACHE STRING "Define suffix of library directory name (32/64)") option(LIBCXX_INSTALL_HEADERS "Install the libc++ headers." ON) option(LIBCXX_INSTALL_LIBRARY "Install the libc++ library." ON) option(LIBCXX_INSTALL_SUPPORT_HEADERS "Install libc++ support headers." ON) cmake_dependent_option(LIBCXX_INSTALL_EXPERIMENTAL_LIBRARY "Install libc++experimental.a" ON "LIBCXX_ENABLE_EXPERIMENTAL_LIBRARY;LIBCXX_INSTALL_LIBRARY" OFF) set(LIBCXX_ABI_VERSION 1 CACHE STRING "ABI version of libc++.") option(LIBCXX_ABI_UNSTABLE "Unstable ABI of libc++." OFF) option(LIBCXX_USE_COMPILER_RT "Use compiler-rt instead of libgcc" OFF) if (NOT LIBCXX_ENABLE_SHARED AND NOT LIBCXX_ENABLE_STATIC) message(FATAL_ERROR "libc++ must be built as either a shared or static library.") endif() # ABI Library options --------------------------------------------------------- set(LIBCXX_CXX_ABI "default" CACHE STRING "Specify C++ ABI library to use.") set(CXXABIS none default libcxxabi libcxxrt libstdc++ libsupc++ vcruntime) set_property(CACHE LIBCXX_CXX_ABI PROPERTY STRINGS ;${CXXABIS}) # Setup the default options if LIBCXX_CXX_ABI is not specified. if (LIBCXX_CXX_ABI STREQUAL "default") find_path( LIBCXX_LIBCXXABI_INCLUDES_INTERNAL cxxabi.h PATHS ${LLVM_MAIN_SRC_DIR}/projects/libcxxabi/include ${LLVM_MAIN_SRC_DIR}/runtimes/libcxxabi/include ${LLVM_MAIN_SRC_DIR}/../libcxxabi/include NO_DEFAULT_PATH ) if (LIBCXX_TARGETING_MSVC) # FIXME: Figure out how to configure the ABI library on Windows. set(LIBCXX_CXX_ABI_LIBNAME "vcruntime") elseif ((NOT LIBCXX_STANDALONE_BUILD OR HAVE_LIBCXXABI) AND IS_DIRECTORY "${LIBCXX_LIBCXXABI_INCLUDES_INTERNAL}") set(LIBCXX_CXX_ABI_LIBNAME "libcxxabi") set(LIBCXX_CXX_ABI_INCLUDE_PATHS "${LIBCXX_LIBCXXABI_INCLUDES_INTERNAL}") set(LIBCXX_CXX_ABI_INTREE 1) elseif (APPLE) set(LIBCXX_CXX_ABI_LIBNAME "libcxxabi") set(LIBCXX_CXX_ABI_SYSTEM 1) else() set(LIBCXX_CXX_ABI_LIBNAME "default") endif() else() set(LIBCXX_CXX_ABI_LIBNAME "${LIBCXX_CXX_ABI}") endif() # Use a static copy of the ABI library when linking libc++. This option # cannot be used with LIBCXX_ENABLE_ABI_LINKER_SCRIPT. option(LIBCXX_ENABLE_STATIC_ABI_LIBRARY "Statically link the ABI library" OFF) # Generate and install a linker script inplace of libc++.so. The linker script # will link libc++ to the correct ABI library. This option is on by default # on UNIX platforms other than Apple unless 'LIBCXX_ENABLE_STATIC_ABI_LIBRARY' # is on. This option is also disabled when the ABI library is not specified # or is specified to be "none". set(ENABLE_LINKER_SCRIPT_DEFAULT_VALUE OFF) if (LLVM_HAVE_LINK_VERSION_SCRIPT AND NOT LIBCXX_ENABLE_STATIC_ABI_LIBRARY AND NOT LIBCXX_CXX_ABI_LIBNAME STREQUAL "none" AND NOT LIBCXX_CXX_ABI_LIBNAME STREQUAL "default" AND PYTHONINTERP_FOUND AND LIBCXX_ENABLE_SHARED) set(ENABLE_LINKER_SCRIPT_DEFAULT_VALUE ON) endif() option(LIBCXX_ENABLE_ABI_LINKER_SCRIPT "Use and install a linker script for the given ABI library" ${ENABLE_LINKER_SCRIPT_DEFAULT_VALUE}) set(ENABLE_NEW_DELETE_DEFAULT ON) if (LIBCXXABI_ENABLE_NEW_DELETE_DEFINITIONS) # FIXME: This option should default to off. Unfortunatly GCC 4.9 fails to link # programs due to undefined references to new/delete in libc++abi so to work # around this libc++abi currently defaults LIBCXXABI_ENABLE_NEW_DELETE_DEFINITIONS # to ON. Once the GCC bug has been worked around this option should be changed # back to OFF. set(ENABLE_NEW_DELETE_DEFAULT ON) endif() option(LIBCXX_ENABLE_NEW_DELETE_DEFINITIONS "Build libc++ with definitions for operator new/delete. This option can be used to disable the definitions when libc++abi is expected to provide them" ${ENABLE_NEW_DELETE_DEFAULT}) # Build libc++abi with libunwind. We need this option to determine whether to # link with libunwind or libgcc_s while running the test cases. option(LIBCXXABI_USE_LLVM_UNWINDER "Build and use the LLVM unwinder." OFF) option(LIBCXXABI_ENABLE_STATIC_UNWINDER "Statically link the LLVM unwinder." OFF) # Target options -------------------------------------------------------------- option(LIBCXX_BUILD_32_BITS "Build 32 bit libc++." ${LLVM_BUILD_32_BITS}) set(LIBCXX_SYSROOT "" CACHE STRING "Use alternate sysroot.") set(LIBCXX_GCC_TOOLCHAIN "" CACHE STRING "Use alternate GCC toolchain.") # Feature options ------------------------------------------------------------- option(LIBCXX_ENABLE_EXCEPTIONS "Use exceptions." ON) option(LIBCXX_ENABLE_RTTI "Use run time type information." ON) option(LIBCXX_ENABLE_GLOBAL_FILESYSTEM_NAMESPACE "Build libc++ with support for the global filesystem namespace." ON) option(LIBCXX_ENABLE_STDIN "Build libc++ with support for stdin/std::cin." ON) option(LIBCXX_ENABLE_STDOUT "Build libc++ with support for stdout/std::cout." ON) option(LIBCXX_ENABLE_THREADS "Build libc++ with support for threads." ON) option(LIBCXX_ENABLE_THREAD_UNSAFE_C_FUNCTIONS "Build libc++ with support for thread-unsafe C functions" ON) option(LIBCXX_ENABLE_MONOTONIC_CLOCK "Build libc++ with support for a monotonic clock. This option may only be set to OFF when LIBCXX_ENABLE_THREADS=OFF." ON) option(LIBCXX_HAS_MUSL_LIBC "Build libc++ with support for the Musl C library" OFF) option(LIBCXX_HAS_PTHREAD_API "Ignore auto-detection and force use of pthread API" OFF) option(LIBCXX_HAS_EXTERNAL_THREAD_API "Build libc++ with an externalized threading API. This option may only be set to ON when LIBCXX_ENABLE_THREADS=ON." OFF) option(LIBCXX_BUILD_EXTERNAL_THREAD_LIBRARY "Build libc++ with an externalized threading library. This option may only be set to ON when LIBCXX_ENABLE_THREADS=ON" OFF) # Misc options ---------------------------------------------------------------- # FIXME: Turn -pedantic back ON. It is currently off because it warns # about #include_next which is used everywhere. option(LIBCXX_ENABLE_PEDANTIC "Compile with pedantic enabled." OFF) option(LIBCXX_ENABLE_WERROR "Fail and stop if a warning is triggered." OFF) option(LIBCXX_DISABLE_MACRO_CONFLICT_WARNINGS "Disable #warnings about conflicting macros." OFF) option(LIBCXX_GENERATE_COVERAGE "Enable generating code coverage." OFF) set(LIBCXX_COVERAGE_LIBRARY "" CACHE STRING "The Profile-rt library used to build with code coverage") # Don't allow a user to accidentally overwrite the system libc++ installation on Darwin. # If the user specifies -DCMAKE_INSTALL_PREFIX=/usr the install rules for libc++ # will not be generated and a warning will be issued. option(LIBCXX_OVERRIDE_DARWIN_INSTALL "Enable overwriting darwins libc++ installation." OFF) mark_as_advanced(LIBCXX_OVERRIDE_DARWIN_INSTALL) # Don't show this option by default. if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin" AND NOT LIBCXX_OVERRIDE_DARWIN_INSTALL) if ("${CMAKE_INSTALL_PREFIX}" STREQUAL "/usr") message(WARNING "Disabling libc++ install rules because installation would " "overwrite the systems installation. Configure with " "-DLIBCXX_OVERRIDE_DARWIN_INSTALL=ON to suppress this behaviour.") mark_as_advanced(CLEAR LIBCXX_OVERRIDE_DARWIN_INSTALL) # Show the override option. set(LIBCXX_INSTALL_HEADERS OFF) set(LIBCXX_INSTALL_LIBRARY OFF) endif() endif() set(LIBCXX_CONFIGURE_IDE_DEFAULT OFF) if (XCODE OR MSVC_IDE) set(LIBCXX_CONFIGURE_IDE_DEFAULT ON) endif() option(LIBCXX_CONFIGURE_IDE "Configure libcxx for use within an IDE" ${LIBCXX_CONFIGURE_IDE_DEFAULT}) #=============================================================================== # Check option configurations #=============================================================================== if (LIBCXX_ENABLE_FILESYSTEM AND NOT LIBCXX_ENABLE_EXPERIMENTAL_LIBRARY) message(FATAL_ERROR "LIBCXX_ENABLE_FILESYSTEM cannot be turned on when LIBCXX_ENABLE_EXPERIMENTAL_LIBRARY=OFF") endif() # Ensure LIBCXX_ENABLE_MONOTONIC_CLOCK is set to ON only when # LIBCXX_ENABLE_THREADS is on. if(LIBCXX_ENABLE_THREADS AND NOT LIBCXX_ENABLE_MONOTONIC_CLOCK) message(FATAL_ERROR "LIBCXX_ENABLE_MONOTONIC_CLOCK can only be set to OFF" " when LIBCXX_ENABLE_THREADS is also set to OFF.") endif() if(NOT LIBCXX_ENABLE_THREADS) if(LIBCXX_HAS_PTHREAD_API) message(FATAL_ERROR "LIBCXX_HAS_PTHREAD_API can only be set to ON" " when LIBCXX_ENABLE_THREADS is also set to ON.") endif() if(LIBCXX_HAS_EXTERNAL_THREAD_API) message(FATAL_ERROR "LIBCXX_HAS_EXTERNAL_THREAD_API can only be set to ON" " when LIBCXX_ENABLE_THREADS is also set to ON.") endif() if (LIBCXX_BUILD_EXTERNAL_THREAD_LIBRARY) message(FATAL_ERROR "LIBCXX_BUILD_EXTERNAL_THREAD_LIBRARY can only be set " "to ON when LIBCXX_ENABLE_THREADS is also set to ON.") endif() endif() if (LIBCXX_HAS_EXTERNAL_THREAD_API) if (LIBCXX_BUILD_EXTERNAL_THREAD_LIBRARY) message(FATAL_ERROR "The options LIBCXX_BUILD_EXTERNAL_THREAD_LIBRARY and " "LIBCXX_HAS_EXTERNAL_THREAD_API cannot both be ON at " "the same time") endif() if (LIBCXX_HAS_PTHREAD_API) message(FATAL_ERROR "The options LIBCXX_HAS_EXTERNAL_THREAD_API" "and LIBCXX_HAS_PTHREAD_API cannot be both" "set to ON at the same time.") endif() endif() # Ensure LLVM_USE_SANITIZER is not specified when LIBCXX_GENERATE_COVERAGE # is ON. if (LLVM_USE_SANITIZER AND LIBCXX_GENERATE_COVERAGE) message(FATAL_ERROR "LLVM_USE_SANITIZER cannot be used with LIBCXX_GENERATE_COVERAGE") endif() # Set LIBCXX_BUILD_32_BITS to (LIBCXX_BUILD_32_BITS OR LLVM_BUILD_32_BITS) # and check that we can build with 32 bits if requested. if (CMAKE_SIZEOF_VOID_P EQUAL 8 AND NOT WIN32) if (LIBCXX_BUILD_32_BITS AND NOT LLVM_BUILD_32_BITS) # Don't duplicate the output from LLVM message(STATUS "Building 32 bits executables and libraries.") endif() elseif(LIBCXX_BUILD_32_BITS) message(FATAL_ERROR "LIBCXX_BUILD_32_BITS=ON is not supported on this platform.") endif() # Check that this option is not enabled on Apple and emit a usage warning. if (LIBCXX_ENABLE_STATIC_ABI_LIBRARY) if (APPLE) message(FATAL_ERROR "LIBCXX_ENABLE_STATIC_ABI_LIBRARY is not supported on OS X") else() message(WARNING "LIBCXX_ENABLE_STATIC_ABI_LIBRARY is an experimental option") endif() if (LIBCXX_ENABLE_STATIC AND NOT PYTHONINTERP_FOUND) message(FATAL_ERROR "LIBCXX_ENABLE_STATIC_ABI_LIBRARY requires python but it was not found.") endif() endif() if (LIBCXX_ENABLE_ABI_LINKER_SCRIPT) if (APPLE) message(FATAL_ERROR "LIBCXX_ENABLE_ABI_LINKER_SCRIPT cannot be used on APPLE targets") endif() if (NOT PYTHONINTERP_FOUND) message(FATAL_ERROR "LIBCXX_ENABLE_ABI_LINKER_SCRIPT requires python but it was not found.") endif() if (NOT LIBCXX_ENABLE_SHARED) message(FATAL_ERROR "LIBCXX_ENABLE_ABI_LINKER_SCRIPT is only available for shared library builds.") endif() endif() if (LIBCXX_ENABLE_STATIC_ABI_LIBRARY AND LIBCXX_ENABLE_ABI_LINKER_SCRIPT) message(FATAL_ERROR "Conflicting options given. LIBCXX_ENABLE_STATIC_ABI_LIBRARY cannot be specified with LIBCXX_ENABLE_ABI_LINKER_SCRIPT") endif() if (LIBCXX_HAS_MUSL_LIBC AND NOT LIBCXX_INSTALL_SUPPORT_HEADERS) message(FATAL_ERROR "LIBCXX_INSTALL_SUPPORT_HEADERS can not be turned off" "when building for Musl with LIBCXX_HAS_MUSL_LIBC.") endif() #=============================================================================== # Configure System #=============================================================================== set(LIBCXX_COMPILER ${CMAKE_CXX_COMPILER}) set(LIBCXX_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) set(LIBCXX_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}) set(LIBCXX_BINARY_INCLUDE_DIR "${LIBCXX_BINARY_DIR}/include/c++build") if (LLVM_LIBRARY_OUTPUT_INTDIR) set(LIBCXX_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}) else() set(LIBCXX_LIBRARY_DIR ${CMAKE_BINARY_DIR}/lib${LIBCXX_LIBDIR_SUFFIX}) endif() file(MAKE_DIRECTORY "${LIBCXX_BINARY_INCLUDE_DIR}") +set(LIBCXX_INSTALL_PREFIX "" CACHE STRING + "Define libc++ destination prefix.") + +if (NOT LIBCXX_INSTALL_PREFIX MATCHES "^$|.*/") + message(FATAL_ERROR "LIBCXX_INSTALL_PREFIX has to end with \"/\".") +endif() + set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${LIBCXX_LIBRARY_DIR}) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${LIBCXX_LIBRARY_DIR}) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${LIBCXX_LIBRARY_DIR}) # Declare libc++ configuration variables. # They are intended for use as follows: # LIBCXX_CXX_FLAGS: General flags for both the compiler and linker. # LIBCXX_COMPILE_FLAGS: Compile only flags. # LIBCXX_LINK_FLAGS: Linker only flags. # LIBCXX_LIBRARIES: libraries libc++ is linked to. # LIBCXX_INTERFACE_LIBRARIES: Libraries that must be linked when using libc++ # These libraries are exposed in the linker script. set(LIBCXX_COMPILE_FLAGS "") set(LIBCXX_LINK_FLAGS "") set(LIBCXX_LIBRARIES "") set(LIBCXX_INTERFACE_LIBRARIES "") # Include macros for adding and removing libc++ flags. include(HandleLibcxxFlags) # Target flags ================================================================ # These flags get added to CMAKE_CXX_FLAGS and CMAKE_C_FLAGS so that # 'config-ix' use them during feature checks. It also adds them to both # 'LIBCXX_COMPILE_FLAGS' and 'LIBCXX_LINK_FLAGS' add_target_flags_if(LIBCXX_BUILD_32_BITS "-m32") add_target_flags_if(LIBCXX_TARGET_TRIPLE "--target=${LIBCXX_TARGET_TRIPLE}") add_target_flags_if(LIBCXX_SYSROOT "--sysroot=${LIBCXX_SYSROOT}") add_target_flags_if(LIBCXX_GCC_TOOLCHAIN "--gcc-toolchain=${LIBCXX_GCC_TOOLCHAIN}") if (LIBCXX_TARGET_TRIPLE) set(TARGET_TRIPLE "${LIBCXX_TARGET_TRIPLE}") endif() # Configure compiler. include(config-ix) if (LIBCXX_USE_COMPILER_RT) list(APPEND LIBCXX_LINK_FLAGS "-rtlib=compiler-rt") endif() # Configure coverage options. if (LIBCXX_GENERATE_COVERAGE) include(CodeCoverage) set(CMAKE_BUILD_TYPE "COVERAGE" CACHE STRING "" FORCE) endif() string(TOUPPER "${CMAKE_BUILD_TYPE}" uppercase_CMAKE_BUILD_TYPE) if (uppercase_CMAKE_BUILD_TYPE STREQUAL "DEBUG") set(LIBCXX_DEBUG_BUILD ON) else() set(LIBCXX_DEBUG_BUILD OFF) endif() #=============================================================================== # Setup Compiler Flags #=============================================================================== include(HandleLibCXXABI) # Setup the ABI library flags if (NOT LIBCXX_STANDALONE_BUILD) # Remove flags that may have snuck in. remove_flags(-DNDEBUG -UNDEBUG -D_DEBUG -lc++abi) endif() remove_flags(-stdlib=libc++ -stdlib=libstdc++) # FIXME: Remove all debug flags and flags that change which Windows # default libraries are linked. Currently we only support linking the # non-debug DLLs remove_flags("/D_DEBUG" "/MTd" "/MDd" "/MT" "/Md") # FIXME(EricWF): See the FIXME on LIBCXX_ENABLE_PEDANTIC. # Remove the -pedantic flag and -Wno-pedantic and -pedantic-errors # so they don't get transformed into -Wno and -errors respectively. remove_flags(-Wno-pedantic -pedantic-errors -pedantic) # Required flags ============================================================== set(LIBCXX_STANDARD_VER c++11 CACHE INTERNAL "internal option to change build dialect") if (LIBCXX_HAS_MUSL_LIBC) # musl's pthread implementations uses volatile types in their structs which is # not a constexpr in C++11 but is in C++14, so we use C++14 with musl. set(LIBCXX_STANDARD_VER c++14 CACHE INTERNAL "internal option to change build dialect") endif() add_compile_flags_if_supported(-std=${LIBCXX_STANDARD_VER}) mangle_name("LIBCXX_SUPPORTS_STD_EQ_${LIBCXX_STANDARD_VER}_FLAG" SUPPORTS_DIALECT_NAME) if(NOT ${SUPPORTS_DIALECT_NAME}) if(NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC" AND NOT "${CMAKE_CXX_SIMULATE_ID}" STREQUAL "MSVC") message(FATAL_ERROR "C++11 or greater is required but the compiler does not support ${LIBCXX_STANDARD_VER}") endif() endif() # On all systems the system c++ standard library headers need to be excluded. # MSVC only has -X, which disables all default includes; including the crt. # Thus, we do nothing and hope we don't accidentally include any of the C++ # headers add_compile_flags_if_supported(-nostdinc++) # Hide all inline function definitions which have not explicitly been marked # visible. This prevents new definitions for inline functions from appearing in # the dylib when get ODR used by another function. add_compile_flags_if_supported(-fvisibility-inlines-hidden) if (LIBCXX_CONFIGURE_IDE) # This simply allows IDE to process add_compile_flags_if_supported(-fcoroutines-ts) endif() # Let the library headers know they are currently being used to build the # library. add_definitions(-D_LIBCPP_BUILDING_LIBRARY) if (NOT LIBCXX_ENABLE_NEW_DELETE_DEFINITIONS) add_definitions(-D_LIBCPP_DISABLE_NEW_DELETE_DEFINITIONS) endif() # Warning flags =============================================================== add_definitions(-D_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) add_compile_flags_if_supported( -Wall -Wextra -W -Wwrite-strings -Wno-unused-parameter -Wno-long-long -Werror=return-type) if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") add_compile_flags_if_supported( -Wno-user-defined-literals -Wno-covered-switch-default) elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") add_compile_flags_if_supported( -Wno-literal-suffix -Wno-c++14-compat -Wno-noexcept-type) endif() if (LIBCXX_ENABLE_WERROR) add_compile_flags_if_supported(-Werror) add_compile_flags_if_supported(-WX) else() # TODO(EricWF) Remove this. We shouldn't be suppressing errors when -Werror is # added elsewhere. add_compile_flags_if_supported(-Wno-error) endif() if (LIBCXX_ENABLE_PEDANTIC) add_compile_flags_if_supported(-pedantic) endif() if (LIBCXX_DISABLE_MACRO_CONFLICT_WARNINGS) add_definitions(-D_LIBCPP_DISABLE_MACRO_CONFLICT_WARNINGS) endif() # Exception flags ============================================================= if (LIBCXX_ENABLE_EXCEPTIONS) # Catches C++ exceptions only and tells the compiler to assume that extern C # functions never throw a C++ exception. add_compile_flags_if_supported(-EHsc) else() add_definitions(-D_LIBCPP_NO_EXCEPTIONS) add_compile_flags_if_supported(-EHs- -EHa-) add_compile_flags_if_supported(-fno-exceptions) endif() # RTTI flags ================================================================== if (NOT LIBCXX_ENABLE_RTTI) add_definitions(-D_LIBCPP_NO_RTTI) add_compile_flags_if_supported(-GR-) add_compile_flags_if_supported(-fno-rtti) endif() # Threading flags ============================================================= if (LIBCXX_BUILD_EXTERNAL_THREAD_LIBRARY AND LIBCXX_ENABLE_SHARED) # Need to allow unresolved symbols if this is to work with shared library builds if (APPLE) add_link_flags("-undefined dynamic_lookup") else() # Relax this restriction from HandleLLVMOptions string(REPLACE "-Wl,-z,defs" "" CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}") endif() endif() # Assertion flags ============================================================= define_if(LIBCXX_ENABLE_ASSERTIONS -UNDEBUG) define_if_not(LIBCXX_ENABLE_ASSERTIONS -DNDEBUG) define_if(LIBCXX_ENABLE_ASSERTIONS -D_LIBCPP_DEBUG=0) define_if(LIBCXX_DEBUG_BUILD -D_DEBUG) if (LIBCXX_ENABLE_ASSERTIONS AND NOT LIBCXX_DEBUG_BUILD) # MSVC doesn't like _DEBUG on release builds. See PR 4379. define_if_not(LIBCXX_TARGETING_MSVC -D_DEBUG) endif() # Modules flags =============================================================== # FIXME The libc++ sources are fundamentally non-modular. They need special # versions of the headers in order to provide C++03 and legacy ABI definitions. # NOTE: The public headers can be used with modules in all other contexts. if (LLVM_ENABLE_MODULES) # Ignore that the rest of the modules flags are now unused. add_compile_flags_if_supported(-Wno-unused-command-line-argument) add_compile_flags(-fno-modules) endif() # Sanitizer flags ============================================================= # Configure for sanitizers. If LIBCXX_STANDALONE_BUILD then we have to do # the flag translation ourselves. Othewise LLVM's CMakeList.txt will handle it. if (LIBCXX_STANDALONE_BUILD) set(LLVM_USE_SANITIZER "" CACHE STRING "Define the sanitizer used to build the library and tests") # NOTE: LLVM_USE_SANITIZER checks for a UNIX like system instead of MSVC. # But we don't have LLVM_ON_UNIX so checking for MSVC is the best we can do. if (LLVM_USE_SANITIZER AND NOT MSVC) add_flags_if_supported("-fno-omit-frame-pointer") add_flags_if_supported("-gline-tables-only") if (NOT uppercase_CMAKE_BUILD_TYPE STREQUAL "DEBUG" AND NOT uppercase_CMAKE_BUILD_TYPE STREQUAL "RELWITHDEBINFO") add_flags_if_supported("-gline-tables-only") endif() if (LLVM_USE_SANITIZER STREQUAL "Address") add_flags("-fsanitize=address") elseif (LLVM_USE_SANITIZER MATCHES "Memory(WithOrigins)?") add_flags(-fsanitize=memory) if (LLVM_USE_SANITIZER STREQUAL "MemoryWithOrigins") add_flags("-fsanitize-memory-track-origins") endif() elseif (LLVM_USE_SANITIZER STREQUAL "Undefined") add_flags("-fsanitize=undefined -fno-sanitize=vptr,function -fno-sanitize-recover=all") elseif (LLVM_USE_SANITIZER STREQUAL "Thread") add_flags(-fsanitize=thread) else() message(WARNING "Unsupported value of LLVM_USE_SANITIZER: ${LLVM_USE_SANITIZER}") endif() elseif(LLVM_USE_SANITIZER AND MSVC) message(WARNING "LLVM_USE_SANITIZER is not supported on this platform.") endif() endif() # Configuration file flags ===================================================== if (NOT LIBCXX_ABI_VERSION EQUAL "1") config_define(${LIBCXX_ABI_VERSION} _LIBCPP_ABI_VERSION) endif() config_define_if(LIBCXX_ABI_UNSTABLE _LIBCPP_ABI_UNSTABLE) config_define_if_not(LIBCXX_ENABLE_GLOBAL_FILESYSTEM_NAMESPACE _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE) config_define_if_not(LIBCXX_ENABLE_STDIN _LIBCPP_HAS_NO_STDIN) config_define_if_not(LIBCXX_ENABLE_STDOUT _LIBCPP_HAS_NO_STDOUT) config_define_if_not(LIBCXX_ENABLE_THREADS _LIBCPP_HAS_NO_THREADS) config_define_if_not(LIBCXX_ENABLE_MONOTONIC_CLOCK _LIBCPP_HAS_NO_MONOTONIC_CLOCK) config_define_if_not(LIBCXX_ENABLE_THREAD_UNSAFE_C_FUNCTIONS _LIBCPP_HAS_NO_THREAD_UNSAFE_C_FUNCTIONS) config_define_if(LIBCXX_HAS_PTHREAD_API _LIBCPP_HAS_THREAD_API_PTHREAD) config_define_if(LIBCXX_HAS_EXTERNAL_THREAD_API _LIBCPP_HAS_THREAD_API_EXTERNAL) config_define_if(LIBCXX_BUILD_EXTERNAL_THREAD_LIBRARY _LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) config_define_if(LIBCXX_HAS_MUSL_LIBC _LIBCPP_HAS_MUSL_LIBC) # By default libc++ on Windows expects to use a shared library, which requires # the headers to use DLL import/export semantics. However when building a # static library only we modify the headers to disable DLL import/export. if (DEFINED WIN32 AND LIBCXX_ENABLE_STATIC AND NOT LIBCXX_ENABLE_SHARED) message(STATUS "Generating custom __config for non-DLL Windows build") config_define(ON _LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS) endif() if (LIBCXX_NEEDS_SITE_CONFIG) configure_file("include/__config_site.in" "${LIBCXX_BINARY_DIR}/__config_site" @ONLY) # Provide the config definitions by included the generated __config_site # file at compile time. if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC" OR "${CMAKE_CXX_SIMULATE_ID}" STREQUAL "MSVC") add_compile_flags("/FI\"${LIBCXX_BINARY_DIR}/__config_site\"") else() add_compile_flags("-include ${LIBCXX_BINARY_DIR}/__config_site") endif() endif() #=============================================================================== # Setup Source Code And Tests #=============================================================================== include_directories(include) add_subdirectory(include) add_subdirectory(lib) if (LIBCXX_INCLUDE_BENCHMARKS) add_subdirectory(benchmarks) endif() # Create the lit.site.cfg file even when LIBCXX_INCLUDE_TESTS is OFF or # LLVM_FOUND is OFF. This allows users to run the tests manually using # LIT without requiring a full LLVM checkout. # # However, since some submission systems strip test/ subdirectories, check for # it before adding it. if(IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/test") add_subdirectory(test) endif() if (LIBCXX_INCLUDE_TESTS) add_subdirectory(lib/abi) endif() if (LIBCXX_INCLUDE_DOCS) add_subdirectory(docs) endif() diff --git a/cmake/Modules/HandleLibCXXABI.cmake b/cmake/Modules/HandleLibCXXABI.cmake index b404e36c1480..b1f6bee8f945 100644 --- a/cmake/Modules/HandleLibCXXABI.cmake +++ b/cmake/Modules/HandleLibCXXABI.cmake @@ -1,127 +1,127 @@ #=============================================================================== # Add an ABI library if appropriate #=============================================================================== # # _setup_abi: Set up the build to use an ABI library # # Parameters: # abidefines: A list of defines needed to compile libc++ with the ABI library # abilib : The ABI library to link against. # abifiles : A list of files (which may be relative paths) to copy into the # libc++ build tree for the build. These files will be copied # twice: once into include/, so the libc++ build itself can find # them, and once into include/c++/v1, so that a clang built into # the same build area will find them. These files will also be # installed alongside the libc++ headers. # abidirs : A list of relative paths to create under an include directory # in the libc++ build directory. # macro(setup_abi_lib abidefines abilib abifiles abidirs) list(APPEND LIBCXX_COMPILE_FLAGS ${abidefines}) set(LIBCXX_CXX_ABI_INCLUDE_PATHS "${LIBCXX_CXX_ABI_INCLUDE_PATHS}" CACHE PATH "Paths to C++ ABI header directories separated by ';'." FORCE ) set(LIBCXX_CXX_ABI_LIBRARY_PATH "${LIBCXX_CXX_ABI_LIBRARY_PATH}" CACHE PATH "Paths to C++ ABI library directory" ) set(LIBCXX_CXX_ABI_LIBRARY ${abilib}) set(LIBCXX_ABILIB_FILES ${abifiles}) # The place in the build tree where we store out-of-source headers. file(MAKE_DIRECTORY "${LIBCXX_BUILD_HEADERS_ROOT}") file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/include/c++/v1") foreach(_d ${abidirs}) file(MAKE_DIRECTORY "${LIBCXX_BINARY_INCLUDE_DIR}/${_d}") file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/include/c++/v1/${_d}") endforeach() foreach(fpath ${LIBCXX_ABILIB_FILES}) set(found FALSE) foreach(incpath ${LIBCXX_CXX_ABI_INCLUDE_PATHS}) if (EXISTS "${incpath}/${fpath}") set(found TRUE) get_filename_component(dstdir ${fpath} PATH) get_filename_component(ifile ${fpath} NAME) file(COPY "${incpath}/${fpath}" DESTINATION "${LIBCXX_BINARY_INCLUDE_DIR}/${dstdir}" ) file(COPY "${incpath}/${fpath}" DESTINATION "${CMAKE_BINARY_DIR}/include/c++/v1/${dstdir}" ) if (LIBCXX_INSTALL_HEADERS) install(FILES "${LIBCXX_BINARY_INCLUDE_DIR}/${fpath}" - DESTINATION include/c++/v1/${dstdir} + DESTINATION ${LIBCXX_INSTALL_PREFIX}include/c++/v1/${dstdir} COMPONENT libcxx PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ ) endif() list(APPEND abilib_headers "${LIBCXX_BINARY_INCLUDE_DIR}/${fpath}") endif() endforeach() if (NOT found) message(WARNING "Failed to find ${fpath}") endif() endforeach() include_directories("${LIBCXX_BINARY_INCLUDE_DIR}") endmacro() # Configure based on the selected ABI library. if ("${LIBCXX_CXX_ABI_LIBNAME}" STREQUAL "libstdc++" OR "${LIBCXX_CXX_ABI_LIBNAME}" STREQUAL "libsupc++") set(_LIBSUPCXX_INCLUDE_FILES cxxabi.h bits/c++config.h bits/os_defines.h bits/cpu_defines.h bits/cxxabi_tweaks.h bits/cxxabi_forced.h ) if ("${LIBCXX_CXX_ABI_LIBNAME}" STREQUAL "libstdc++") set(_LIBSUPCXX_DEFINES "-DLIBSTDCXX") set(_LIBSUPCXX_LIBNAME stdc++) else() set(_LIBSUPCXX_DEFINES "") set(_LIBSUPCXX_LIBNAME supc++) endif() setup_abi_lib( "-D__GLIBCXX__ ${_LIBSUPCXX_DEFINES}" "${_LIBSUPCXX_LIBNAME}" "${_LIBSUPCXX_INCLUDE_FILES}" "bits" ) elseif ("${LIBCXX_CXX_ABI_LIBNAME}" STREQUAL "libcxxabi") if (LIBCXX_CXX_ABI_INTREE) # Link against just-built "cxxabi" target. if (LIBCXX_ENABLE_STATIC_ABI_LIBRARY) set(CXXABI_LIBNAME cxxabi_static) else() set(CXXABI_LIBNAME cxxabi_shared) endif() set(LIBCXX_LIBCPPABI_VERSION "2" PARENT_SCOPE) else() # Assume c++abi is installed in the system, rely on -lc++abi link flag. set(CXXABI_LIBNAME "c++abi") endif() set(HEADERS "cxxabi.h;__cxxabi_config.h") if (LIBCXX_CXX_ABI_SYSTEM) set(HEADERS "") endif() setup_abi_lib("-DLIBCXX_BUILDING_LIBCXXABI" ${CXXABI_LIBNAME} "${HEADERS}" "") elseif ("${LIBCXX_CXX_ABI_LIBNAME}" STREQUAL "libcxxrt") setup_abi_lib("-DLIBCXXRT" "cxxrt" "cxxabi.h;unwind.h;unwind-arm.h;unwind-itanium.h" "" ) elseif ("${LIBCXX_CXX_ABI_LIBNAME}" STREQUAL "vcruntime") # Nothing TODO elseif ("${LIBCXX_CXX_ABI_LIBNAME}" STREQUAL "none") list(APPEND LIBCXX_COMPILE_FLAGS "-D_LIBCPP_BUILDING_HAS_NO_ABI_LIBRARY") elseif ("${LIBCXX_CXX_ABI_LIBNAME}" STREQUAL "default") # Nothing TODO else() message(FATAL_ERROR "Unsupported c++ abi: '${LIBCXX_CXX_ABI_LIBNAME}'. \ Currently libstdc++, libsupc++, libcxxabi, libcxxrt, default and none are supported for c++ abi." ) endif () diff --git a/docs/BuildingLibcxx.rst b/docs/BuildingLibcxx.rst index c7b5e96422f0..81a7c2341473 100644 --- a/docs/BuildingLibcxx.rst +++ b/docs/BuildingLibcxx.rst @@ -1,497 +1,502 @@ .. _BuildingLibcxx: =============== Building libc++ =============== .. contents:: :local: .. _build instructions: Getting Started =============== On Mac OS 10.7 (Lion) and later, the easiest way to get this library is to install Xcode 4.2 or later. However if you want to install tip-of-trunk from here (getting the bleeding edge), read on. The basic steps needed to build libc++ are: #. Checkout LLVM: * ``cd where-you-want-llvm-to-live`` * ``svn co http://llvm.org/svn/llvm-project/llvm/trunk llvm`` #. Checkout libc++: * ``cd where-you-want-llvm-to-live`` * ``cd llvm/projects`` * ``svn co http://llvm.org/svn/llvm-project/libcxx/trunk libcxx`` #. Checkout libc++abi: * ``cd where-you-want-llvm-to-live`` * ``cd llvm/projects`` * ``svn co http://llvm.org/svn/llvm-project/libcxxabi/trunk libcxxabi`` #. Configure and build libc++ with libc++abi: CMake is the only supported configuration system. Clang is the preferred compiler when building and using libc++. * ``cd where you want to build llvm`` * ``mkdir build`` * ``cd build`` * ``cmake -G [options] `` For more information about configuring libc++ see :ref:`CMake Options`. * ``make cxx`` --- will build libc++ and libc++abi. * ``make check-cxx check-cxxabi`` --- will run the test suites. Shared libraries for libc++ and libc++ abi should now be present in llvm/build/lib. See :ref:`using an alternate libc++ installation ` #. **Optional**: Install libc++ and libc++abi If your system already provides a libc++ installation it is important to be careful not to replace it. Remember Use the CMake option ``CMAKE_INSTALL_PREFIX`` to select a safe place to install libc++. * ``make install-cxx install-cxxabi`` --- Will install the libraries and the headers .. warning:: * Replacing your systems libc++ installation could render the system non-functional. * Mac OS X will not boot without a valid copy of ``libc++.1.dylib`` in ``/usr/lib``. The instructions are for building libc++ on FreeBSD, Linux, or Mac using `libc++abi`_ as the C++ ABI library. On Linux, it is also possible to use :ref:`libsupc++ ` or libcxxrt. It is sometimes beneficial to build outside of the LLVM tree. An out-of-tree build would look like this: .. code-block:: bash $ cd where-you-want-libcxx-to-live $ # Check out llvm, libc++ and libc++abi. $ ``svn co http://llvm.org/svn/llvm-project/llvm/trunk llvm`` $ ``svn co http://llvm.org/svn/llvm-project/libcxx/trunk libcxx`` $ ``svn co http://llvm.org/svn/llvm-project/libcxxabi/trunk libcxxabi`` $ cd where-you-want-to-build $ mkdir build && cd build $ export CC=clang CXX=clang++ $ cmake -DLLVM_PATH=path/to/llvm \ -DLIBCXX_CXX_ABI=libcxxabi \ -DLIBCXX_CXX_ABI_INCLUDE_PATHS=path/to/libcxxabi/include \ path/to/libcxx $ make $ make check-libcxx # optional Experimental Support for Windows -------------------------------- The Windows support requires building with clang-cl as cl does not support one required extension: `#include_next`. Furthermore, VS 2015 or newer (19.00) is required. In the case of clang-cl, we need to specify the "MS Compatibility Version" as it defaults to 2014 (18.00). CMake + Visual Studio ~~~~~~~~~~~~~~~~~~~~~ Building with Visual Studio currently does not permit running tests. However, it is the simplest way to build. .. code-block:: batch > cmake -G "Visual Studio 14 2015" ^ -T "LLVM-vs2014" ^ -DLIBCXX_ENABLE_SHARED=YES ^ -DLIBCXX_ENABLE_STATIC=NO ^ -DLIBCXX_ENABLE_EXPERIMENTAL_LIBRARY=NO ^ \path\to\libcxx > cmake --build . CMake + ninja ~~~~~~~~~~~~~ Building with ninja is required for development to enable tests. Unfortunately, doing so requires additional configuration as we cannot just specify a toolset. .. code-block:: batch > cmake -G Ninja ^ -DCMAKE_MAKE_PROGRAM=/path/to/ninja ^ -DCMAKE_SYSTEM_NAME=Windows ^ -DCMAKE_C_COMPILER=clang-cl ^ -DCMAKE_C_FLAGS="-fms-compatibility-version=19.00 --target=i686--windows" ^ -DCMAKE_CXX_COMPILER=clang-c ^ -DCMAKE_CXX_FLAGS="-fms-compatibility-version=19.00 --target=i686--windows" ^ -DLLVM_PATH=/path/to/llvm/tree ^ -DLIBCXX_ENABLE_SHARED=YES ^ -DLIBCXX_ENABLE_STATIC=NO ^ -DLIBCXX_ENABLE_EXPERIMENTAL_LIBRARY=NO ^ \path\to\libcxx > /path/to/ninja cxx > /path/to/ninja check-cxx Note that the paths specified with backward slashes must use the `\\` as the directory separator as clang-cl may otherwise parse the path as an argument. .. _`libc++abi`: http://libcxxabi.llvm.org/ .. _CMake Options: CMake Options ============= Here are some of the CMake variables that are used often, along with a brief explanation and LLVM-specific notes. For full documentation, check the CMake docs or execute ``cmake --help-variable VARIABLE_NAME``. **CMAKE_BUILD_TYPE**:STRING Sets the build type for ``make`` based generators. Possible values are Release, Debug, RelWithDebInfo and MinSizeRel. On systems like Visual Studio the user sets the build type with the IDE settings. **CMAKE_INSTALL_PREFIX**:PATH Path where LLVM will be installed if "make install" is invoked or the "INSTALL" target is built. **CMAKE_CXX_COMPILER**:STRING The C++ compiler to use when building and testing libc++. .. _libcxx-specific options: libc++ specific options ----------------------- .. option:: LIBCXX_INSTALL_LIBRARY:BOOL **Default**: ``ON`` Toggle the installation of the library portion of libc++. .. option:: LIBCXX_INSTALL_HEADERS:BOOL **Default**: ``ON`` Toggle the installation of the libc++ headers. .. option:: LIBCXX_ENABLE_ASSERTIONS:BOOL **Default**: ``ON`` Build libc++ with assertions enabled. .. option:: LIBCXX_BUILD_32_BITS:BOOL **Default**: ``OFF`` Build libc++ as a 32 bit library. Also see `LLVM_BUILD_32_BITS`. .. option:: LIBCXX_ENABLE_SHARED:BOOL **Default**: ``ON`` Build libc++ as a shared library. Either `LIBCXX_ENABLE_SHARED` or `LIBCXX_ENABLE_STATIC` has to be enabled. .. option:: LIBCXX_ENABLE_STATIC:BOOL **Default**: ``ON`` Build libc++ as a static library. Either `LIBCXX_ENABLE_SHARED` or `LIBCXX_ENABLE_STATIC` has to be enabled. .. option:: LIBCXX_LIBDIR_SUFFIX:STRING Extra suffix to append to the directory where libraries are to be installed. This option overrides `LLVM_LIBDIR_SUFFIX`. +.. option:: LIBCXX_INSTALL_PREFIX:STRING + + **Default**: ``""`` + + Define libc++ destination prefix. .. _libc++experimental options: libc++experimental Specific Options ------------------------------------ .. option:: LIBCXX_ENABLE_EXPERIMENTAL_LIBRARY:BOOL **Default**: ``ON`` Build and test libc++experimental.a. .. option:: LIBCXX_INSTALL_EXPERIMENTAL_LIBRARY:BOOL **Default**: ``LIBCXX_ENABLE_EXPERIMENTAL_LIBRARY AND LIBCXX_INSTALL_LIBRARY`` Install libc++experimental.a alongside libc++. .. option:: LIBCXX_ENABLE_FILESYSTEM:BOOL **Default**: ``LIBCXX_ENABLE_EXPERIMENTAL_LIBRARY`` Build filesystem as part of libc++experimental.a. This allows filesystem to be disabled without turning off the entire experimental library. .. _ABI Library Specific Options: ABI Library Specific Options ---------------------------- .. option:: LIBCXX_CXX_ABI:STRING **Values**: ``none``, ``libcxxabi``, ``libcxxrt``, ``libstdc++``, ``libsupc++``. Select the ABI library to build libc++ against. .. option:: LIBCXX_CXX_ABI_INCLUDE_PATHS:PATHS Provide additional search paths for the ABI library headers. .. option:: LIBCXX_CXX_ABI_LIBRARY_PATH:PATH Provide the path to the ABI library that libc++ should link against. .. option:: LIBCXX_ENABLE_STATIC_ABI_LIBRARY:BOOL **Default**: ``OFF`` If this option is enabled, libc++ will try and link the selected ABI library statically. .. option:: LIBCXX_ENABLE_ABI_LINKER_SCRIPT:BOOL **Default**: ``ON`` by default on UNIX platforms other than Apple unless 'LIBCXX_ENABLE_STATIC_ABI_LIBRARY' is ON. Otherwise the default value is ``OFF``. This option generate and installs a linker script as ``libc++.so`` which links the correct ABI library. .. option:: LIBCXXABI_USE_LLVM_UNWINDER:BOOL **Default**: ``OFF`` Build and use the LLVM unwinder. Note: This option can only be used when libc++abi is the C++ ABI library used. libc++ Feature Options ---------------------- .. option:: LIBCXX_ENABLE_EXCEPTIONS:BOOL **Default**: ``ON`` Build libc++ with exception support. .. option:: LIBCXX_ENABLE_RTTI:BOOL **Default**: ``ON`` Build libc++ with run time type information. .. option:: LIBCXX_INCLUDE_BENCHMARKS:BOOL **Default**: ``ON`` Build the libc++ benchmark tests and the Google Benchmark library needed to support them. .. option:: LIBCXX_BENCHMARK_NATIVE_STDLIB:STRING **Default**:: ``""`` **Values**:: ``libc++``, ``libstdc++`` Build the libc++ benchmark tests and Google Benchmark library against the specified standard library on the platform. On linux this can be used to compare libc++ to libstdc++ by building the benchmark tests against both standard libraries. .. option:: LIBCXX_BENCHMARK_NATIVE_GCC_TOOLCHAIN:STRING Use the specified GCC toolchain and standard library when building the native stdlib benchmark tests. libc++ ABI Feature Options -------------------------- The following options allow building libc++ for a different ABI version. .. option:: LIBCXX_ABI_VERSION:STRING **Default**: ``1`` Defines the target ABI version of libc++. .. option:: LIBCXX_ABI_UNSTABLE:BOOL **Default**: ``OFF`` Build the "unstable" ABI version of libc++. Includes all ABI changing features on top of the current stable version. .. _LLVM-specific variables: LLVM-specific options --------------------- .. option:: LLVM_LIBDIR_SUFFIX:STRING Extra suffix to append to the directory where libraries are to be installed. On a 64-bit architecture, one could use ``-DLLVM_LIBDIR_SUFFIX=64`` to install libraries to ``/usr/lib64``. .. option:: LLVM_BUILD_32_BITS:BOOL Build 32-bits executables and libraries on 64-bits systems. This option is available only on some 64-bits unix systems. Defaults to OFF. .. option:: LLVM_LIT_ARGS:STRING Arguments given to lit. ``make check`` and ``make clang-test`` are affected. By default, ``'-sv --no-progress-bar'`` on Visual C++ and Xcode, ``'-sv'`` on others. Using Alternate ABI libraries ============================= .. _libsupcxx: Using libsupc++ on Linux ------------------------ You will need libstdc++ in order to provide libsupc++. Figure out where the libsupc++ headers are on your system. On Ubuntu this is ``/usr/include/c++/`` and ``/usr/include/c++//`` You can also figure this out by running .. code-block:: bash $ echo | g++ -Wp,-v -x c++ - -fsyntax-only ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu" ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../../x86_64-linux-gnu/include" #include "..." search starts here: #include <...> search starts here: /usr/include/c++/4.7 /usr/include/c++/4.7/x86_64-linux-gnu /usr/include/c++/4.7/backward /usr/lib/gcc/x86_64-linux-gnu/4.7/include /usr/local/include /usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed /usr/include/x86_64-linux-gnu /usr/include End of search list. Note that the first two entries happen to be what we are looking for. This may not be correct on other platforms. We can now run CMake: .. code-block:: bash $ CC=clang CXX=clang++ cmake -G "Unix Makefiles" \ -DLIBCXX_CXX_ABI=libstdc++ \ -DLIBCXX_CXX_ABI_INCLUDE_PATHS="/usr/include/c++/4.7/;/usr/include/c++/4.7/x86_64-linux-gnu/" \ -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr \ You can also substitute ``-DLIBCXX_CXX_ABI=libsupc++`` above, which will cause the library to be linked to libsupc++ instead of libstdc++, but this is only recommended if you know that you will never need to link against libstdc++ in the same executable as libc++. GCC ships libsupc++ separately but only as a static library. If a program also needs to link against libstdc++, it will provide its own copy of libsupc++ and this can lead to subtle problems. .. code-block:: bash $ make cxx $ make install You can now run clang with -stdlib=libc++. .. _libcxxrt_ref: Using libcxxrt on Linux ------------------------ You will need to keep the source tree of `libcxxrt`_ available on your build machine and your copy of the libcxxrt shared library must be placed where your linker will find it. We can now run CMake like: .. code-block:: bash $ CC=clang CXX=clang++ cmake -G "Unix Makefiles" \ -DLIBCXX_CXX_ABI=libcxxrt \ -DLIBCXX_CXX_ABI_INCLUDE_PATHS=path/to/libcxxrt-sources/src \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_INSTALL_PREFIX=/usr \ $ make cxx $ make install Unfortunately you can't simply run clang with "-stdlib=libc++" at this point, as clang is set up to link for libc++ linked to libsupc++. To get around this you'll have to set up your linker yourself (or patch clang). For example, .. code-block:: bash $ clang++ -stdlib=libc++ helloworld.cpp \ -nodefaultlibs -lc++ -lcxxrt -lm -lc -lgcc_s -lgcc Alternately, you could just add libcxxrt to your libraries list, which in most situations will give the same result: .. code-block:: bash $ clang++ -stdlib=libc++ helloworld.cpp -lcxxrt .. _`libcxxrt`: https://github.com/pathscale/libcxxrt/ Using a local ABI library installation --------------------------------------- .. warning:: This is not recommended in almost all cases. These instructions should only be used when you can't install your ABI library. Normally you must link libc++ against a ABI shared library that the linker can find. If you want to build and test libc++ against an ABI library not in the linker's path you needq to set ``-DLIBCXX_CXX_ABI_LIBRARY_PATH=/path/to/abi/lib`` when configuring CMake. An example build using libc++abi would look like: .. code-block:: bash $ CC=clang CXX=clang++ cmake \ -DLIBCXX_CXX_ABI=libc++abi \ -DLIBCXX_CXX_ABI_INCLUDE_PATHS="/path/to/libcxxabi/include" \ -DLIBCXX_CXX_ABI_LIBRARY_PATH="/path/to/libcxxabi-build/lib" \ path/to/libcxx $ make When testing libc++ LIT will automatically link against the proper ABI library. diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index 1c6790ab4652..5a1b2ccdc426 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -1,66 +1,66 @@ if (NOT LIBCXX_INSTALL_SUPPORT_HEADERS) set(LIBCXX_SUPPORT_HEADER_PATTERN PATTERN "support" EXCLUDE) endif() set(LIBCXX_HEADER_PATTERN PATTERN "*" PATTERN "CMakeLists.txt" EXCLUDE PATTERN ".svn" EXCLUDE PATTERN "__config_site.in" EXCLUDE ${LIBCXX_SUPPORT_HEADER_PATTERN} ) if(NOT LIBCXX_USING_INSTALLED_LLVM AND LLVM_BINARY_DIR) file(COPY . DESTINATION "${LLVM_BINARY_DIR}/include/c++/v1" FILES_MATCHING ${LIBCXX_HEADER_PATTERN} ) endif() if (LIBCXX_INSTALL_HEADERS) install(DIRECTORY . - DESTINATION include/c++/v1 + DESTINATION ${LIBCXX_INSTALL_PREFIX}include/c++/v1 COMPONENT cxx-headers FILES_MATCHING ${LIBCXX_HEADER_PATTERN} PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ ) if (LIBCXX_NEEDS_SITE_CONFIG) # Generate and install a custom __config header. The new header is created # by prepending __config_site to the current __config header. add_custom_command(OUTPUT ${LIBCXX_BINARY_DIR}/__generated_config COMMAND ${PYTHON_EXECUTABLE} ${LIBCXX_SOURCE_DIR}/utils/cat_files.py ${LIBCXX_BINARY_DIR}/__config_site ${LIBCXX_SOURCE_DIR}/include/__config -o ${LIBCXX_BINARY_DIR}/__generated_config DEPENDS ${LIBCXX_SOURCE_DIR}/include/__config ${LIBCXX_BINARY_DIR}/__config_site ) # Add a target that executes the generation commands. add_custom_target(generate_config_header ALL DEPENDS ${LIBCXX_BINARY_DIR}/__generated_config) set(generated_config_deps generate_config_header) # Install the generated header as __config. install(FILES ${LIBCXX_BINARY_DIR}/__generated_config - DESTINATION include/c++/v1 + DESTINATION ${LIBCXX_INSTALL_PREFIX}include/c++/v1 PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ RENAME __config COMPONENT cxx-headers) endif() if (NOT CMAKE_CONFIGURATION_TYPES) # this target is just needed as a placeholder for the distribution target add_custom_target(cxx-headers) add_custom_target(install-cxx-headers DEPENDS cxx-headers ${generated_config_deps} COMMAND "${CMAKE_COMMAND}" -DCMAKE_INSTALL_COMPONENT=cxx-headers -P "${CMAKE_BINARY_DIR}/cmake_install.cmake") add_custom_target(libcxx-headers) add_custom_target(install-libcxx-headers DEPENDS install-cxx-headers) endif() endif() diff --git a/include/cmath b/include/cmath index b41f247af59c..917928a1f42f 100644 --- a/include/cmath +++ b/include/cmath @@ -1,611 +1,611 @@ // -*- C++ -*- //===---------------------------- cmath -----------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef _LIBCPP_CMATH #define _LIBCPP_CMATH /* cmath synopsis Macros: HUGE_VAL HUGE_VALF // C99 HUGE_VALL // C99 INFINITY // C99 NAN // C99 FP_INFINITE // C99 FP_NAN // C99 FP_NORMAL // C99 FP_SUBNORMAL // C99 FP_ZERO // C99 FP_FAST_FMA // C99 FP_FAST_FMAF // C99 FP_FAST_FMAL // C99 FP_ILOGB0 // C99 FP_ILOGBNAN // C99 MATH_ERRNO // C99 MATH_ERREXCEPT // C99 math_errhandling // C99 namespace std { Types: float_t // C99 double_t // C99 // C90 floating_point abs(floating_point x); floating_point acos (arithmetic x); float acosf(float x); long double acosl(long double x); floating_point asin (arithmetic x); float asinf(float x); long double asinl(long double x); floating_point atan (arithmetic x); float atanf(float x); long double atanl(long double x); floating_point atan2 (arithmetic y, arithmetic x); float atan2f(float y, float x); long double atan2l(long double y, long double x); floating_point ceil (arithmetic x); float ceilf(float x); long double ceill(long double x); floating_point cos (arithmetic x); float cosf(float x); long double cosl(long double x); floating_point cosh (arithmetic x); float coshf(float x); long double coshl(long double x); floating_point exp (arithmetic x); float expf(float x); long double expl(long double x); floating_point fabs (arithmetic x); float fabsf(float x); long double fabsl(long double x); floating_point floor (arithmetic x); float floorf(float x); long double floorl(long double x); floating_point fmod (arithmetic x, arithmetic y); float fmodf(float x, float y); long double fmodl(long double x, long double y); floating_point frexp (arithmetic value, int* exp); float frexpf(float value, int* exp); long double frexpl(long double value, int* exp); floating_point ldexp (arithmetic value, int exp); float ldexpf(float value, int exp); long double ldexpl(long double value, int exp); floating_point log (arithmetic x); float logf(float x); long double logl(long double x); floating_point log10 (arithmetic x); float log10f(float x); long double log10l(long double x); floating_point modf (floating_point value, floating_point* iptr); float modff(float value, float* iptr); long double modfl(long double value, long double* iptr); floating_point pow (arithmetic x, arithmetic y); float powf(float x, float y); long double powl(long double x, long double y); floating_point sin (arithmetic x); float sinf(float x); long double sinl(long double x); floating_point sinh (arithmetic x); float sinhf(float x); long double sinhl(long double x); floating_point sqrt (arithmetic x); float sqrtf(float x); long double sqrtl(long double x); floating_point tan (arithmetic x); float tanf(float x); long double tanl(long double x); floating_point tanh (arithmetic x); float tanhf(float x); long double tanhl(long double x); // C99 bool signbit(arithmetic x); int fpclassify(arithmetic x); bool isfinite(arithmetic x); bool isinf(arithmetic x); bool isnan(arithmetic x); bool isnormal(arithmetic x); bool isgreater(arithmetic x, arithmetic y); bool isgreaterequal(arithmetic x, arithmetic y); bool isless(arithmetic x, arithmetic y); bool islessequal(arithmetic x, arithmetic y); bool islessgreater(arithmetic x, arithmetic y); bool isunordered(arithmetic x, arithmetic y); floating_point acosh (arithmetic x); float acoshf(float x); long double acoshl(long double x); floating_point asinh (arithmetic x); float asinhf(float x); long double asinhl(long double x); floating_point atanh (arithmetic x); float atanhf(float x); long double atanhl(long double x); floating_point cbrt (arithmetic x); float cbrtf(float x); long double cbrtl(long double x); floating_point copysign (arithmetic x, arithmetic y); float copysignf(float x, float y); long double copysignl(long double x, long double y); floating_point erf (arithmetic x); float erff(float x); long double erfl(long double x); floating_point erfc (arithmetic x); float erfcf(float x); long double erfcl(long double x); floating_point exp2 (arithmetic x); float exp2f(float x); long double exp2l(long double x); floating_point expm1 (arithmetic x); float expm1f(float x); long double expm1l(long double x); floating_point fdim (arithmetic x, arithmetic y); float fdimf(float x, float y); long double fdiml(long double x, long double y); floating_point fma (arithmetic x, arithmetic y, arithmetic z); float fmaf(float x, float y, float z); long double fmal(long double x, long double y, long double z); floating_point fmax (arithmetic x, arithmetic y); float fmaxf(float x, float y); long double fmaxl(long double x, long double y); floating_point fmin (arithmetic x, arithmetic y); float fminf(float x, float y); long double fminl(long double x, long double y); floating_point hypot (arithmetic x, arithmetic y); float hypotf(float x, float y); long double hypotl(long double x, long double y); double hypot(double x, double y, double z); // C++17 float hypot(float x, float y, float z); // C++17 long double hypot(long double x, long double y, long double z); // C++17 int ilogb (arithmetic x); int ilogbf(float x); int ilogbl(long double x); floating_point lgamma (arithmetic x); float lgammaf(float x); long double lgammal(long double x); long long llrint (arithmetic x); long long llrintf(float x); long long llrintl(long double x); long long llround (arithmetic x); long long llroundf(float x); long long llroundl(long double x); floating_point log1p (arithmetic x); float log1pf(float x); long double log1pl(long double x); floating_point log2 (arithmetic x); float log2f(float x); long double log2l(long double x); floating_point logb (arithmetic x); float logbf(float x); long double logbl(long double x); long lrint (arithmetic x); long lrintf(float x); long lrintl(long double x); long lround (arithmetic x); long lroundf(float x); long lroundl(long double x); double nan (const char* str); float nanf(const char* str); long double nanl(const char* str); floating_point nearbyint (arithmetic x); float nearbyintf(float x); long double nearbyintl(long double x); floating_point nextafter (arithmetic x, arithmetic y); float nextafterf(float x, float y); long double nextafterl(long double x, long double y); floating_point nexttoward (arithmetic x, long double y); float nexttowardf(float x, long double y); long double nexttowardl(long double x, long double y); floating_point remainder (arithmetic x, arithmetic y); float remainderf(float x, float y); long double remainderl(long double x, long double y); floating_point remquo (arithmetic x, arithmetic y, int* pquo); float remquof(float x, float y, int* pquo); long double remquol(long double x, long double y, int* pquo); floating_point rint (arithmetic x); float rintf(float x); long double rintl(long double x); floating_point round (arithmetic x); float roundf(float x); long double roundl(long double x); floating_point scalbln (arithmetic x, long ex); float scalblnf(float x, long ex); long double scalblnl(long double x, long ex); floating_point scalbn (arithmetic x, int ex); float scalbnf(float x, int ex); long double scalbnl(long double x, int ex); floating_point tgamma (arithmetic x); float tgammaf(float x); long double tgammal(long double x); floating_point trunc (arithmetic x); float truncf(float x); long double truncl(long double x); } // std */ #include <__config> #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header #endif _LIBCPP_BEGIN_NAMESPACE_STD using ::signbit; using ::fpclassify; using ::isfinite; using ::isinf; using ::isnan; using ::isnormal; using ::isgreater; using ::isgreaterequal; using ::isless; using ::islessequal; using ::islessgreater; using ::isunordered; using ::isunordered; using ::float_t; using ::double_t; #ifndef _AIX using ::abs; #endif using ::acos; using ::acosf; using ::asin; using ::asinf; using ::atan; using ::atanf; using ::atan2; using ::atan2f; using ::ceil; using ::ceilf; using ::cos; using ::cosf; using ::cosh; using ::coshf; using ::exp; using ::expf; using ::fabs; using ::fabsf; using ::floor; using ::floorf; using ::fmod; using ::fmodf; using ::frexp; using ::frexpf; using ::ldexp; using ::ldexpf; using ::log; using ::logf; using ::log10; using ::log10f; using ::modf; using ::modff; using ::pow; using ::powf; using ::sin; using ::sinf; using ::sinh; using ::sinhf; using ::sqrt; using ::sqrtf; using ::tan; using ::tanf; using ::tanh; using ::tanhf; using ::acosh; using ::acoshf; using ::asinh; using ::asinhf; using ::atanh; using ::atanhf; using ::cbrt; using ::cbrtf; using ::copysign; using ::copysignf; using ::erf; using ::erff; using ::erfc; using ::erfcf; using ::exp2; using ::exp2f; using ::expm1; using ::expm1f; using ::fdim; using ::fdimf; using ::fmaf; using ::fma; using ::fmax; using ::fmaxf; using ::fmin; using ::fminf; using ::hypot; using ::hypotf; using ::ilogb; using ::ilogbf; using ::lgamma; using ::lgammaf; using ::llrint; using ::llrintf; using ::llround; using ::llroundf; using ::log1p; using ::log1pf; using ::log2; using ::log2f; using ::logb; using ::logbf; using ::lrint; using ::lrintf; using ::lround; using ::lroundf; using ::nan; using ::nanf; using ::nearbyint; using ::nearbyintf; using ::nextafter; using ::nextafterf; using ::nexttoward; using ::nexttowardf; using ::remainder; using ::remainderf; using ::remquo; using ::remquof; using ::rint; using ::rintf; using ::round; using ::roundf; using ::scalbln; using ::scalblnf; using ::scalbn; using ::scalbnf; using ::tgamma; using ::tgammaf; using ::trunc; using ::truncf; using ::acosl; using ::asinl; using ::atanl; using ::atan2l; using ::ceill; using ::cosl; using ::coshl; using ::expl; using ::fabsl; using ::floorl; using ::fmodl; using ::frexpl; using ::ldexpl; using ::logl; using ::log10l; using ::modfl; using ::powl; using ::sinl; using ::sinhl; using ::sqrtl; using ::tanl; using ::tanhl; using ::acoshl; using ::asinhl; using ::atanhl; using ::cbrtl; using ::copysignl; using ::erfl; using ::erfcl; using ::exp2l; using ::expm1l; using ::fdiml; using ::fmal; using ::fmaxl; using ::fminl; using ::hypotl; using ::ilogbl; using ::lgammal; using ::llrintl; using ::llroundl; using ::log1pl; using ::log2l; using ::logbl; using ::lrintl; using ::lroundl; using ::nanl; using ::nearbyintl; using ::nextafterl; using ::nexttowardl; using ::remainderl; using ::remquol; using ::rintl; using ::roundl; using ::scalblnl; using ::scalbnl; using ::tgammal; using ::truncl; #if _LIBCPP_STD_VER > 14 inline _LIBCPP_INLINE_VISIBILITY float hypot( float x, float y, float z ) { return sqrt(x*x + y*y + z*z); } inline _LIBCPP_INLINE_VISIBILITY double hypot( double x, double y, double z ) { return sqrt(x*x + y*y + z*z); } inline _LIBCPP_INLINE_VISIBILITY long double hypot( long double x, long double y, long double z ) { return sqrt(x*x + y*y + z*z); } template inline _LIBCPP_INLINE_VISIBILITY typename __lazy_enable_if < is_arithmetic<_A1>::value && is_arithmetic<_A2>::value && is_arithmetic<_A3>::value, __promote<_A1, _A2, _A3> >::type hypot(_A1 __lcpp_x, _A2 __lcpp_y, _A3 __lcpp_z) _NOEXCEPT { typedef typename __promote<_A1, _A2, _A3>::type __result_type; static_assert((!(is_same<_A1, __result_type>::value && is_same<_A2, __result_type>::value && is_same<_A3, __result_type>::value)), ""); return hypot((__result_type)__lcpp_x, (__result_type)__lcpp_y, (__result_type)__lcpp_z); } #endif template _LIBCPP_ALWAYS_INLINE _LIBCPP_CONSTEXPR typename enable_if::value, bool>::type -__libcpp_isnan(_A1 __lcpp_x) _NOEXCEPT +__libcpp_isnan_or_builtin(_A1 __lcpp_x) _NOEXCEPT { #if __has_builtin(__builtin_isnan) return __builtin_isnan(__lcpp_x); #else return isnan(__lcpp_x); #endif } template _LIBCPP_ALWAYS_INLINE _LIBCPP_CONSTEXPR typename enable_if::value, bool>::type -__libcpp_isnan(_A1 __lcpp_x) _NOEXCEPT +__libcpp_isnan_or_builtin(_A1 __lcpp_x) _NOEXCEPT { return isnan(__lcpp_x); } template _LIBCPP_ALWAYS_INLINE _LIBCPP_CONSTEXPR typename enable_if::value, bool>::type -__libcpp_isinf(_A1 __lcpp_x) _NOEXCEPT +__libcpp_isinf_or_builtin(_A1 __lcpp_x) _NOEXCEPT { #if __has_builtin(__builtin_isinf) return __builtin_isinf(__lcpp_x); #else return isinf(__lcpp_x); #endif } template _LIBCPP_ALWAYS_INLINE _LIBCPP_CONSTEXPR typename enable_if::value, bool>::type -__libcpp_isinf(_A1 __lcpp_x) _NOEXCEPT +__libcpp_isinf_or_builtin(_A1 __lcpp_x) _NOEXCEPT { return isinf(__lcpp_x); } template _LIBCPP_ALWAYS_INLINE _LIBCPP_CONSTEXPR typename enable_if::value, bool>::type -__libcpp_isfinite(_A1 __lcpp_x) _NOEXCEPT +__libcpp_isfinite_or_builtin(_A1 __lcpp_x) _NOEXCEPT { #if __has_builtin(__builtin_isfinite) return __builtin_isfinite(__lcpp_x); #else return isfinite(__lcpp_x); #endif } template _LIBCPP_ALWAYS_INLINE _LIBCPP_CONSTEXPR typename enable_if::value, bool>::type -__libcpp_isfinite(_A1 __lcpp_x) _NOEXCEPT +__libcpp_isfinite_or_builtin(_A1 __lcpp_x) _NOEXCEPT { return isfinite(__lcpp_x); } _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP_CMATH diff --git a/include/complex b/include/complex index d41971b3b4db..41a47cfba47c 100644 --- a/include/complex +++ b/include/complex @@ -1,1484 +1,1484 @@ // -*- C++ -*- //===--------------------------- complex ----------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef _LIBCPP_COMPLEX #define _LIBCPP_COMPLEX /* complex synopsis namespace std { template class complex { public: typedef T value_type; complex(const T& re = T(), const T& im = T()); // constexpr in C++14 complex(const complex&); // constexpr in C++14 template complex(const complex&); // constexpr in C++14 T real() const; // constexpr in C++14 T imag() const; // constexpr in C++14 void real(T); void imag(T); complex& operator= (const T&); complex& operator+=(const T&); complex& operator-=(const T&); complex& operator*=(const T&); complex& operator/=(const T&); complex& operator=(const complex&); template complex& operator= (const complex&); template complex& operator+=(const complex&); template complex& operator-=(const complex&); template complex& operator*=(const complex&); template complex& operator/=(const complex&); }; template<> class complex { public: typedef float value_type; constexpr complex(float re = 0.0f, float im = 0.0f); explicit constexpr complex(const complex&); explicit constexpr complex(const complex&); constexpr float real() const; void real(float); constexpr float imag() const; void imag(float); complex& operator= (float); complex& operator+=(float); complex& operator-=(float); complex& operator*=(float); complex& operator/=(float); complex& operator=(const complex&); template complex& operator= (const complex&); template complex& operator+=(const complex&); template complex& operator-=(const complex&); template complex& operator*=(const complex&); template complex& operator/=(const complex&); }; template<> class complex { public: typedef double value_type; constexpr complex(double re = 0.0, double im = 0.0); constexpr complex(const complex&); explicit constexpr complex(const complex&); constexpr double real() const; void real(double); constexpr double imag() const; void imag(double); complex& operator= (double); complex& operator+=(double); complex& operator-=(double); complex& operator*=(double); complex& operator/=(double); complex& operator=(const complex&); template complex& operator= (const complex&); template complex& operator+=(const complex&); template complex& operator-=(const complex&); template complex& operator*=(const complex&); template complex& operator/=(const complex&); }; template<> class complex { public: typedef long double value_type; constexpr complex(long double re = 0.0L, long double im = 0.0L); constexpr complex(const complex&); constexpr complex(const complex&); constexpr long double real() const; void real(long double); constexpr long double imag() const; void imag(long double); complex& operator=(const complex&); complex& operator= (long double); complex& operator+=(long double); complex& operator-=(long double); complex& operator*=(long double); complex& operator/=(long double); template complex& operator= (const complex&); template complex& operator+=(const complex&); template complex& operator-=(const complex&); template complex& operator*=(const complex&); template complex& operator/=(const complex&); }; // 26.3.6 operators: template complex operator+(const complex&, const complex&); template complex operator+(const complex&, const T&); template complex operator+(const T&, const complex&); template complex operator-(const complex&, const complex&); template complex operator-(const complex&, const T&); template complex operator-(const T&, const complex&); template complex operator*(const complex&, const complex&); template complex operator*(const complex&, const T&); template complex operator*(const T&, const complex&); template complex operator/(const complex&, const complex&); template complex operator/(const complex&, const T&); template complex operator/(const T&, const complex&); template complex operator+(const complex&); template complex operator-(const complex&); template bool operator==(const complex&, const complex&); // constexpr in C++14 template bool operator==(const complex&, const T&); // constexpr in C++14 template bool operator==(const T&, const complex&); // constexpr in C++14 template bool operator!=(const complex&, const complex&); // constexpr in C++14 template bool operator!=(const complex&, const T&); // constexpr in C++14 template bool operator!=(const T&, const complex&); // constexpr in C++14 template basic_istream& operator>>(basic_istream&, complex&); template basic_ostream& operator<<(basic_ostream&, const complex&); // 26.3.7 values: template T real(const complex&); // constexpr in C++14 long double real(long double); // constexpr in C++14 double real(double); // constexpr in C++14 template double real(T); // constexpr in C++14 float real(float); // constexpr in C++14 template T imag(const complex&); // constexpr in C++14 long double imag(long double); // constexpr in C++14 double imag(double); // constexpr in C++14 template double imag(T); // constexpr in C++14 float imag(float); // constexpr in C++14 template T abs(const complex&); template T arg(const complex&); long double arg(long double); double arg(double); template double arg(T); float arg(float); template T norm(const complex&); long double norm(long double); double norm(double); template double norm(T); float norm(float); template complex conj(const complex&); complex conj(long double); complex conj(double); template complex conj(T); complex conj(float); template complex proj(const complex&); complex proj(long double); complex proj(double); template complex proj(T); complex proj(float); template complex polar(const T&, const T& = 0); // 26.3.8 transcendentals: template complex acos(const complex&); template complex asin(const complex&); template complex atan(const complex&); template complex acosh(const complex&); template complex asinh(const complex&); template complex atanh(const complex&); template complex cos (const complex&); template complex cosh (const complex&); template complex exp (const complex&); template complex log (const complex&); template complex log10(const complex&); template complex pow(const complex&, const T&); template complex pow(const complex&, const complex&); template complex pow(const T&, const complex&); template complex sin (const complex&); template complex sinh (const complex&); template complex sqrt (const complex&); template complex tan (const complex&); template complex tanh (const complex&); template basic_istream& operator>>(basic_istream& is, complex& x); template basic_ostream& operator<<(basic_ostream& o, const complex& x); } // std */ #include <__config> #include #include #include #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header #endif _LIBCPP_BEGIN_NAMESPACE_STD template class _LIBCPP_TEMPLATE_VIS complex; template complex<_Tp> operator*(const complex<_Tp>& __z, const complex<_Tp>& __w); template complex<_Tp> operator/(const complex<_Tp>& __x, const complex<_Tp>& __y); template class _LIBCPP_TEMPLATE_VIS complex { public: typedef _Tp value_type; private: value_type __re_; value_type __im_; public: _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 complex(const value_type& __re = value_type(), const value_type& __im = value_type()) : __re_(__re), __im_(__im) {} template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 complex(const complex<_Xp>& __c) : __re_(__c.real()), __im_(__c.imag()) {} _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 value_type real() const {return __re_;} _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 value_type imag() const {return __im_;} _LIBCPP_INLINE_VISIBILITY void real(value_type __re) {__re_ = __re;} _LIBCPP_INLINE_VISIBILITY void imag(value_type __im) {__im_ = __im;} _LIBCPP_INLINE_VISIBILITY complex& operator= (const value_type& __re) {__re_ = __re; __im_ = value_type(); return *this;} _LIBCPP_INLINE_VISIBILITY complex& operator+=(const value_type& __re) {__re_ += __re; return *this;} _LIBCPP_INLINE_VISIBILITY complex& operator-=(const value_type& __re) {__re_ -= __re; return *this;} _LIBCPP_INLINE_VISIBILITY complex& operator*=(const value_type& __re) {__re_ *= __re; __im_ *= __re; return *this;} _LIBCPP_INLINE_VISIBILITY complex& operator/=(const value_type& __re) {__re_ /= __re; __im_ /= __re; return *this;} template _LIBCPP_INLINE_VISIBILITY complex& operator= (const complex<_Xp>& __c) { __re_ = __c.real(); __im_ = __c.imag(); return *this; } template _LIBCPP_INLINE_VISIBILITY complex& operator+=(const complex<_Xp>& __c) { __re_ += __c.real(); __im_ += __c.imag(); return *this; } template _LIBCPP_INLINE_VISIBILITY complex& operator-=(const complex<_Xp>& __c) { __re_ -= __c.real(); __im_ -= __c.imag(); return *this; } template _LIBCPP_INLINE_VISIBILITY complex& operator*=(const complex<_Xp>& __c) { *this = *this * complex(__c.real(), __c.imag()); return *this; } template _LIBCPP_INLINE_VISIBILITY complex& operator/=(const complex<_Xp>& __c) { *this = *this / complex(__c.real(), __c.imag()); return *this; } }; template<> class _LIBCPP_TEMPLATE_VIS complex; template<> class _LIBCPP_TEMPLATE_VIS complex; template<> class _LIBCPP_TEMPLATE_VIS complex { float __re_; float __im_; public: typedef float value_type; _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR complex(float __re = 0.0f, float __im = 0.0f) : __re_(__re), __im_(__im) {} _LIBCPP_INLINE_VISIBILITY explicit _LIBCPP_CONSTEXPR complex(const complex& __c); _LIBCPP_INLINE_VISIBILITY explicit _LIBCPP_CONSTEXPR complex(const complex& __c); _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR float real() const {return __re_;} _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR float imag() const {return __im_;} _LIBCPP_INLINE_VISIBILITY void real(value_type __re) {__re_ = __re;} _LIBCPP_INLINE_VISIBILITY void imag(value_type __im) {__im_ = __im;} _LIBCPP_INLINE_VISIBILITY complex& operator= (float __re) {__re_ = __re; __im_ = value_type(); return *this;} _LIBCPP_INLINE_VISIBILITY complex& operator+=(float __re) {__re_ += __re; return *this;} _LIBCPP_INLINE_VISIBILITY complex& operator-=(float __re) {__re_ -= __re; return *this;} _LIBCPP_INLINE_VISIBILITY complex& operator*=(float __re) {__re_ *= __re; __im_ *= __re; return *this;} _LIBCPP_INLINE_VISIBILITY complex& operator/=(float __re) {__re_ /= __re; __im_ /= __re; return *this;} template _LIBCPP_INLINE_VISIBILITY complex& operator= (const complex<_Xp>& __c) { __re_ = __c.real(); __im_ = __c.imag(); return *this; } template _LIBCPP_INLINE_VISIBILITY complex& operator+=(const complex<_Xp>& __c) { __re_ += __c.real(); __im_ += __c.imag(); return *this; } template _LIBCPP_INLINE_VISIBILITY complex& operator-=(const complex<_Xp>& __c) { __re_ -= __c.real(); __im_ -= __c.imag(); return *this; } template _LIBCPP_INLINE_VISIBILITY complex& operator*=(const complex<_Xp>& __c) { *this = *this * complex(__c.real(), __c.imag()); return *this; } template _LIBCPP_INLINE_VISIBILITY complex& operator/=(const complex<_Xp>& __c) { *this = *this / complex(__c.real(), __c.imag()); return *this; } }; template<> class _LIBCPP_TEMPLATE_VIS complex { double __re_; double __im_; public: typedef double value_type; _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR complex(double __re = 0.0, double __im = 0.0) : __re_(__re), __im_(__im) {} _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR complex(const complex& __c); _LIBCPP_INLINE_VISIBILITY explicit _LIBCPP_CONSTEXPR complex(const complex& __c); _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR double real() const {return __re_;} _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR double imag() const {return __im_;} _LIBCPP_INLINE_VISIBILITY void real(value_type __re) {__re_ = __re;} _LIBCPP_INLINE_VISIBILITY void imag(value_type __im) {__im_ = __im;} _LIBCPP_INLINE_VISIBILITY complex& operator= (double __re) {__re_ = __re; __im_ = value_type(); return *this;} _LIBCPP_INLINE_VISIBILITY complex& operator+=(double __re) {__re_ += __re; return *this;} _LIBCPP_INLINE_VISIBILITY complex& operator-=(double __re) {__re_ -= __re; return *this;} _LIBCPP_INLINE_VISIBILITY complex& operator*=(double __re) {__re_ *= __re; __im_ *= __re; return *this;} _LIBCPP_INLINE_VISIBILITY complex& operator/=(double __re) {__re_ /= __re; __im_ /= __re; return *this;} template _LIBCPP_INLINE_VISIBILITY complex& operator= (const complex<_Xp>& __c) { __re_ = __c.real(); __im_ = __c.imag(); return *this; } template _LIBCPP_INLINE_VISIBILITY complex& operator+=(const complex<_Xp>& __c) { __re_ += __c.real(); __im_ += __c.imag(); return *this; } template _LIBCPP_INLINE_VISIBILITY complex& operator-=(const complex<_Xp>& __c) { __re_ -= __c.real(); __im_ -= __c.imag(); return *this; } template _LIBCPP_INLINE_VISIBILITY complex& operator*=(const complex<_Xp>& __c) { *this = *this * complex(__c.real(), __c.imag()); return *this; } template _LIBCPP_INLINE_VISIBILITY complex& operator/=(const complex<_Xp>& __c) { *this = *this / complex(__c.real(), __c.imag()); return *this; } }; template<> class _LIBCPP_TEMPLATE_VIS complex { long double __re_; long double __im_; public: typedef long double value_type; _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR complex(long double __re = 0.0L, long double __im = 0.0L) : __re_(__re), __im_(__im) {} _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR complex(const complex& __c); _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR complex(const complex& __c); _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR long double real() const {return __re_;} _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR long double imag() const {return __im_;} _LIBCPP_INLINE_VISIBILITY void real(value_type __re) {__re_ = __re;} _LIBCPP_INLINE_VISIBILITY void imag(value_type __im) {__im_ = __im;} _LIBCPP_INLINE_VISIBILITY complex& operator= (long double __re) {__re_ = __re; __im_ = value_type(); return *this;} _LIBCPP_INLINE_VISIBILITY complex& operator+=(long double __re) {__re_ += __re; return *this;} _LIBCPP_INLINE_VISIBILITY complex& operator-=(long double __re) {__re_ -= __re; return *this;} _LIBCPP_INLINE_VISIBILITY complex& operator*=(long double __re) {__re_ *= __re; __im_ *= __re; return *this;} _LIBCPP_INLINE_VISIBILITY complex& operator/=(long double __re) {__re_ /= __re; __im_ /= __re; return *this;} template _LIBCPP_INLINE_VISIBILITY complex& operator= (const complex<_Xp>& __c) { __re_ = __c.real(); __im_ = __c.imag(); return *this; } template _LIBCPP_INLINE_VISIBILITY complex& operator+=(const complex<_Xp>& __c) { __re_ += __c.real(); __im_ += __c.imag(); return *this; } template _LIBCPP_INLINE_VISIBILITY complex& operator-=(const complex<_Xp>& __c) { __re_ -= __c.real(); __im_ -= __c.imag(); return *this; } template _LIBCPP_INLINE_VISIBILITY complex& operator*=(const complex<_Xp>& __c) { *this = *this * complex(__c.real(), __c.imag()); return *this; } template _LIBCPP_INLINE_VISIBILITY complex& operator/=(const complex<_Xp>& __c) { *this = *this / complex(__c.real(), __c.imag()); return *this; } }; inline _LIBCPP_CONSTEXPR complex::complex(const complex& __c) : __re_(__c.real()), __im_(__c.imag()) {} inline _LIBCPP_CONSTEXPR complex::complex(const complex& __c) : __re_(__c.real()), __im_(__c.imag()) {} inline _LIBCPP_CONSTEXPR complex::complex(const complex& __c) : __re_(__c.real()), __im_(__c.imag()) {} inline _LIBCPP_CONSTEXPR complex::complex(const complex& __c) : __re_(__c.real()), __im_(__c.imag()) {} inline _LIBCPP_CONSTEXPR complex::complex(const complex& __c) : __re_(__c.real()), __im_(__c.imag()) {} inline _LIBCPP_CONSTEXPR complex::complex(const complex& __c) : __re_(__c.real()), __im_(__c.imag()) {} // 26.3.6 operators: template inline _LIBCPP_INLINE_VISIBILITY complex<_Tp> operator+(const complex<_Tp>& __x, const complex<_Tp>& __y) { complex<_Tp> __t(__x); __t += __y; return __t; } template inline _LIBCPP_INLINE_VISIBILITY complex<_Tp> operator+(const complex<_Tp>& __x, const _Tp& __y) { complex<_Tp> __t(__x); __t += __y; return __t; } template inline _LIBCPP_INLINE_VISIBILITY complex<_Tp> operator+(const _Tp& __x, const complex<_Tp>& __y) { complex<_Tp> __t(__y); __t += __x; return __t; } template inline _LIBCPP_INLINE_VISIBILITY complex<_Tp> operator-(const complex<_Tp>& __x, const complex<_Tp>& __y) { complex<_Tp> __t(__x); __t -= __y; return __t; } template inline _LIBCPP_INLINE_VISIBILITY complex<_Tp> operator-(const complex<_Tp>& __x, const _Tp& __y) { complex<_Tp> __t(__x); __t -= __y; return __t; } template inline _LIBCPP_INLINE_VISIBILITY complex<_Tp> operator-(const _Tp& __x, const complex<_Tp>& __y) { complex<_Tp> __t(-__y); __t += __x; return __t; } template complex<_Tp> operator*(const complex<_Tp>& __z, const complex<_Tp>& __w) { _Tp __a = __z.real(); _Tp __b = __z.imag(); _Tp __c = __w.real(); _Tp __d = __w.imag(); _Tp __ac = __a * __c; _Tp __bd = __b * __d; _Tp __ad = __a * __d; _Tp __bc = __b * __c; _Tp __x = __ac - __bd; _Tp __y = __ad + __bc; - if (__libcpp_isnan(__x) && __libcpp_isnan(__y)) + if (__libcpp_isnan_or_builtin(__x) && __libcpp_isnan_or_builtin(__y)) { bool __recalc = false; - if (__libcpp_isinf(__a) || __libcpp_isinf(__b)) + if (__libcpp_isinf_or_builtin(__a) || __libcpp_isinf_or_builtin(__b)) { - __a = copysign(__libcpp_isinf(__a) ? _Tp(1) : _Tp(0), __a); - __b = copysign(__libcpp_isinf(__b) ? _Tp(1) : _Tp(0), __b); - if (__libcpp_isnan(__c)) + __a = copysign(__libcpp_isinf_or_builtin(__a) ? _Tp(1) : _Tp(0), __a); + __b = copysign(__libcpp_isinf_or_builtin(__b) ? _Tp(1) : _Tp(0), __b); + if (__libcpp_isnan_or_builtin(__c)) __c = copysign(_Tp(0), __c); - if (__libcpp_isnan(__d)) + if (__libcpp_isnan_or_builtin(__d)) __d = copysign(_Tp(0), __d); __recalc = true; } - if (__libcpp_isinf(__c) || __libcpp_isinf(__d)) + if (__libcpp_isinf_or_builtin(__c) || __libcpp_isinf_or_builtin(__d)) { - __c = copysign(__libcpp_isinf(__c) ? _Tp(1) : _Tp(0), __c); - __d = copysign(__libcpp_isinf(__d) ? _Tp(1) : _Tp(0), __d); - if (__libcpp_isnan(__a)) + __c = copysign(__libcpp_isinf_or_builtin(__c) ? _Tp(1) : _Tp(0), __c); + __d = copysign(__libcpp_isinf_or_builtin(__d) ? _Tp(1) : _Tp(0), __d); + if (__libcpp_isnan_or_builtin(__a)) __a = copysign(_Tp(0), __a); - if (__libcpp_isnan(__b)) + if (__libcpp_isnan_or_builtin(__b)) __b = copysign(_Tp(0), __b); __recalc = true; } - if (!__recalc && (__libcpp_isinf(__ac) || __libcpp_isinf(__bd) || - __libcpp_isinf(__ad) || __libcpp_isinf(__bc))) + if (!__recalc && (__libcpp_isinf_or_builtin(__ac) || __libcpp_isinf_or_builtin(__bd) || + __libcpp_isinf_or_builtin(__ad) || __libcpp_isinf_or_builtin(__bc))) { - if (__libcpp_isnan(__a)) + if (__libcpp_isnan_or_builtin(__a)) __a = copysign(_Tp(0), __a); - if (__libcpp_isnan(__b)) + if (__libcpp_isnan_or_builtin(__b)) __b = copysign(_Tp(0), __b); - if (__libcpp_isnan(__c)) + if (__libcpp_isnan_or_builtin(__c)) __c = copysign(_Tp(0), __c); - if (__libcpp_isnan(__d)) + if (__libcpp_isnan_or_builtin(__d)) __d = copysign(_Tp(0), __d); __recalc = true; } if (__recalc) { __x = _Tp(INFINITY) * (__a * __c - __b * __d); __y = _Tp(INFINITY) * (__a * __d + __b * __c); } } return complex<_Tp>(__x, __y); } template inline _LIBCPP_INLINE_VISIBILITY complex<_Tp> operator*(const complex<_Tp>& __x, const _Tp& __y) { complex<_Tp> __t(__x); __t *= __y; return __t; } template inline _LIBCPP_INLINE_VISIBILITY complex<_Tp> operator*(const _Tp& __x, const complex<_Tp>& __y) { complex<_Tp> __t(__y); __t *= __x; return __t; } template complex<_Tp> operator/(const complex<_Tp>& __z, const complex<_Tp>& __w) { int __ilogbw = 0; _Tp __a = __z.real(); _Tp __b = __z.imag(); _Tp __c = __w.real(); _Tp __d = __w.imag(); _Tp __logbw = logb(fmax(fabs(__c), fabs(__d))); - if (__libcpp_isfinite(__logbw)) + if (__libcpp_isfinite_or_builtin(__logbw)) { __ilogbw = static_cast(__logbw); __c = scalbn(__c, -__ilogbw); __d = scalbn(__d, -__ilogbw); } _Tp __denom = __c * __c + __d * __d; _Tp __x = scalbn((__a * __c + __b * __d) / __denom, -__ilogbw); _Tp __y = scalbn((__b * __c - __a * __d) / __denom, -__ilogbw); - if (__libcpp_isnan(__x) && __libcpp_isnan(__y)) + if (__libcpp_isnan_or_builtin(__x) && __libcpp_isnan_or_builtin(__y)) { - if ((__denom == _Tp(0)) && (!__libcpp_isnan(__a) || !__libcpp_isnan(__b))) + if ((__denom == _Tp(0)) && (!__libcpp_isnan_or_builtin(__a) || !__libcpp_isnan_or_builtin(__b))) { __x = copysign(_Tp(INFINITY), __c) * __a; __y = copysign(_Tp(INFINITY), __c) * __b; } - else if ((__libcpp_isinf(__a) || __libcpp_isinf(__b)) && __libcpp_isfinite(__c) && __libcpp_isfinite(__d)) + else if ((__libcpp_isinf_or_builtin(__a) || __libcpp_isinf_or_builtin(__b)) && __libcpp_isfinite_or_builtin(__c) && __libcpp_isfinite_or_builtin(__d)) { - __a = copysign(__libcpp_isinf(__a) ? _Tp(1) : _Tp(0), __a); - __b = copysign(__libcpp_isinf(__b) ? _Tp(1) : _Tp(0), __b); + __a = copysign(__libcpp_isinf_or_builtin(__a) ? _Tp(1) : _Tp(0), __a); + __b = copysign(__libcpp_isinf_or_builtin(__b) ? _Tp(1) : _Tp(0), __b); __x = _Tp(INFINITY) * (__a * __c + __b * __d); __y = _Tp(INFINITY) * (__b * __c - __a * __d); } - else if (__libcpp_isinf(__logbw) && __logbw > _Tp(0) && __libcpp_isfinite(__a) && __libcpp_isfinite(__b)) + else if (__libcpp_isinf_or_builtin(__logbw) && __logbw > _Tp(0) && __libcpp_isfinite_or_builtin(__a) && __libcpp_isfinite_or_builtin(__b)) { - __c = copysign(__libcpp_isinf(__c) ? _Tp(1) : _Tp(0), __c); - __d = copysign(__libcpp_isinf(__d) ? _Tp(1) : _Tp(0), __d); + __c = copysign(__libcpp_isinf_or_builtin(__c) ? _Tp(1) : _Tp(0), __c); + __d = copysign(__libcpp_isinf_or_builtin(__d) ? _Tp(1) : _Tp(0), __d); __x = _Tp(0) * (__a * __c + __b * __d); __y = _Tp(0) * (__b * __c - __a * __d); } } return complex<_Tp>(__x, __y); } template inline _LIBCPP_INLINE_VISIBILITY complex<_Tp> operator/(const complex<_Tp>& __x, const _Tp& __y) { return complex<_Tp>(__x.real() / __y, __x.imag() / __y); } template inline _LIBCPP_INLINE_VISIBILITY complex<_Tp> operator/(const _Tp& __x, const complex<_Tp>& __y) { complex<_Tp> __t(__x); __t /= __y; return __t; } template inline _LIBCPP_INLINE_VISIBILITY complex<_Tp> operator+(const complex<_Tp>& __x) { return __x; } template inline _LIBCPP_INLINE_VISIBILITY complex<_Tp> operator-(const complex<_Tp>& __x) { return complex<_Tp>(-__x.real(), -__x.imag()); } template inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 bool operator==(const complex<_Tp>& __x, const complex<_Tp>& __y) { return __x.real() == __y.real() && __x.imag() == __y.imag(); } template inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 bool operator==(const complex<_Tp>& __x, const _Tp& __y) { return __x.real() == __y && __x.imag() == 0; } template inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 bool operator==(const _Tp& __x, const complex<_Tp>& __y) { return __x == __y.real() && 0 == __y.imag(); } template inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 bool operator!=(const complex<_Tp>& __x, const complex<_Tp>& __y) { return !(__x == __y); } template inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 bool operator!=(const complex<_Tp>& __x, const _Tp& __y) { return !(__x == __y); } template inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 bool operator!=(const _Tp& __x, const complex<_Tp>& __y) { return !(__x == __y); } // 26.3.7 values: template ::value, bool = is_floating_point<_Tp>::value > struct __libcpp_complex_overload_traits {}; // Integral Types template struct __libcpp_complex_overload_traits<_Tp, true, false> { typedef double _ValueType; typedef complex _ComplexType; }; // Floating point types template struct __libcpp_complex_overload_traits<_Tp, false, true> { typedef _Tp _ValueType; typedef complex<_Tp> _ComplexType; }; // real template inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 _Tp real(const complex<_Tp>& __c) { return __c.real(); } template inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 typename __libcpp_complex_overload_traits<_Tp>::_ValueType real(_Tp __re) { return __re; } // imag template inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 _Tp imag(const complex<_Tp>& __c) { return __c.imag(); } template inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 typename __libcpp_complex_overload_traits<_Tp>::_ValueType imag(_Tp) { return 0; } // abs template inline _LIBCPP_INLINE_VISIBILITY _Tp abs(const complex<_Tp>& __c) { return hypot(__c.real(), __c.imag()); } // arg template inline _LIBCPP_INLINE_VISIBILITY _Tp arg(const complex<_Tp>& __c) { return atan2(__c.imag(), __c.real()); } template inline _LIBCPP_INLINE_VISIBILITY typename enable_if< is_same<_Tp, long double>::value, long double >::type arg(_Tp __re) { return atan2l(0.L, __re); } template inline _LIBCPP_INLINE_VISIBILITY typename enable_if < is_integral<_Tp>::value || is_same<_Tp, double>::value, double >::type arg(_Tp __re) { return atan2(0., __re); } template inline _LIBCPP_INLINE_VISIBILITY typename enable_if< is_same<_Tp, float>::value, float >::type arg(_Tp __re) { return atan2f(0.F, __re); } // norm template inline _LIBCPP_INLINE_VISIBILITY _Tp norm(const complex<_Tp>& __c) { - if (__libcpp_isinf(__c.real())) + if (__libcpp_isinf_or_builtin(__c.real())) return abs(__c.real()); - if (__libcpp_isinf(__c.imag())) + if (__libcpp_isinf_or_builtin(__c.imag())) return abs(__c.imag()); return __c.real() * __c.real() + __c.imag() * __c.imag(); } template inline _LIBCPP_INLINE_VISIBILITY typename __libcpp_complex_overload_traits<_Tp>::_ValueType norm(_Tp __re) { typedef typename __libcpp_complex_overload_traits<_Tp>::_ValueType _ValueType; return static_cast<_ValueType>(__re) * __re; } // conj template inline _LIBCPP_INLINE_VISIBILITY complex<_Tp> conj(const complex<_Tp>& __c) { return complex<_Tp>(__c.real(), -__c.imag()); } template inline _LIBCPP_INLINE_VISIBILITY typename __libcpp_complex_overload_traits<_Tp>::_ComplexType conj(_Tp __re) { typedef typename __libcpp_complex_overload_traits<_Tp>::_ComplexType _ComplexType; return _ComplexType(__re); } // proj template inline _LIBCPP_INLINE_VISIBILITY complex<_Tp> proj(const complex<_Tp>& __c) { std::complex<_Tp> __r = __c; - if (__libcpp_isinf(__c.real()) || __libcpp_isinf(__c.imag())) + if (__libcpp_isinf_or_builtin(__c.real()) || __libcpp_isinf_or_builtin(__c.imag())) __r = complex<_Tp>(INFINITY, copysign(_Tp(0), __c.imag())); return __r; } template inline _LIBCPP_INLINE_VISIBILITY typename enable_if < is_floating_point<_Tp>::value, typename __libcpp_complex_overload_traits<_Tp>::_ComplexType >::type proj(_Tp __re) { - if (__libcpp_isinf(__re)) + if (__libcpp_isinf_or_builtin(__re)) __re = abs(__re); return complex<_Tp>(__re); } template inline _LIBCPP_INLINE_VISIBILITY typename enable_if < is_integral<_Tp>::value, typename __libcpp_complex_overload_traits<_Tp>::_ComplexType >::type proj(_Tp __re) { typedef typename __libcpp_complex_overload_traits<_Tp>::_ComplexType _ComplexType; return _ComplexType(__re); } // polar template complex<_Tp> polar(const _Tp& __rho, const _Tp& __theta = _Tp(0)) { - if (__libcpp_isnan(__rho) || signbit(__rho)) + if (__libcpp_isnan_or_builtin(__rho) || signbit(__rho)) return complex<_Tp>(_Tp(NAN), _Tp(NAN)); - if (__libcpp_isnan(__theta)) + if (__libcpp_isnan_or_builtin(__theta)) { - if (__libcpp_isinf(__rho)) + if (__libcpp_isinf_or_builtin(__rho)) return complex<_Tp>(__rho, __theta); return complex<_Tp>(__theta, __theta); } - if (__libcpp_isinf(__theta)) + if (__libcpp_isinf_or_builtin(__theta)) { - if (__libcpp_isinf(__rho)) + if (__libcpp_isinf_or_builtin(__rho)) return complex<_Tp>(__rho, _Tp(NAN)); return complex<_Tp>(_Tp(NAN), _Tp(NAN)); } _Tp __x = __rho * cos(__theta); - if (__libcpp_isnan(__x)) + if (__libcpp_isnan_or_builtin(__x)) __x = 0; _Tp __y = __rho * sin(__theta); - if (__libcpp_isnan(__y)) + if (__libcpp_isnan_or_builtin(__y)) __y = 0; return complex<_Tp>(__x, __y); } // log template inline _LIBCPP_INLINE_VISIBILITY complex<_Tp> log(const complex<_Tp>& __x) { return complex<_Tp>(log(abs(__x)), arg(__x)); } // log10 template inline _LIBCPP_INLINE_VISIBILITY complex<_Tp> log10(const complex<_Tp>& __x) { return log(__x) / log(_Tp(10)); } // sqrt template complex<_Tp> sqrt(const complex<_Tp>& __x) { - if (__libcpp_isinf(__x.imag())) + if (__libcpp_isinf_or_builtin(__x.imag())) return complex<_Tp>(_Tp(INFINITY), __x.imag()); - if (__libcpp_isinf(__x.real())) + if (__libcpp_isinf_or_builtin(__x.real())) { if (__x.real() > _Tp(0)) - return complex<_Tp>(__x.real(), __libcpp_isnan(__x.imag()) ? __x.imag() : copysign(_Tp(0), __x.imag())); - return complex<_Tp>(__libcpp_isnan(__x.imag()) ? __x.imag() : _Tp(0), copysign(__x.real(), __x.imag())); + return complex<_Tp>(__x.real(), __libcpp_isnan_or_builtin(__x.imag()) ? __x.imag() : copysign(_Tp(0), __x.imag())); + return complex<_Tp>(__libcpp_isnan_or_builtin(__x.imag()) ? __x.imag() : _Tp(0), copysign(__x.real(), __x.imag())); } return polar(sqrt(abs(__x)), arg(__x) / _Tp(2)); } // exp template complex<_Tp> exp(const complex<_Tp>& __x) { _Tp __i = __x.imag(); - if (__libcpp_isinf(__x.real())) + if (__libcpp_isinf_or_builtin(__x.real())) { if (__x.real() < _Tp(0)) { - if (!__libcpp_isfinite(__i)) + if (!__libcpp_isfinite_or_builtin(__i)) __i = _Tp(1); } - else if (__i == 0 || !__libcpp_isfinite(__i)) + else if (__i == 0 || !__libcpp_isfinite_or_builtin(__i)) { - if (__libcpp_isinf(__i)) + if (__libcpp_isinf_or_builtin(__i)) __i = _Tp(NAN); return complex<_Tp>(__x.real(), __i); } } - else if (__libcpp_isnan(__x.real()) && __x.imag() == 0) + else if (__libcpp_isnan_or_builtin(__x.real()) && __x.imag() == 0) return __x; _Tp __e = exp(__x.real()); return complex<_Tp>(__e * cos(__i), __e * sin(__i)); } // pow template inline _LIBCPP_INLINE_VISIBILITY complex<_Tp> pow(const complex<_Tp>& __x, const complex<_Tp>& __y) { return exp(__y * log(__x)); } template inline _LIBCPP_INLINE_VISIBILITY complex::type> pow(const complex<_Tp>& __x, const complex<_Up>& __y) { typedef complex::type> result_type; return _VSTD::pow(result_type(__x), result_type(__y)); } template inline _LIBCPP_INLINE_VISIBILITY typename enable_if < is_arithmetic<_Up>::value, complex::type> >::type pow(const complex<_Tp>& __x, const _Up& __y) { typedef complex::type> result_type; return _VSTD::pow(result_type(__x), result_type(__y)); } template inline _LIBCPP_INLINE_VISIBILITY typename enable_if < is_arithmetic<_Tp>::value, complex::type> >::type pow(const _Tp& __x, const complex<_Up>& __y) { typedef complex::type> result_type; return _VSTD::pow(result_type(__x), result_type(__y)); } // asinh template complex<_Tp> asinh(const complex<_Tp>& __x) { const _Tp __pi(atan2(+0., -0.)); - if (__libcpp_isinf(__x.real())) + if (__libcpp_isinf_or_builtin(__x.real())) { - if (__libcpp_isnan(__x.imag())) + if (__libcpp_isnan_or_builtin(__x.imag())) return __x; - if (__libcpp_isinf(__x.imag())) + if (__libcpp_isinf_or_builtin(__x.imag())) return complex<_Tp>(__x.real(), copysign(__pi * _Tp(0.25), __x.imag())); return complex<_Tp>(__x.real(), copysign(_Tp(0), __x.imag())); } - if (__libcpp_isnan(__x.real())) + if (__libcpp_isnan_or_builtin(__x.real())) { - if (__libcpp_isinf(__x.imag())) + if (__libcpp_isinf_or_builtin(__x.imag())) return complex<_Tp>(__x.imag(), __x.real()); if (__x.imag() == 0) return __x; return complex<_Tp>(__x.real(), __x.real()); } - if (__libcpp_isinf(__x.imag())) + if (__libcpp_isinf_or_builtin(__x.imag())) return complex<_Tp>(copysign(__x.imag(), __x.real()), copysign(__pi/_Tp(2), __x.imag())); complex<_Tp> __z = log(__x + sqrt(pow(__x, _Tp(2)) + _Tp(1))); return complex<_Tp>(copysign(__z.real(), __x.real()), copysign(__z.imag(), __x.imag())); } // acosh template complex<_Tp> acosh(const complex<_Tp>& __x) { const _Tp __pi(atan2(+0., -0.)); - if (__libcpp_isinf(__x.real())) + if (__libcpp_isinf_or_builtin(__x.real())) { - if (__libcpp_isnan(__x.imag())) + if (__libcpp_isnan_or_builtin(__x.imag())) return complex<_Tp>(abs(__x.real()), __x.imag()); - if (__libcpp_isinf(__x.imag())) + if (__libcpp_isinf_or_builtin(__x.imag())) { if (__x.real() > 0) return complex<_Tp>(__x.real(), copysign(__pi * _Tp(0.25), __x.imag())); else return complex<_Tp>(-__x.real(), copysign(__pi * _Tp(0.75), __x.imag())); } if (__x.real() < 0) return complex<_Tp>(-__x.real(), copysign(__pi, __x.imag())); return complex<_Tp>(__x.real(), copysign(_Tp(0), __x.imag())); } - if (__libcpp_isnan(__x.real())) + if (__libcpp_isnan_or_builtin(__x.real())) { - if (__libcpp_isinf(__x.imag())) + if (__libcpp_isinf_or_builtin(__x.imag())) return complex<_Tp>(abs(__x.imag()), __x.real()); return complex<_Tp>(__x.real(), __x.real()); } - if (__libcpp_isinf(__x.imag())) + if (__libcpp_isinf_or_builtin(__x.imag())) return complex<_Tp>(abs(__x.imag()), copysign(__pi/_Tp(2), __x.imag())); complex<_Tp> __z = log(__x + sqrt(pow(__x, _Tp(2)) - _Tp(1))); return complex<_Tp>(copysign(__z.real(), _Tp(0)), copysign(__z.imag(), __x.imag())); } // atanh template complex<_Tp> atanh(const complex<_Tp>& __x) { const _Tp __pi(atan2(+0., -0.)); - if (__libcpp_isinf(__x.imag())) + if (__libcpp_isinf_or_builtin(__x.imag())) { return complex<_Tp>(copysign(_Tp(0), __x.real()), copysign(__pi/_Tp(2), __x.imag())); } - if (__libcpp_isnan(__x.imag())) + if (__libcpp_isnan_or_builtin(__x.imag())) { - if (__libcpp_isinf(__x.real()) || __x.real() == 0) + if (__libcpp_isinf_or_builtin(__x.real()) || __x.real() == 0) return complex<_Tp>(copysign(_Tp(0), __x.real()), __x.imag()); return complex<_Tp>(__x.imag(), __x.imag()); } - if (__libcpp_isnan(__x.real())) + if (__libcpp_isnan_or_builtin(__x.real())) { return complex<_Tp>(__x.real(), __x.real()); } - if (__libcpp_isinf(__x.real())) + if (__libcpp_isinf_or_builtin(__x.real())) { return complex<_Tp>(copysign(_Tp(0), __x.real()), copysign(__pi/_Tp(2), __x.imag())); } if (abs(__x.real()) == _Tp(1) && __x.imag() == _Tp(0)) { return complex<_Tp>(copysign(_Tp(INFINITY), __x.real()), copysign(_Tp(0), __x.imag())); } complex<_Tp> __z = log((_Tp(1) + __x) / (_Tp(1) - __x)) / _Tp(2); return complex<_Tp>(copysign(__z.real(), __x.real()), copysign(__z.imag(), __x.imag())); } // sinh template complex<_Tp> sinh(const complex<_Tp>& __x) { - if (__libcpp_isinf(__x.real()) && !__libcpp_isfinite(__x.imag())) + if (__libcpp_isinf_or_builtin(__x.real()) && !__libcpp_isfinite_or_builtin(__x.imag())) return complex<_Tp>(__x.real(), _Tp(NAN)); - if (__x.real() == 0 && !__libcpp_isfinite(__x.imag())) + if (__x.real() == 0 && !__libcpp_isfinite_or_builtin(__x.imag())) return complex<_Tp>(__x.real(), _Tp(NAN)); - if (__x.imag() == 0 && !__libcpp_isfinite(__x.real())) + if (__x.imag() == 0 && !__libcpp_isfinite_or_builtin(__x.real())) return __x; return complex<_Tp>(sinh(__x.real()) * cos(__x.imag()), cosh(__x.real()) * sin(__x.imag())); } // cosh template complex<_Tp> cosh(const complex<_Tp>& __x) { - if (__libcpp_isinf(__x.real()) && !__libcpp_isfinite(__x.imag())) + if (__libcpp_isinf_or_builtin(__x.real()) && !__libcpp_isfinite_or_builtin(__x.imag())) return complex<_Tp>(abs(__x.real()), _Tp(NAN)); - if (__x.real() == 0 && !__libcpp_isfinite(__x.imag())) + if (__x.real() == 0 && !__libcpp_isfinite_or_builtin(__x.imag())) return complex<_Tp>(_Tp(NAN), __x.real()); if (__x.real() == 0 && __x.imag() == 0) return complex<_Tp>(_Tp(1), __x.imag()); - if (__x.imag() == 0 && !__libcpp_isfinite(__x.real())) + if (__x.imag() == 0 && !__libcpp_isfinite_or_builtin(__x.real())) return complex<_Tp>(abs(__x.real()), __x.imag()); return complex<_Tp>(cosh(__x.real()) * cos(__x.imag()), sinh(__x.real()) * sin(__x.imag())); } // tanh template complex<_Tp> tanh(const complex<_Tp>& __x) { - if (__libcpp_isinf(__x.real())) + if (__libcpp_isinf_or_builtin(__x.real())) { - if (!__libcpp_isfinite(__x.imag())) + if (!__libcpp_isfinite_or_builtin(__x.imag())) return complex<_Tp>(_Tp(1), _Tp(0)); return complex<_Tp>(_Tp(1), copysign(_Tp(0), sin(_Tp(2) * __x.imag()))); } - if (__libcpp_isnan(__x.real()) && __x.imag() == 0) + if (__libcpp_isnan_or_builtin(__x.real()) && __x.imag() == 0) return __x; _Tp __2r(_Tp(2) * __x.real()); _Tp __2i(_Tp(2) * __x.imag()); _Tp __d(cosh(__2r) + cos(__2i)); _Tp __2rsh(sinh(__2r)); - if (__libcpp_isinf(__2rsh) && __libcpp_isinf(__d)) + if (__libcpp_isinf_or_builtin(__2rsh) && __libcpp_isinf_or_builtin(__d)) return complex<_Tp>(__2rsh > _Tp(0) ? _Tp(1) : _Tp(-1), __2i > _Tp(0) ? _Tp(0) : _Tp(-0.)); return complex<_Tp>(__2rsh/__d, sin(__2i)/__d); } // asin template complex<_Tp> asin(const complex<_Tp>& __x) { complex<_Tp> __z = asinh(complex<_Tp>(-__x.imag(), __x.real())); return complex<_Tp>(__z.imag(), -__z.real()); } // acos template complex<_Tp> acos(const complex<_Tp>& __x) { const _Tp __pi(atan2(+0., -0.)); - if (__libcpp_isinf(__x.real())) + if (__libcpp_isinf_or_builtin(__x.real())) { - if (__libcpp_isnan(__x.imag())) + if (__libcpp_isnan_or_builtin(__x.imag())) return complex<_Tp>(__x.imag(), __x.real()); - if (__libcpp_isinf(__x.imag())) + if (__libcpp_isinf_or_builtin(__x.imag())) { if (__x.real() < _Tp(0)) return complex<_Tp>(_Tp(0.75) * __pi, -__x.imag()); return complex<_Tp>(_Tp(0.25) * __pi, -__x.imag()); } if (__x.real() < _Tp(0)) return complex<_Tp>(__pi, signbit(__x.imag()) ? -__x.real() : __x.real()); return complex<_Tp>(_Tp(0), signbit(__x.imag()) ? __x.real() : -__x.real()); } - if (__libcpp_isnan(__x.real())) + if (__libcpp_isnan_or_builtin(__x.real())) { - if (__libcpp_isinf(__x.imag())) + if (__libcpp_isinf_or_builtin(__x.imag())) return complex<_Tp>(__x.real(), -__x.imag()); return complex<_Tp>(__x.real(), __x.real()); } - if (__libcpp_isinf(__x.imag())) + if (__libcpp_isinf_or_builtin(__x.imag())) return complex<_Tp>(__pi/_Tp(2), -__x.imag()); if (__x.real() == 0 && (__x.imag() == 0 || isnan(__x.imag()))) return complex<_Tp>(__pi/_Tp(2), -__x.imag()); complex<_Tp> __z = log(__x + sqrt(pow(__x, _Tp(2)) - _Tp(1))); if (signbit(__x.imag())) return complex<_Tp>(abs(__z.imag()), abs(__z.real())); return complex<_Tp>(abs(__z.imag()), -abs(__z.real())); } // atan template complex<_Tp> atan(const complex<_Tp>& __x) { complex<_Tp> __z = atanh(complex<_Tp>(-__x.imag(), __x.real())); return complex<_Tp>(__z.imag(), -__z.real()); } // sin template complex<_Tp> sin(const complex<_Tp>& __x) { complex<_Tp> __z = sinh(complex<_Tp>(-__x.imag(), __x.real())); return complex<_Tp>(__z.imag(), -__z.real()); } // cos template inline _LIBCPP_INLINE_VISIBILITY complex<_Tp> cos(const complex<_Tp>& __x) { return cosh(complex<_Tp>(-__x.imag(), __x.real())); } // tan template complex<_Tp> tan(const complex<_Tp>& __x) { complex<_Tp> __z = tanh(complex<_Tp>(-__x.imag(), __x.real())); return complex<_Tp>(__z.imag(), -__z.real()); } template basic_istream<_CharT, _Traits>& operator>>(basic_istream<_CharT, _Traits>& __is, complex<_Tp>& __x) { if (__is.good()) { ws(__is); if (__is.peek() == _CharT('(')) { __is.get(); _Tp __r; __is >> __r; if (!__is.fail()) { ws(__is); _CharT __c = __is.peek(); if (__c == _CharT(',')) { __is.get(); _Tp __i; __is >> __i; if (!__is.fail()) { ws(__is); __c = __is.peek(); if (__c == _CharT(')')) { __is.get(); __x = complex<_Tp>(__r, __i); } else __is.setstate(ios_base::failbit); } else __is.setstate(ios_base::failbit); } else if (__c == _CharT(')')) { __is.get(); __x = complex<_Tp>(__r, _Tp(0)); } else __is.setstate(ios_base::failbit); } else __is.setstate(ios_base::failbit); } else { _Tp __r; __is >> __r; if (!__is.fail()) __x = complex<_Tp>(__r, _Tp(0)); else __is.setstate(ios_base::failbit); } } else __is.setstate(ios_base::failbit); return __is; } template basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& __os, const complex<_Tp>& __x) { basic_ostringstream<_CharT, _Traits> __s; __s.flags(__os.flags()); __s.imbue(__os.getloc()); __s.precision(__os.precision()); __s << '(' << __x.real() << ',' << __x.imag() << ')'; return __os << __s.str(); } #if _LIBCPP_STD_VER > 11 // Literal suffix for complex number literals [complex.literals] inline namespace literals { inline namespace complex_literals { constexpr complex operator""il(long double __im) { return { 0.0l, __im }; } constexpr complex operator""il(unsigned long long __im) { return { 0.0l, static_cast(__im) }; } constexpr complex operator""i(long double __im) { return { 0.0, static_cast(__im) }; } constexpr complex operator""i(unsigned long long __im) { return { 0.0, static_cast(__im) }; } constexpr complex operator""if(long double __im) { return { 0.0f, static_cast(__im) }; } constexpr complex operator""if(unsigned long long __im) { return { 0.0f, static_cast(__im) }; } } } #endif _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP_COMPLEX diff --git a/include/optional b/include/optional index c0fd0e7bc49f..1fb953bab743 100644 --- a/include/optional +++ b/include/optional @@ -1,1323 +1,1399 @@ // -*- C++ -*- //===-------------------------- optional ----------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef _LIBCPP_OPTIONAL #define _LIBCPP_OPTIONAL /* optional synopsis // C++1z namespace std { // 23.6.3, optional for object types template class optional; // 23.6.4, no-value state indicator struct nullopt_t{see below }; constexpr nullopt_t nullopt(unspecified ); // 23.6.5, class bad_optional_access class bad_optional_access; // 23.6.6, relational operators template constexpr bool operator==(const optional&, const optional&); template constexpr bool operator!=(const optional&, const optional&); template constexpr bool operator<(const optional&, const optional&); template constexpr bool operator>(const optional&, const optional&); template constexpr bool operator<=(const optional&, const optional&); template constexpr bool operator>=(const optional&, const optional&); // 23.6.7 comparison with nullopt template constexpr bool operator==(const optional&, nullopt_t) noexcept; template constexpr bool operator==(nullopt_t, const optional&) noexcept; template constexpr bool operator!=(const optional&, nullopt_t) noexcept; template constexpr bool operator!=(nullopt_t, const optional&) noexcept; template constexpr bool operator<(const optional&, nullopt_t) noexcept; template constexpr bool operator<(nullopt_t, const optional&) noexcept; template constexpr bool operator<=(const optional&, nullopt_t) noexcept; template constexpr bool operator<=(nullopt_t, const optional&) noexcept; template constexpr bool operator>(const optional&, nullopt_t) noexcept; template constexpr bool operator>(nullopt_t, const optional&) noexcept; template constexpr bool operator>=(const optional&, nullopt_t) noexcept; template constexpr bool operator>=(nullopt_t, const optional&) noexcept; // 23.6.8, comparison with T template constexpr bool operator==(const optional&, const U&); template constexpr bool operator==(const U&, const optional&); template constexpr bool operator!=(const optional&, const U&); template constexpr bool operator!=(const U&, const optional&); template constexpr bool operator<(const optional&, const U&); template constexpr bool operator<(const U&, const optional&); template constexpr bool operator<=(const optional&, const U&); template constexpr bool operator<=(const U&, const optional&); template constexpr bool operator>(const optional&, const U&); template constexpr bool operator>(const U&, const optional&); template constexpr bool operator>=(const optional&, const U&); template constexpr bool operator>=(const U&, const optional&); // 23.6.9, specialized algorithms template void swap(optional&, optional&) noexcept(see below ); template constexpr optional make_optional(T&&); template constexpr optional make_optional(Args&&... args); template constexpr optional make_optional(initializer_list il, Args&&... args); // 23.6.10, hash support template struct hash; template struct hash>; template class optional { public: using value_type = T; // 23.6.3.1, constructors constexpr optional() noexcept; constexpr optional(nullopt_t) noexcept; optional(const optional &); optional(optional &&) noexcept(see below); template constexpr explicit optional(in_place_t, Args &&...); template constexpr explicit optional(in_place_t, initializer_list, Args &&...); template constexpr EXPLICIT optional(U &&); template constexpr EXPLICIT optional(const optional &); template constexpr EXPLICIT optional(optional &&); // 23.6.3.2, destructor ~optional(); // 23.6.3.3, assignment optional &operator=(nullopt_t) noexcept; optional &operator=(const optional &); optional &operator=(optional &&) noexcept(see below ); template optional &operator=(U &&); template optional &operator=(const optional &); template optional &operator=(optional &&); template T& emplace(Args &&...); template T& emplace(initializer_list, Args &&...); // 23.6.3.4, swap void swap(optional &) noexcept(see below ); // 23.6.3.5, observers constexpr T const *operator->() const; constexpr T *operator->(); constexpr T const &operator*() const &; constexpr T &operator*() &; constexpr T &&operator*() &&; constexpr const T &&operator*() const &&; constexpr explicit operator bool() const noexcept; constexpr bool has_value() const noexcept; constexpr T const &value() const &; constexpr T &value() &; constexpr T &&value() &&; constexpr const T &&value() const &&; template constexpr T value_or(U &&) const &; template constexpr T value_or(U &&) &&; // 23.6.3.6, modifiers void reset() noexcept; private: T *val; // exposition only }; } // namespace std */ #include <__config> #include <__debug> #include <__functional_base> #include #include #include #include #include #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header #endif _LIBCPP_PUSH_MACROS #include <__undef_macros> namespace std // purposefully not using versioning namespace { class _LIBCPP_EXCEPTION_ABI bad_optional_access : public exception { public: // Get the key function ~bad_optional_access() into the dylib virtual ~bad_optional_access() _NOEXCEPT; virtual const char* what() const _NOEXCEPT; }; } // std #if _LIBCPP_STD_VER > 14 _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY void __throw_bad_optional_access() { #ifndef _LIBCPP_NO_EXCEPTIONS throw bad_optional_access(); #else _VSTD::abort(); #endif } struct nullopt_t { struct __secret_tag { _LIBCPP_INLINE_VISIBILITY explicit __secret_tag() = default; }; _LIBCPP_INLINE_VISIBILITY constexpr explicit nullopt_t(__secret_tag, __secret_tag) noexcept {} }; /* inline */ constexpr nullopt_t nullopt{nullopt_t::__secret_tag{}, nullopt_t::__secret_tag{}}; template ::value> struct __optional_destruct_base; template struct __optional_destruct_base<_Tp, false> { typedef _Tp value_type; static_assert(is_object_v, "instantiation of optional with a non-object type is undefined behavior"); union { char __null_state_; value_type __val_; }; bool __engaged_; _LIBCPP_INLINE_VISIBILITY ~__optional_destruct_base() { if (__engaged_) __val_.~value_type(); } _LIBCPP_INLINE_VISIBILITY constexpr __optional_destruct_base() noexcept : __null_state_(), __engaged_(false) {} template _LIBCPP_INLINE_VISIBILITY constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args) : __val_(_VSTD::forward<_Args>(__args)...), __engaged_(true) {} _LIBCPP_INLINE_VISIBILITY void reset() noexcept { if (__engaged_) { __val_.~value_type(); __engaged_ = false; } } }; template struct __optional_destruct_base<_Tp, true> { typedef _Tp value_type; static_assert(is_object_v, "instantiation of optional with a non-object type is undefined behavior"); union { char __null_state_; value_type __val_; }; bool __engaged_; _LIBCPP_INLINE_VISIBILITY constexpr __optional_destruct_base() noexcept : __null_state_(), __engaged_(false) {} template _LIBCPP_INLINE_VISIBILITY constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args) : __val_(_VSTD::forward<_Args>(__args)...), __engaged_(true) {} _LIBCPP_INLINE_VISIBILITY void reset() noexcept { if (__engaged_) { __engaged_ = false; } } }; template ::value> struct __optional_storage_base : __optional_destruct_base<_Tp> { using __base = __optional_destruct_base<_Tp>; using value_type = _Tp; using __base::__base; _LIBCPP_INLINE_VISIBILITY constexpr bool has_value() const noexcept { return this->__engaged_; } _LIBCPP_INLINE_VISIBILITY constexpr value_type& __get() & noexcept { return this->__val_; } _LIBCPP_INLINE_VISIBILITY constexpr const value_type& __get() const& noexcept { return this->__val_; } _LIBCPP_INLINE_VISIBILITY constexpr value_type&& __get() && noexcept { return _VSTD::move(this->__val_); } _LIBCPP_INLINE_VISIBILITY constexpr const value_type&& __get() const&& noexcept { return _VSTD::move(this->__val_); } template _LIBCPP_INLINE_VISIBILITY void __construct(_Args&&... __args) { _LIBCPP_ASSERT(!has_value(), "__construct called for engaged __optional_storage"); ::new((void*)_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Args>(__args)...); this->__engaged_ = true; } template _LIBCPP_INLINE_VISIBILITY void __construct_from(_That&& __opt) { if (__opt.has_value()) __construct(_VSTD::forward<_That>(__opt).__get()); } template _LIBCPP_INLINE_VISIBILITY void __assign_from(_That&& __opt) { if (this->__engaged_ == __opt.has_value()) { if (this->__engaged_) this->__val_ = _VSTD::forward<_That>(__opt).__get(); } else { if (this->__engaged_) this->reset(); else __construct(_VSTD::forward<_That>(__opt).__get()); } } }; // optional is currently required ill-formed, however it may to be in the // future. For this reason it has already been implemented to ensure we can // make the change in an ABI compatible manner. template struct __optional_storage_base<_Tp, true> { using value_type = _Tp; using __raw_type = remove_reference_t<_Tp>; __raw_type* __value_; template static constexpr bool __can_bind_reference() { using _RawUp = typename remove_reference<_Up>::type; using _UpPtr = _RawUp*; using _RawTp = typename remove_reference<_Tp>::type; using _TpPtr = _RawTp*; using _CheckLValueArg = integral_constant::value && is_convertible<_UpPtr, _TpPtr>::value) || is_same<_RawUp, reference_wrapper<_RawTp>>::value || is_same<_RawUp, reference_wrapper::type>>::value >; return (is_lvalue_reference<_Tp>::value && _CheckLValueArg::value) || (is_rvalue_reference<_Tp>::value && !is_lvalue_reference<_Up>::value && is_convertible<_UpPtr, _TpPtr>::value); } _LIBCPP_INLINE_VISIBILITY constexpr __optional_storage_base() noexcept : __value_(nullptr) {} template _LIBCPP_INLINE_VISIBILITY constexpr explicit __optional_storage_base(in_place_t, _UArg&& __uarg) : __value_(_VSTD::addressof(__uarg)) { static_assert(__can_bind_reference<_UArg>(), "Attempted to construct a reference element in tuple from a " "possible temporary"); } _LIBCPP_INLINE_VISIBILITY void reset() noexcept { __value_ = nullptr; } _LIBCPP_INLINE_VISIBILITY constexpr bool has_value() const noexcept { return __value_ != nullptr; } _LIBCPP_INLINE_VISIBILITY constexpr value_type& __get() const& noexcept { return *__value_; } _LIBCPP_INLINE_VISIBILITY constexpr value_type&& __get() const&& noexcept { return _VSTD::forward(*__value_); } template _LIBCPP_INLINE_VISIBILITY void __construct(_UArg&& __val) { _LIBCPP_ASSERT(!has_value(), "__construct called for engaged __optional_storage"); static_assert(__can_bind_reference<_UArg>(), "Attempted to construct a reference element in tuple from a " "possible temporary"); __value_ = _VSTD::addressof(__val); } template _LIBCPP_INLINE_VISIBILITY void __construct_from(_That&& __opt) { if (__opt.has_value()) __construct(_VSTD::forward<_That>(__opt).__get()); } template _LIBCPP_INLINE_VISIBILITY void __assign_from(_That&& __opt) { if (has_value() == __opt.has_value()) { if (has_value()) *__value_ = _VSTD::forward<_That>(__opt).__get(); } else { if (has_value()) reset(); else __construct(_VSTD::forward<_That>(__opt).__get()); } } }; -template ::value> -struct __optional_storage; - -template -struct __optional_storage<_Tp, true> : __optional_storage_base<_Tp> +template ::value> +struct __optional_copy_base : __optional_storage_base<_Tp> { using __optional_storage_base<_Tp>::__optional_storage_base; }; template -struct __optional_storage<_Tp, false> : __optional_storage_base<_Tp> +struct __optional_copy_base<_Tp, false> : __optional_storage_base<_Tp> { - using value_type = _Tp; using __optional_storage_base<_Tp>::__optional_storage_base; _LIBCPP_INLINE_VISIBILITY - __optional_storage() = default; + __optional_copy_base() = default; _LIBCPP_INLINE_VISIBILITY - __optional_storage(const __optional_storage& __opt) + __optional_copy_base(const __optional_copy_base& __opt) { this->__construct_from(__opt); } _LIBCPP_INLINE_VISIBILITY - __optional_storage(__optional_storage&& __opt) + __optional_copy_base(__optional_copy_base&&) = default; + _LIBCPP_INLINE_VISIBILITY + __optional_copy_base& operator=(const __optional_copy_base&) = default; + _LIBCPP_INLINE_VISIBILITY + __optional_copy_base& operator=(__optional_copy_base&&) = default; +}; + +template ::value> +struct __optional_move_base : __optional_copy_base<_Tp> +{ + using __optional_copy_base<_Tp>::__optional_copy_base; +}; + +template +struct __optional_move_base<_Tp, false> : __optional_copy_base<_Tp> +{ + using value_type = _Tp; + using __optional_copy_base<_Tp>::__optional_copy_base; + + _LIBCPP_INLINE_VISIBILITY + __optional_move_base() = default; + _LIBCPP_INLINE_VISIBILITY + __optional_move_base(const __optional_move_base&) = default; + + _LIBCPP_INLINE_VISIBILITY + __optional_move_base(__optional_move_base&& __opt) noexcept(is_nothrow_move_constructible_v) { this->__construct_from(_VSTD::move(__opt)); } _LIBCPP_INLINE_VISIBILITY - __optional_storage& operator=(const __optional_storage& __opt) + __optional_move_base& operator=(const __optional_move_base&) = default; + _LIBCPP_INLINE_VISIBILITY + __optional_move_base& operator=(__optional_move_base&&) = default; +}; + +template ::value && + is_trivially_copy_constructible<_Tp>::value && + is_trivially_copy_assignable<_Tp>::value> +struct __optional_copy_assign_base : __optional_move_base<_Tp> +{ + using __optional_move_base<_Tp>::__optional_move_base; +}; + +template +struct __optional_copy_assign_base<_Tp, false> : __optional_move_base<_Tp> +{ + using __optional_move_base<_Tp>::__optional_move_base; + + _LIBCPP_INLINE_VISIBILITY + __optional_copy_assign_base() = default; + _LIBCPP_INLINE_VISIBILITY + __optional_copy_assign_base(const __optional_copy_assign_base&) = default; + _LIBCPP_INLINE_VISIBILITY + __optional_copy_assign_base(__optional_copy_assign_base&&) = default; + + _LIBCPP_INLINE_VISIBILITY + __optional_copy_assign_base& operator=(const __optional_copy_assign_base& __opt) { this->__assign_from(__opt); return *this; } _LIBCPP_INLINE_VISIBILITY - __optional_storage& operator=(__optional_storage&& __opt) + __optional_copy_assign_base& operator=(__optional_copy_assign_base&&) = default; +}; + +template ::value && + is_trivially_move_constructible<_Tp>::value && + is_trivially_move_assignable<_Tp>::value> +struct __optional_move_assign_base : __optional_copy_assign_base<_Tp> +{ + using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base; +}; + +template +struct __optional_move_assign_base<_Tp, false> : __optional_copy_assign_base<_Tp> +{ + using value_type = _Tp; + using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base; + + _LIBCPP_INLINE_VISIBILITY + __optional_move_assign_base() = default; + _LIBCPP_INLINE_VISIBILITY + __optional_move_assign_base(const __optional_move_assign_base& __opt) = default; + _LIBCPP_INLINE_VISIBILITY + __optional_move_assign_base(__optional_move_assign_base&&) = default; + _LIBCPP_INLINE_VISIBILITY + __optional_move_assign_base& operator=(const __optional_move_assign_base&) = default; + + _LIBCPP_INLINE_VISIBILITY + __optional_move_assign_base& operator=(__optional_move_assign_base&& __opt) noexcept(is_nothrow_move_assignable_v && is_nothrow_move_constructible_v) { this->__assign_from(_VSTD::move(__opt)); return *this; } }; template using __optional_sfinae_ctor_base_t = __sfinae_ctor_base< is_copy_constructible<_Tp>::value, is_move_constructible<_Tp>::value >; template using __optional_sfinae_assign_base_t = __sfinae_assign_base< (is_copy_constructible<_Tp>::value && is_copy_assignable<_Tp>::value), (is_move_constructible<_Tp>::value && is_move_assignable<_Tp>::value) >; template class optional - : private __optional_storage<_Tp> + : private __optional_move_assign_base<_Tp> , private __optional_sfinae_ctor_base_t<_Tp> , private __optional_sfinae_assign_base_t<_Tp> { - using __base = __optional_storage<_Tp>; + using __base = __optional_move_assign_base<_Tp>; public: using value_type = _Tp; private: // Disable the reference extension using this static assert. static_assert(!is_same_v, "instantiation of optional with in_place_t is ill-formed"); static_assert(!is_same_v<__uncvref_t, nullopt_t>, "instantiation of optional with nullopt_t is ill-formed"); static_assert(!is_reference_v, "instantiation of optional with a reference type is ill-formed"); static_assert(is_destructible_v, "instantiation of optional with a non-destructible type is ill-formed"); // LWG2756: conditionally explicit conversion from _Up struct _CheckOptionalArgsConstructor { template static constexpr bool __enable_implicit() { return is_constructible_v<_Tp, _Up&&> && is_convertible_v<_Up&&, _Tp>; } template static constexpr bool __enable_explicit() { return is_constructible_v<_Tp, _Up&&> && !is_convertible_v<_Up&&, _Tp>; } }; template using _CheckOptionalArgsCtor = conditional_t< !is_same_v, in_place_t> && !is_same_v, optional>, _CheckOptionalArgsConstructor, __check_tuple_constructor_fail >; template struct _CheckOptionalLikeConstructor { template > using __check_constructible_from_opt = __lazy_or< is_constructible<_Tp, _Opt&>, is_constructible<_Tp, _Opt const&>, is_constructible<_Tp, _Opt&&>, is_constructible<_Tp, _Opt const&&>, is_convertible<_Opt&, _Tp>, is_convertible<_Opt const&, _Tp>, is_convertible<_Opt&&, _Tp>, is_convertible<_Opt const&&, _Tp> >; template > using __check_assignable_from_opt = __lazy_or< is_assignable<_Tp&, _Opt&>, is_assignable<_Tp&, _Opt const&>, is_assignable<_Tp&, _Opt&&>, is_assignable<_Tp&, _Opt const&&> >; template static constexpr bool __enable_implicit() { return is_convertible<_QUp, _Tp>::value && !__check_constructible_from_opt<_Up>::value; } template static constexpr bool __enable_explicit() { return !is_convertible<_QUp, _Tp>::value && !__check_constructible_from_opt<_Up>::value; } template static constexpr bool __enable_assign() { // Construction and assignability of _Qup to _Tp has already been // checked. return !__check_constructible_from_opt<_Up>::value && !__check_assignable_from_opt<_Up>::value; } }; template using _CheckOptionalLikeCtor = conditional_t< __lazy_and< __lazy_not>, is_constructible<_Tp, _QualUp> >::value, _CheckOptionalLikeConstructor<_QualUp>, __check_tuple_constructor_fail >; template using _CheckOptionalLikeAssign = conditional_t< __lazy_and< __lazy_not>, is_constructible<_Tp, _QualUp>, is_assignable<_Tp&, _QualUp> >::value, _CheckOptionalLikeConstructor<_QualUp>, __check_tuple_constructor_fail >; public: _LIBCPP_INLINE_VISIBILITY constexpr optional() noexcept {} _LIBCPP_INLINE_VISIBILITY constexpr optional(const optional&) = default; _LIBCPP_INLINE_VISIBILITY constexpr optional(optional&&) = default; _LIBCPP_INLINE_VISIBILITY constexpr optional(nullopt_t) noexcept {} template > > _LIBCPP_INLINE_VISIBILITY constexpr explicit optional(in_place_t, _Args&&... __args) : __base(in_place, _VSTD::forward<_Args>(__args)...) {} template &, _Args...>> > _LIBCPP_INLINE_VISIBILITY constexpr explicit optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args) : __base(in_place, __il, _VSTD::forward<_Args>(__args)...) {} template ::template __enable_implicit<_Up>() , int> = 0> _LIBCPP_INLINE_VISIBILITY constexpr optional(_Up&& __v) : __base(in_place, _VSTD::forward<_Up>(__v)) {} template ::template __enable_explicit<_Up>() , int> = 0> _LIBCPP_INLINE_VISIBILITY constexpr explicit optional(_Up&& __v) : __base(in_place, _VSTD::forward<_Up>(__v)) {} // LWG2756: conditionally explicit conversion from const optional<_Up>& template ::template __enable_implicit<_Up>() , int> = 0> _LIBCPP_INLINE_VISIBILITY optional(const optional<_Up>& __v) { this->__construct_from(__v); } template ::template __enable_explicit<_Up>() , int> = 0> _LIBCPP_INLINE_VISIBILITY explicit optional(const optional<_Up>& __v) { this->__construct_from(__v); } // LWG2756: conditionally explicit conversion from optional<_Up>&& template ::template __enable_implicit<_Up>() , int> = 0> _LIBCPP_INLINE_VISIBILITY optional(optional<_Up>&& __v) { this->__construct_from(_VSTD::move(__v)); } template ::template __enable_explicit<_Up>() , int> = 0> _LIBCPP_INLINE_VISIBILITY explicit optional(optional<_Up>&& __v) { this->__construct_from(_VSTD::move(__v)); } _LIBCPP_INLINE_VISIBILITY optional& operator=(nullopt_t) noexcept { reset(); return *this; } _LIBCPP_INLINE_VISIBILITY optional& operator=(const optional&) = default; _LIBCPP_INLINE_VISIBILITY optional& operator=(optional&&) = default; // LWG2756 template , optional> && !(is_same_v<_Up, value_type> && is_scalar_v) >, is_constructible, is_assignable >::value> > _LIBCPP_INLINE_VISIBILITY optional& operator=(_Up&& __v) { if (this->has_value()) this->__get() = _VSTD::forward<_Up>(__v); else this->__construct(_VSTD::forward<_Up>(__v)); return *this; } // LWG2756 template ::template __enable_assign<_Up>() , int> = 0> _LIBCPP_INLINE_VISIBILITY optional& operator=(const optional<_Up>& __v) { this->__assign_from(__v); return *this; } // LWG2756 template ::template __enable_assign<_Up>() , int> = 0> _LIBCPP_INLINE_VISIBILITY optional& operator=(optional<_Up>&& __v) { this->__assign_from(_VSTD::move(__v)); return *this; } template > > _LIBCPP_INLINE_VISIBILITY _Tp & emplace(_Args&&... __args) { reset(); this->__construct(_VSTD::forward<_Args>(__args)...); return this->__get(); } template &, _Args...> > > _LIBCPP_INLINE_VISIBILITY _Tp & emplace(initializer_list<_Up> __il, _Args&&... __args) { reset(); this->__construct(__il, _VSTD::forward<_Args>(__args)...); return this->__get(); } _LIBCPP_INLINE_VISIBILITY void swap(optional& __opt) noexcept(is_nothrow_move_constructible_v && is_nothrow_swappable_v) { if (this->has_value() == __opt.has_value()) { using _VSTD::swap; if (this->has_value()) swap(this->__get(), __opt.__get()); } else { if (this->has_value()) { __opt.__construct(_VSTD::move(this->__get())); reset(); } else { this->__construct(_VSTD::move(__opt.__get())); __opt.reset(); } } } _LIBCPP_INLINE_VISIBILITY constexpr add_pointer_t operator->() const { _LIBCPP_ASSERT(this->has_value(), "optional operator-> called for disengaged value"); #ifndef _LIBCPP_HAS_NO_BUILTIN_ADDRESSOF return _VSTD::addressof(this->__get()); #else return __operator_arrow(__has_operator_addressof{}, this->__get()); #endif } _LIBCPP_INLINE_VISIBILITY constexpr add_pointer_t operator->() { _LIBCPP_ASSERT(this->has_value(), "optional operator-> called for disengaged value"); #ifndef _LIBCPP_HAS_NO_BUILTIN_ADDRESSOF return _VSTD::addressof(this->__get()); #else return __operator_arrow(__has_operator_addressof{}, this->__get()); #endif } _LIBCPP_INLINE_VISIBILITY constexpr const value_type& operator*() const& { _LIBCPP_ASSERT(this->has_value(), "optional operator* called for disengaged value"); return this->__get(); } _LIBCPP_INLINE_VISIBILITY constexpr value_type& operator*() & { _LIBCPP_ASSERT(this->has_value(), "optional operator* called for disengaged value"); return this->__get(); } _LIBCPP_INLINE_VISIBILITY constexpr value_type&& operator*() && { _LIBCPP_ASSERT(this->has_value(), "optional operator* called for disengaged value"); return _VSTD::move(this->__get()); } _LIBCPP_INLINE_VISIBILITY constexpr const value_type&& operator*() const&& { _LIBCPP_ASSERT(this->has_value(), "optional operator* called for disengaged value"); return _VSTD::move(this->__get()); } _LIBCPP_INLINE_VISIBILITY constexpr explicit operator bool() const noexcept { return has_value(); } using __base::has_value; using __base::__get; _LIBCPP_INLINE_VISIBILITY constexpr value_type const& value() const& { if (!this->has_value()) __throw_bad_optional_access(); return this->__get(); } _LIBCPP_INLINE_VISIBILITY constexpr value_type& value() & { if (!this->has_value()) __throw_bad_optional_access(); return this->__get(); } _LIBCPP_INLINE_VISIBILITY constexpr value_type&& value() && { if (!this->has_value()) __throw_bad_optional_access(); return _VSTD::move(this->__get()); } _LIBCPP_INLINE_VISIBILITY constexpr value_type const&& value() const&& { if (!this->has_value()) __throw_bad_optional_access(); return _VSTD::move(this->__get()); } template _LIBCPP_INLINE_VISIBILITY constexpr value_type value_or(_Up&& __v) const& { static_assert(is_copy_constructible_v, "optional::value_or: T must be copy constructible"); static_assert(is_convertible_v<_Up, value_type>, "optional::value_or: U must be convertible to T"); return this->has_value() ? this->__get() : static_cast(_VSTD::forward<_Up>(__v)); } template _LIBCPP_INLINE_VISIBILITY constexpr value_type value_or(_Up&& __v) && { static_assert(is_move_constructible_v, "optional::value_or: T must be move constructible"); static_assert(is_convertible_v<_Up, value_type>, "optional::value_or: U must be convertible to T"); return this->has_value() ? _VSTD::move(this->__get()) : static_cast(_VSTD::forward<_Up>(__v)); } using __base::reset; private: template _LIBCPP_INLINE_VISIBILITY static _Up* __operator_arrow(true_type, _Up& __x) { return _VSTD::addressof(__x); } template _LIBCPP_INLINE_VISIBILITY static constexpr _Up* __operator_arrow(false_type, _Up& __x) { return &__x; } }; // Comparisons between optionals template _LIBCPP_INLINE_VISIBILITY constexpr enable_if_t< is_convertible_v() == _VSTD::declval()), bool>, bool > operator==(const optional<_Tp>& __x, const optional<_Up>& __y) { if (static_cast(__x) != static_cast(__y)) return false; if (!static_cast(__x)) return true; return *__x == *__y; } template _LIBCPP_INLINE_VISIBILITY constexpr enable_if_t< is_convertible_v() != _VSTD::declval()), bool>, bool > operator!=(const optional<_Tp>& __x, const optional<_Up>& __y) { if (static_cast(__x) != static_cast(__y)) return true; if (!static_cast(__x)) return false; return *__x != *__y; } template _LIBCPP_INLINE_VISIBILITY constexpr enable_if_t< is_convertible_v() < _VSTD::declval()), bool>, bool > operator<(const optional<_Tp>& __x, const optional<_Up>& __y) { if (!static_cast(__y)) return false; if (!static_cast(__x)) return true; return *__x < *__y; } template _LIBCPP_INLINE_VISIBILITY constexpr enable_if_t< is_convertible_v() > _VSTD::declval()), bool>, bool > operator>(const optional<_Tp>& __x, const optional<_Up>& __y) { if (!static_cast(__x)) return false; if (!static_cast(__y)) return true; return *__x > *__y; } template _LIBCPP_INLINE_VISIBILITY constexpr enable_if_t< is_convertible_v() <= _VSTD::declval()), bool>, bool > operator<=(const optional<_Tp>& __x, const optional<_Up>& __y) { if (!static_cast(__x)) return true; if (!static_cast(__y)) return false; return *__x <= *__y; } template _LIBCPP_INLINE_VISIBILITY constexpr enable_if_t< is_convertible_v() >= _VSTD::declval()), bool>, bool > operator>=(const optional<_Tp>& __x, const optional<_Up>& __y) { if (!static_cast(__y)) return true; if (!static_cast(__x)) return false; return *__x >= *__y; } // Comparisons with nullopt template _LIBCPP_INLINE_VISIBILITY constexpr bool operator==(const optional<_Tp>& __x, nullopt_t) noexcept { return !static_cast(__x); } template _LIBCPP_INLINE_VISIBILITY constexpr bool operator==(nullopt_t, const optional<_Tp>& __x) noexcept { return !static_cast(__x); } template _LIBCPP_INLINE_VISIBILITY constexpr bool operator!=(const optional<_Tp>& __x, nullopt_t) noexcept { return static_cast(__x); } template _LIBCPP_INLINE_VISIBILITY constexpr bool operator!=(nullopt_t, const optional<_Tp>& __x) noexcept { return static_cast(__x); } template _LIBCPP_INLINE_VISIBILITY constexpr bool operator<(const optional<_Tp>&, nullopt_t) noexcept { return false; } template _LIBCPP_INLINE_VISIBILITY constexpr bool operator<(nullopt_t, const optional<_Tp>& __x) noexcept { return static_cast(__x); } template _LIBCPP_INLINE_VISIBILITY constexpr bool operator<=(const optional<_Tp>& __x, nullopt_t) noexcept { return !static_cast(__x); } template _LIBCPP_INLINE_VISIBILITY constexpr bool operator<=(nullopt_t, const optional<_Tp>&) noexcept { return true; } template _LIBCPP_INLINE_VISIBILITY constexpr bool operator>(const optional<_Tp>& __x, nullopt_t) noexcept { return static_cast(__x); } template _LIBCPP_INLINE_VISIBILITY constexpr bool operator>(nullopt_t, const optional<_Tp>&) noexcept { return false; } template _LIBCPP_INLINE_VISIBILITY constexpr bool operator>=(const optional<_Tp>&, nullopt_t) noexcept { return true; } template _LIBCPP_INLINE_VISIBILITY constexpr bool operator>=(nullopt_t, const optional<_Tp>& __x) noexcept { return !static_cast(__x); } // Comparisons with T template _LIBCPP_INLINE_VISIBILITY constexpr enable_if_t< is_convertible_v() == _VSTD::declval()), bool>, bool > operator==(const optional<_Tp>& __x, const _Up& __v) { return static_cast(__x) ? *__x == __v : false; } template _LIBCPP_INLINE_VISIBILITY constexpr enable_if_t< is_convertible_v() == _VSTD::declval()), bool>, bool > operator==(const _Tp& __v, const optional<_Up>& __x) { return static_cast(__x) ? __v == *__x : false; } template _LIBCPP_INLINE_VISIBILITY constexpr enable_if_t< is_convertible_v() != _VSTD::declval()), bool>, bool > operator!=(const optional<_Tp>& __x, const _Up& __v) { return static_cast(__x) ? *__x != __v : true; } template _LIBCPP_INLINE_VISIBILITY constexpr enable_if_t< is_convertible_v() != _VSTD::declval()), bool>, bool > operator!=(const _Tp& __v, const optional<_Up>& __x) { return static_cast(__x) ? __v != *__x : true; } template _LIBCPP_INLINE_VISIBILITY constexpr enable_if_t< is_convertible_v() < _VSTD::declval()), bool>, bool > operator<(const optional<_Tp>& __x, const _Up& __v) { return static_cast(__x) ? *__x < __v : true; } template _LIBCPP_INLINE_VISIBILITY constexpr enable_if_t< is_convertible_v() < _VSTD::declval()), bool>, bool > operator<(const _Tp& __v, const optional<_Up>& __x) { return static_cast(__x) ? __v < *__x : false; } template _LIBCPP_INLINE_VISIBILITY constexpr enable_if_t< is_convertible_v() <= _VSTD::declval()), bool>, bool > operator<=(const optional<_Tp>& __x, const _Up& __v) { return static_cast(__x) ? *__x <= __v : true; } template _LIBCPP_INLINE_VISIBILITY constexpr enable_if_t< is_convertible_v() <= _VSTD::declval()), bool>, bool > operator<=(const _Tp& __v, const optional<_Up>& __x) { return static_cast(__x) ? __v <= *__x : false; } template _LIBCPP_INLINE_VISIBILITY constexpr enable_if_t< is_convertible_v() > _VSTD::declval()), bool>, bool > operator>(const optional<_Tp>& __x, const _Up& __v) { return static_cast(__x) ? *__x > __v : false; } template _LIBCPP_INLINE_VISIBILITY constexpr enable_if_t< is_convertible_v() > _VSTD::declval()), bool>, bool > operator>(const _Tp& __v, const optional<_Up>& __x) { return static_cast(__x) ? __v > *__x : true; } template _LIBCPP_INLINE_VISIBILITY constexpr enable_if_t< is_convertible_v() >= _VSTD::declval()), bool>, bool > operator>=(const optional<_Tp>& __x, const _Up& __v) { return static_cast(__x) ? *__x >= __v : false; } template _LIBCPP_INLINE_VISIBILITY constexpr enable_if_t< is_convertible_v() >= _VSTD::declval()), bool>, bool > operator>=(const _Tp& __v, const optional<_Up>& __x) { return static_cast(__x) ? __v >= *__x : true; } template inline _LIBCPP_INLINE_VISIBILITY enable_if_t< is_move_constructible_v<_Tp> && is_swappable_v<_Tp>, void > swap(optional<_Tp>& __x, optional<_Tp>& __y) noexcept(noexcept(__x.swap(__y))) { __x.swap(__y); } template _LIBCPP_INLINE_VISIBILITY constexpr optional> make_optional(_Tp&& __v) { return optional>(_VSTD::forward<_Tp>(__v)); } template _LIBCPP_INLINE_VISIBILITY constexpr optional<_Tp> make_optional(_Args&&... __args) { return optional<_Tp>(in_place, _VSTD::forward<_Args>(__args)...); } template _LIBCPP_INLINE_VISIBILITY constexpr optional<_Tp> make_optional(initializer_list<_Up> __il, _Args&&... __args) { return optional<_Tp>(in_place, __il, _VSTD::forward<_Args>(__args)...); } template struct _LIBCPP_TEMPLATE_VIS hash< __enable_hash_helper, remove_const_t<_Tp>> > { typedef optional<_Tp> argument_type; typedef size_t result_type; _LIBCPP_INLINE_VISIBILITY result_type operator()(const argument_type& __opt) const { return static_cast(__opt) ? hash>()(*__opt) : 0; } }; _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP_STD_VER > 14 _LIBCPP_POP_MACROS #endif // _LIBCPP_OPTIONAL diff --git a/include/regex b/include/regex index 443c2e303465..77ca648109b2 100644 --- a/include/regex +++ b/include/regex @@ -1,6569 +1,6569 @@ // -*- C++ -*- //===--------------------------- regex ------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef _LIBCPP_REGEX #define _LIBCPP_REGEX /* regex synopsis #include namespace std { namespace regex_constants { emum syntax_option_type { icase = unspecified, nosubs = unspecified, optimize = unspecified, collate = unspecified, ECMAScript = unspecified, basic = unspecified, extended = unspecified, awk = unspecified, grep = unspecified, egrep = unspecified }; constexpr syntax_option_type operator~(syntax_option_type f); constexpr syntax_option_type operator&(syntax_option_type lhs, syntax_option_type rhs); constexpr syntax_option_type operator|(syntax_option_type lhs, syntax_option_type rhs); enum match_flag_type { match_default = 0, match_not_bol = unspecified, match_not_eol = unspecified, match_not_bow = unspecified, match_not_eow = unspecified, match_any = unspecified, match_not_null = unspecified, match_continuous = unspecified, match_prev_avail = unspecified, format_default = 0, format_sed = unspecified, format_no_copy = unspecified, format_first_only = unspecified }; constexpr match_flag_type operator~(match_flag_type f); constexpr match_flag_type operator&(match_flag_type lhs, match_flag_type rhs); constexpr match_flag_type operator|(match_flag_type lhs, match_flag_type rhs); enum error_type { error_collate = unspecified, error_ctype = unspecified, error_escape = unspecified, error_backref = unspecified, error_brack = unspecified, error_paren = unspecified, error_brace = unspecified, error_badbrace = unspecified, error_range = unspecified, error_space = unspecified, error_badrepeat = unspecified, error_complexity = unspecified, error_stack = unspecified }; } // regex_constants class regex_error : public runtime_error { public: explicit regex_error(regex_constants::error_type ecode); regex_constants::error_type code() const; }; template struct regex_traits { public: typedef charT char_type; typedef basic_string string_type; typedef locale locale_type; typedef /bitmask_type/ char_class_type; regex_traits(); static size_t length(const char_type* p); charT translate(charT c) const; charT translate_nocase(charT c) const; template string_type transform(ForwardIterator first, ForwardIterator last) const; template string_type transform_primary( ForwardIterator first, ForwardIterator last) const; template string_type lookup_collatename(ForwardIterator first, ForwardIterator last) const; template char_class_type lookup_classname(ForwardIterator first, ForwardIterator last, bool icase = false) const; bool isctype(charT c, char_class_type f) const; int value(charT ch, int radix) const; locale_type imbue(locale_type l); locale_type getloc()const; }; template > class basic_regex { public: // types: typedef charT value_type; typedef traits traits_type; typedef typename traits::string_type string_type; typedef regex_constants::syntax_option_type flag_type; typedef typename traits::locale_type locale_type; // constants: static constexpr regex_constants::syntax_option_type icase = regex_constants::icase; static constexpr regex_constants::syntax_option_type nosubs = regex_constants::nosubs; static constexpr regex_constants::syntax_option_type optimize = regex_constants::optimize; static constexpr regex_constants::syntax_option_type collate = regex_constants::collate; static constexpr regex_constants::syntax_option_type ECMAScript = regex_constants::ECMAScript; static constexpr regex_constants::syntax_option_type basic = regex_constants::basic; static constexpr regex_constants::syntax_option_type extended = regex_constants::extended; static constexpr regex_constants::syntax_option_type awk = regex_constants::awk; static constexpr regex_constants::syntax_option_type grep = regex_constants::grep; static constexpr regex_constants::syntax_option_type egrep = regex_constants::egrep; // construct/copy/destroy: basic_regex(); explicit basic_regex(const charT* p, flag_type f = regex_constants::ECMAScript); basic_regex(const charT* p, size_t len, flag_type f = regex_constants::ECMAScript); basic_regex(const basic_regex&); basic_regex(basic_regex&&) noexcept; template explicit basic_regex(const basic_string& p, flag_type f = regex_constants::ECMAScript); template basic_regex(ForwardIterator first, ForwardIterator last, flag_type f = regex_constants::ECMAScript); basic_regex(initializer_list, flag_type = regex_constants::ECMAScript); ~basic_regex(); basic_regex& operator=(const basic_regex&); basic_regex& operator=(basic_regex&&) noexcept; basic_regex& operator=(const charT* ptr); basic_regex& operator=(initializer_list il); template basic_regex& operator=(const basic_string& p); // assign: basic_regex& assign(const basic_regex& that); basic_regex& assign(basic_regex&& that) noexcept; basic_regex& assign(const charT* ptr, flag_type f = regex_constants::ECMAScript); basic_regex& assign(const charT* p, size_t len, flag_type f); template basic_regex& assign(const basic_string& s, flag_type f = regex_constants::ECMAScript); template basic_regex& assign(InputIterator first, InputIterator last, flag_type f = regex_constants::ECMAScript); basic_regex& assign(initializer_list, flag_type = regex_constants::ECMAScript); // const operations: unsigned mark_count() const; flag_type flags() const; // locale: locale_type imbue(locale_type loc); locale_type getloc() const; // swap: void swap(basic_regex&); }; typedef basic_regex regex; typedef basic_regex wregex; template void swap(basic_regex& e1, basic_regex& e2); template class sub_match : public pair { public: typedef typename iterator_traits::value_type value_type; typedef typename iterator_traits::difference_type difference_type; typedef BidirectionalIterator iterator; typedef basic_string string_type; bool matched; constexpr sub_match(); difference_type length() const; operator string_type() const; string_type str() const; int compare(const sub_match& s) const; int compare(const string_type& s) const; int compare(const value_type* s) const; }; typedef sub_match csub_match; typedef sub_match wcsub_match; typedef sub_match ssub_match; typedef sub_match wssub_match; template bool operator==(const sub_match& lhs, const sub_match& rhs); template bool operator!=(const sub_match& lhs, const sub_match& rhs); template bool operator<(const sub_match& lhs, const sub_match& rhs); template bool operator<=(const sub_match& lhs, const sub_match& rhs); template bool operator>=(const sub_match& lhs, const sub_match& rhs); template bool operator>(const sub_match& lhs, const sub_match& rhs); template bool operator==(const basic_string::value_type, ST, SA>& lhs, const sub_match& rhs); template bool operator!=(const basic_string::value_type, ST, SA>& lhs, const sub_match& rhs); template bool operator<(const basic_string::value_type, ST, SA>& lhs, const sub_match& rhs); template bool operator>(const basic_string::value_type, ST, SA>& lhs, const sub_match& rhs); template bool operator>=(const basic_string::value_type, ST, SA>& lhs, const sub_match& rhs); template bool operator<=(const basic_string::value_type, ST, SA>& lhs, const sub_match& rhs); template bool operator==(const sub_match& lhs, const basic_string::value_type, ST, SA>& rhs); template bool operator!=(const sub_match& lhs, const basic_string::value_type, ST, SA>& rhs); template bool operator<(const sub_match& lhs, const basic_string::value_type, ST, SA>& rhs); template bool operator>(const sub_match& lhs, const basic_string::value_type, ST, SA>& rhs); template bool operator>=(const sub_match& lhs, const basic_string::value_type, ST, SA>& rhs); template bool operator<=(const sub_match& lhs, const basic_string::value_type, ST, SA>& rhs); template bool operator==(typename iterator_traits::value_type const* lhs, const sub_match& rhs); template bool operator!=(typename iterator_traits::value_type const* lhs, const sub_match& rhs); template bool operator<(typename iterator_traits::value_type const* lhs, const sub_match& rhs); template bool operator>(typename iterator_traits::value_type const* lhs, const sub_match& rhs); template bool operator>=(typename iterator_traits::value_type const* lhs, const sub_match& rhs); template bool operator<=(typename iterator_traits::value_type const* lhs, const sub_match& rhs); template bool operator==(const sub_match& lhs, typename iterator_traits::value_type const* rhs); template bool operator!=(const sub_match& lhs, typename iterator_traits::value_type const* rhs); template bool operator<(const sub_match& lhs, typename iterator_traits::value_type const* rhs); template bool operator>(const sub_match& lhs, typename iterator_traits::value_type const* rhs); template bool operator>=(const sub_match& lhs, typename iterator_traits::value_type const* rhs); template bool operator<=(const sub_match& lhs, typename iterator_traits::value_type const* rhs); template bool operator==(typename iterator_traits::value_type const& lhs, const sub_match& rhs); template bool operator!=(typename iterator_traits::value_type const& lhs, const sub_match& rhs); template bool operator<(typename iterator_traits::value_type const& lhs, const sub_match& rhs); template bool operator>(typename iterator_traits::value_type const& lhs, const sub_match& rhs); template bool operator>=(typename iterator_traits::value_type const& lhs, const sub_match& rhs); template bool operator<=(typename iterator_traits::value_type const& lhs, const sub_match& rhs); template bool operator==(const sub_match& lhs, typename iterator_traits::value_type const& rhs); template bool operator!=(const sub_match& lhs, typename iterator_traits::value_type const& rhs); template bool operator<(const sub_match& lhs, typename iterator_traits::value_type const& rhs); template bool operator>(const sub_match& lhs, typename iterator_traits::value_type const& rhs); template bool operator>=(const sub_match& lhs, typename iterator_traits::value_type const& rhs); template bool operator<=(const sub_match& lhs, typename iterator_traits::value_type const& rhs); template basic_ostream& operator<<(basic_ostream& os, const sub_match& m); template >> class match_results { public: typedef sub_match value_type; typedef const value_type& const_reference; typedef value_type& reference; typedef /implementation-defined/ const_iterator; typedef const_iterator iterator; typedef typename iterator_traits::difference_type difference_type; typedef typename allocator_traits::size_type size_type; typedef Allocator allocator_type; typedef typename iterator_traits::value_type char_type; typedef basic_string string_type; // construct/copy/destroy: explicit match_results(const Allocator& a = Allocator()); match_results(const match_results& m); match_results(match_results&& m) noexcept; match_results& operator=(const match_results& m); match_results& operator=(match_results&& m); ~match_results(); bool ready() const; // size: size_type size() const; size_type max_size() const; bool empty() const; // element access: difference_type length(size_type sub = 0) const; difference_type position(size_type sub = 0) const; string_type str(size_type sub = 0) const; const_reference operator[](size_type n) const; const_reference prefix() const; const_reference suffix() const; const_iterator begin() const; const_iterator end() const; const_iterator cbegin() const; const_iterator cend() const; // format: template OutputIter format(OutputIter out, const char_type* fmt_first, const char_type* fmt_last, regex_constants::match_flag_type flags = regex_constants::format_default) const; template OutputIter format(OutputIter out, const basic_string& fmt, regex_constants::match_flag_type flags = regex_constants::format_default) const; template basic_string format(const basic_string& fmt, regex_constants::match_flag_type flags = regex_constants::format_default) const; string_type format(const char_type* fmt, regex_constants::match_flag_type flags = regex_constants::format_default) const; // allocator: allocator_type get_allocator() const; // swap: void swap(match_results& that); }; typedef match_results cmatch; typedef match_results wcmatch; typedef match_results smatch; typedef match_results wsmatch; template bool operator==(const match_results& m1, const match_results& m2); template bool operator!=(const match_results& m1, const match_results& m2); template void swap(match_results& m1, match_results& m2); template bool regex_match(BidirectionalIterator first, BidirectionalIterator last, match_results& m, const basic_regex& e, regex_constants::match_flag_type flags = regex_constants::match_default); template bool regex_match(BidirectionalIterator first, BidirectionalIterator last, const basic_regex& e, regex_constants::match_flag_type flags = regex_constants::match_default); template bool regex_match(const charT* str, match_results& m, const basic_regex& e, regex_constants::match_flag_type flags = regex_constants::match_default); template bool regex_match(const basic_string& s, match_results::const_iterator, Allocator>& m, const basic_regex& e, regex_constants::match_flag_type flags = regex_constants::match_default); template bool regex_match(const basic_string&& s, match_results::const_iterator, Allocator>& m, const basic_regex& e, regex_constants::match_flag_type flags = regex_constants::match_default) = delete; // C++14 template bool regex_match(const charT* str, const basic_regex& e, regex_constants::match_flag_type flags = regex_constants::match_default); template bool regex_match(const basic_string& s, const basic_regex& e, regex_constants::match_flag_type flags = regex_constants::match_default); template bool regex_search(BidirectionalIterator first, BidirectionalIterator last, match_results& m, const basic_regex& e, regex_constants::match_flag_type flags = regex_constants::match_default); template bool regex_search(BidirectionalIterator first, BidirectionalIterator last, const basic_regex& e, regex_constants::match_flag_type flags = regex_constants::match_default); template bool regex_search(const charT* str, match_results& m, const basic_regex& e, regex_constants::match_flag_type flags = regex_constants::match_default); template bool regex_search(const charT* str, const basic_regex& e, regex_constants::match_flag_type flags = regex_constants::match_default); template bool regex_search(const basic_string& s, const basic_regex& e, regex_constants::match_flag_type flags = regex_constants::match_default); template bool regex_search(const basic_string& s, match_results::const_iterator, Allocator>& m, const basic_regex& e, regex_constants::match_flag_type flags = regex_constants::match_default); template bool regex_search(const basic_string&& s, match_results::const_iterator, Allocator>& m, const basic_regex& e, regex_constants::match_flag_type flags = regex_constants::match_default) = delete; // C++14 template OutputIterator regex_replace(OutputIterator out, BidirectionalIterator first, BidirectionalIterator last, const basic_regex& e, const basic_string& fmt, regex_constants::match_flag_type flags = regex_constants::match_default); template OutputIterator regex_replace(OutputIterator out, BidirectionalIterator first, BidirectionalIterator last, const basic_regex& e, const charT* fmt, regex_constants::match_flag_type flags = regex_constants::match_default); template > basic_string regex_replace(const basic_string& s, const basic_regex& e, const basic_string& fmt, regex_constants::match_flag_type flags = regex_constants::match_default); template basic_string regex_replace(const basic_string& s, const basic_regex& e, const charT* fmt, regex_constants::match_flag_type flags = regex_constants::match_default); template basic_string regex_replace(const charT* s, const basic_regex& e, const basic_string& fmt, regex_constants::match_flag_type flags = regex_constants::match_default); template basic_string regex_replace(const charT* s, const basic_regex& e, const charT* fmt, regex_constants::match_flag_type flags = regex_constants::match_default); template ::value_type, class traits = regex_traits> class regex_iterator { public: typedef basic_regex regex_type; typedef match_results value_type; typedef ptrdiff_t difference_type; typedef const value_type* pointer; typedef const value_type& reference; typedef forward_iterator_tag iterator_category; regex_iterator(); regex_iterator(BidirectionalIterator a, BidirectionalIterator b, const regex_type& re, regex_constants::match_flag_type m = regex_constants::match_default); regex_iterator(_BidirectionalIterator __a, _BidirectionalIterator __b, const regex_type&& __re, regex_constants::match_flag_type __m = regex_constants::match_default) = delete; // C++14 regex_iterator(const regex_iterator&); regex_iterator& operator=(const regex_iterator&); bool operator==(const regex_iterator&) const; bool operator!=(const regex_iterator&) const; const value_type& operator*() const; const value_type* operator->() const; regex_iterator& operator++(); regex_iterator operator++(int); }; typedef regex_iterator cregex_iterator; typedef regex_iterator wcregex_iterator; typedef regex_iterator sregex_iterator; typedef regex_iterator wsregex_iterator; template ::value_type, class traits = regex_traits> class regex_token_iterator { public: typedef basic_regex regex_type; typedef sub_match value_type; typedef ptrdiff_t difference_type; typedef const value_type* pointer; typedef const value_type& reference; typedef forward_iterator_tag iterator_category; regex_token_iterator(); regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, const regex_type& re, int submatch = 0, regex_constants::match_flag_type m = regex_constants::match_default); regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, const regex_type&& re, int submatch = 0, regex_constants::match_flag_type m = regex_constants::match_default) = delete; // C++14 regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, const regex_type& re, const vector& submatches, regex_constants::match_flag_type m = regex_constants::match_default); regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, const regex_type&& re, const vector& submatches, regex_constants::match_flag_type m = regex_constants::match_default) = delete; // C++14 regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, const regex_type& re, initializer_list submatches, regex_constants::match_flag_type m = regex_constants::match_default); regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, const regex_type&& re, initializer_list submatches, regex_constants::match_flag_type m = regex_constants::match_default) = delete; // C++14 template regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, const regex_type& re, const int (&submatches)[N], regex_constants::match_flag_type m = regex_constants::match_default); template regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, const regex_type& re, const int (&submatches)[N], regex_constants::match_flag_type m = regex_constants::match_default) = delete // C++14; regex_token_iterator(const regex_token_iterator&); regex_token_iterator& operator=(const regex_token_iterator&); bool operator==(const regex_token_iterator&) const; bool operator!=(const regex_token_iterator&) const; const value_type& operator*() const; const value_type* operator->() const; regex_token_iterator& operator++(); regex_token_iterator operator++(int); }; typedef regex_token_iterator cregex_token_iterator; typedef regex_token_iterator wcregex_token_iterator; typedef regex_token_iterator sregex_token_iterator; typedef regex_token_iterator wsregex_token_iterator; } // std */ #include <__config> #include #include <__locale> #include #include #include #include #include #include #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header #endif _LIBCPP_PUSH_MACROS #include <__undef_macros> _LIBCPP_BEGIN_NAMESPACE_STD namespace regex_constants { // syntax_option_type enum syntax_option_type { icase = 1 << 0, nosubs = 1 << 1, optimize = 1 << 2, collate = 1 << 3, ECMAScript = 0, basic = 1 << 4, extended = 1 << 5, awk = 1 << 6, grep = 1 << 7, egrep = 1 << 8 }; inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR syntax_option_type operator~(syntax_option_type __x) { return syntax_option_type(~int(__x) & 0x1FF); } inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR syntax_option_type operator&(syntax_option_type __x, syntax_option_type __y) { return syntax_option_type(int(__x) & int(__y)); } inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR syntax_option_type operator|(syntax_option_type __x, syntax_option_type __y) { return syntax_option_type(int(__x) | int(__y)); } inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR syntax_option_type operator^(syntax_option_type __x, syntax_option_type __y) { return syntax_option_type(int(__x) ^ int(__y)); } inline _LIBCPP_INLINE_VISIBILITY syntax_option_type& operator&=(syntax_option_type& __x, syntax_option_type __y) { __x = __x & __y; return __x; } inline _LIBCPP_INLINE_VISIBILITY syntax_option_type& operator|=(syntax_option_type& __x, syntax_option_type __y) { __x = __x | __y; return __x; } inline _LIBCPP_INLINE_VISIBILITY syntax_option_type& operator^=(syntax_option_type& __x, syntax_option_type __y) { __x = __x ^ __y; return __x; } // match_flag_type enum match_flag_type { match_default = 0, match_not_bol = 1 << 0, match_not_eol = 1 << 1, match_not_bow = 1 << 2, match_not_eow = 1 << 3, match_any = 1 << 4, match_not_null = 1 << 5, match_continuous = 1 << 6, match_prev_avail = 1 << 7, format_default = 0, format_sed = 1 << 8, format_no_copy = 1 << 9, format_first_only = 1 << 10, __no_update_pos = 1 << 11, __full_match = 1 << 12 }; inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR match_flag_type operator~(match_flag_type __x) { return match_flag_type(~int(__x) & 0x0FFF); } inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR match_flag_type operator&(match_flag_type __x, match_flag_type __y) { return match_flag_type(int(__x) & int(__y)); } inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR match_flag_type operator|(match_flag_type __x, match_flag_type __y) { return match_flag_type(int(__x) | int(__y)); } inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR match_flag_type operator^(match_flag_type __x, match_flag_type __y) { return match_flag_type(int(__x) ^ int(__y)); } inline _LIBCPP_INLINE_VISIBILITY match_flag_type& operator&=(match_flag_type& __x, match_flag_type __y) { __x = __x & __y; return __x; } inline _LIBCPP_INLINE_VISIBILITY match_flag_type& operator|=(match_flag_type& __x, match_flag_type __y) { __x = __x | __y; return __x; } inline _LIBCPP_INLINE_VISIBILITY match_flag_type& operator^=(match_flag_type& __x, match_flag_type __y) { __x = __x ^ __y; return __x; } enum error_type { error_collate = 1, error_ctype, error_escape, error_backref, error_brack, error_paren, error_brace, error_badbrace, error_range, error_space, error_badrepeat, error_complexity, error_stack, __re_err_grammar, __re_err_empty, __re_err_unknown }; } // regex_constants class _LIBCPP_EXCEPTION_ABI regex_error : public runtime_error { regex_constants::error_type __code_; public: explicit regex_error(regex_constants::error_type __ecode); virtual ~regex_error() throw(); _LIBCPP_INLINE_VISIBILITY regex_constants::error_type code() const {return __code_;} }; template _LIBCPP_NORETURN inline _LIBCPP_ALWAYS_INLINE void __throw_regex_error() { #ifndef _LIBCPP_NO_EXCEPTIONS throw regex_error(_Ev); #else _VSTD::abort(); #endif } template struct _LIBCPP_TEMPLATE_VIS regex_traits { public: typedef _CharT char_type; typedef basic_string string_type; typedef locale locale_type; typedef ctype_base::mask char_class_type; #if defined(__mips__) && defined(__GLIBC__) static const char_class_type __regex_word = static_cast(_ISbit(15)); #else static const char_class_type __regex_word = 0x80; #endif private: locale __loc_; const ctype* __ct_; const collate* __col_; public: regex_traits(); _LIBCPP_INLINE_VISIBILITY static size_t length(const char_type* __p) {return char_traits::length(__p);} _LIBCPP_INLINE_VISIBILITY char_type translate(char_type __c) const {return __c;} char_type translate_nocase(char_type __c) const; template string_type transform(_ForwardIterator __f, _ForwardIterator __l) const; template _LIBCPP_INLINE_VISIBILITY string_type transform_primary( _ForwardIterator __f, _ForwardIterator __l) const {return __transform_primary(__f, __l, char_type());} template _LIBCPP_INLINE_VISIBILITY string_type lookup_collatename(_ForwardIterator __f, _ForwardIterator __l) const {return __lookup_collatename(__f, __l, char_type());} template _LIBCPP_INLINE_VISIBILITY char_class_type lookup_classname(_ForwardIterator __f, _ForwardIterator __l, bool __icase = false) const {return __lookup_classname(__f, __l, __icase, char_type());} bool isctype(char_type __c, char_class_type __m) const; _LIBCPP_INLINE_VISIBILITY int value(char_type __ch, int __radix) const {return __regex_traits_value(__ch, __radix);} locale_type imbue(locale_type __l); _LIBCPP_INLINE_VISIBILITY locale_type getloc()const {return __loc_;} private: void __init(); template string_type __transform_primary(_ForwardIterator __f, _ForwardIterator __l, char) const; template string_type __transform_primary(_ForwardIterator __f, _ForwardIterator __l, wchar_t) const; template string_type __lookup_collatename(_ForwardIterator __f, _ForwardIterator __l, char) const; template string_type __lookup_collatename(_ForwardIterator __f, _ForwardIterator __l, wchar_t) const; template char_class_type __lookup_classname(_ForwardIterator __f, _ForwardIterator __l, bool __icase, char) const; template char_class_type __lookup_classname(_ForwardIterator __f, _ForwardIterator __l, bool __icase, wchar_t) const; static int __regex_traits_value(unsigned char __ch, int __radix); _LIBCPP_INLINE_VISIBILITY int __regex_traits_value(char __ch, int __radix) const {return __regex_traits_value(static_cast(__ch), __radix);} _LIBCPP_INLINE_VISIBILITY int __regex_traits_value(wchar_t __ch, int __radix) const; }; template const typename regex_traits<_CharT>::char_class_type regex_traits<_CharT>::__regex_word; template regex_traits<_CharT>::regex_traits() { __init(); } template typename regex_traits<_CharT>::char_type regex_traits<_CharT>::translate_nocase(char_type __c) const { return __ct_->tolower(__c); } template template typename regex_traits<_CharT>::string_type regex_traits<_CharT>::transform(_ForwardIterator __f, _ForwardIterator __l) const { string_type __s(__f, __l); return __col_->transform(__s.data(), __s.data() + __s.size()); } template void regex_traits<_CharT>::__init() { __ct_ = &use_facet >(__loc_); __col_ = &use_facet >(__loc_); } template typename regex_traits<_CharT>::locale_type regex_traits<_CharT>::imbue(locale_type __l) { locale __r = __loc_; __loc_ = __l; __init(); return __r; } // transform_primary is very FreeBSD-specific template template typename regex_traits<_CharT>::string_type regex_traits<_CharT>::__transform_primary(_ForwardIterator __f, _ForwardIterator __l, char) const { const string_type __s(__f, __l); string_type __d = __col_->transform(__s.data(), __s.data() + __s.size()); switch (__d.size()) { case 1: break; case 12: __d[11] = __d[3]; break; default: __d.clear(); break; } return __d; } template template typename regex_traits<_CharT>::string_type regex_traits<_CharT>::__transform_primary(_ForwardIterator __f, _ForwardIterator __l, wchar_t) const { const string_type __s(__f, __l); string_type __d = __col_->transform(__s.data(), __s.data() + __s.size()); switch (__d.size()) { case 1: break; case 3: __d[2] = __d[0]; break; default: __d.clear(); break; } return __d; } // lookup_collatename is very FreeBSD-specific _LIBCPP_FUNC_VIS string __get_collation_name(const char* __s); template template typename regex_traits<_CharT>::string_type regex_traits<_CharT>::__lookup_collatename(_ForwardIterator __f, _ForwardIterator __l, char) const { string_type __s(__f, __l); string_type __r; if (!__s.empty()) { __r = __get_collation_name(__s.c_str()); if (__r.empty() && __s.size() <= 2) { __r = __col_->transform(__s.data(), __s.data() + __s.size()); if (__r.size() == 1 || __r.size() == 12) __r = __s; else __r.clear(); } } return __r; } template template typename regex_traits<_CharT>::string_type regex_traits<_CharT>::__lookup_collatename(_ForwardIterator __f, _ForwardIterator __l, wchar_t) const { string_type __s(__f, __l); string __n; __n.reserve(__s.size()); for (typename string_type::const_iterator __i = __s.begin(), __e = __s.end(); __i != __e; ++__i) { if (static_cast(*__i) >= 127) return string_type(); __n.push_back(char(*__i)); } string_type __r; if (!__s.empty()) { __n = __get_collation_name(__n.c_str()); if (!__n.empty()) __r.assign(__n.begin(), __n.end()); else if (__s.size() <= 2) { __r = __col_->transform(__s.data(), __s.data() + __s.size()); if (__r.size() == 1 || __r.size() == 3) __r = __s; else __r.clear(); } } return __r; } // lookup_classname regex_traits::char_class_type _LIBCPP_FUNC_VIS __get_classname(const char* __s, bool __icase); template template typename regex_traits<_CharT>::char_class_type regex_traits<_CharT>::__lookup_classname(_ForwardIterator __f, _ForwardIterator __l, bool __icase, char) const { string_type __s(__f, __l); __ct_->tolower(&__s[0], &__s[0] + __s.size()); return __get_classname(__s.c_str(), __icase); } template template typename regex_traits<_CharT>::char_class_type regex_traits<_CharT>::__lookup_classname(_ForwardIterator __f, _ForwardIterator __l, bool __icase, wchar_t) const { string_type __s(__f, __l); __ct_->tolower(&__s[0], &__s[0] + __s.size()); string __n; __n.reserve(__s.size()); for (typename string_type::const_iterator __i = __s.begin(), __e = __s.end(); __i != __e; ++__i) { if (static_cast(*__i) >= 127) return char_class_type(); __n.push_back(char(*__i)); } return __get_classname(__n.c_str(), __icase); } template bool regex_traits<_CharT>::isctype(char_type __c, char_class_type __m) const { if (__ct_->is(__m, __c)) return true; return (__c == '_' && (__m & __regex_word)); } template int regex_traits<_CharT>::__regex_traits_value(unsigned char __ch, int __radix) { if ((__ch & 0xF8u) == 0x30) // '0' <= __ch && __ch <= '7' return __ch - '0'; if (__radix != 8) { if ((__ch & 0xFEu) == 0x38) // '8' <= __ch && __ch <= '9' return __ch - '0'; if (__radix == 16) { __ch |= 0x20; // tolower if ('a' <= __ch && __ch <= 'f') return __ch - ('a' - 10); } } return -1; } template inline int regex_traits<_CharT>::__regex_traits_value(wchar_t __ch, int __radix) const { return __regex_traits_value(static_cast(__ct_->narrow(__ch, char_type())), __radix); } template class __node; template class _LIBCPP_TEMPLATE_VIS sub_match; template > > class _LIBCPP_TEMPLATE_VIS match_results; template struct __state { enum { __end_state = -1000, __consume_input, // -999 __begin_marked_expr, // -998 __end_marked_expr, // -997 __pop_state, // -996 __accept_and_consume, // -995 __accept_but_not_consume, // -994 __reject, // -993 __split, __repeat }; int __do_; const _CharT* __first_; const _CharT* __current_; const _CharT* __last_; vector > __sub_matches_; vector > __loop_data_; const __node<_CharT>* __node_; regex_constants::match_flag_type __flags_; bool __at_first_; _LIBCPP_INLINE_VISIBILITY __state() : __do_(0), __first_(nullptr), __current_(nullptr), __last_(nullptr), __node_(nullptr), __flags_() {} }; // __node template class __node { __node(const __node&); __node& operator=(const __node&); public: typedef _VSTD::__state<_CharT> __state; _LIBCPP_INLINE_VISIBILITY __node() {} _LIBCPP_INLINE_VISIBILITY virtual ~__node() {} _LIBCPP_INLINE_VISIBILITY virtual void __exec(__state&) const {}; _LIBCPP_INLINE_VISIBILITY virtual void __exec_split(bool, __state&) const {}; }; // __end_state template class __end_state : public __node<_CharT> { public: typedef _VSTD::__state<_CharT> __state; _LIBCPP_INLINE_VISIBILITY __end_state() {} virtual void __exec(__state&) const; }; template void __end_state<_CharT>::__exec(__state& __s) const { __s.__do_ = __state::__end_state; } // __has_one_state template class __has_one_state : public __node<_CharT> { __node<_CharT>* __first_; public: _LIBCPP_INLINE_VISIBILITY explicit __has_one_state(__node<_CharT>* __s) : __first_(__s) {} _LIBCPP_INLINE_VISIBILITY __node<_CharT>* first() const {return __first_;} _LIBCPP_INLINE_VISIBILITY __node<_CharT>*& first() {return __first_;} }; // __owns_one_state template class __owns_one_state : public __has_one_state<_CharT> { typedef __has_one_state<_CharT> base; public: _LIBCPP_INLINE_VISIBILITY explicit __owns_one_state(__node<_CharT>* __s) : base(__s) {} virtual ~__owns_one_state(); }; template __owns_one_state<_CharT>::~__owns_one_state() { delete this->first(); } // __empty_state template class __empty_state : public __owns_one_state<_CharT> { typedef __owns_one_state<_CharT> base; public: typedef _VSTD::__state<_CharT> __state; _LIBCPP_INLINE_VISIBILITY explicit __empty_state(__node<_CharT>* __s) : base(__s) {} virtual void __exec(__state&) const; }; template void __empty_state<_CharT>::__exec(__state& __s) const { __s.__do_ = __state::__accept_but_not_consume; __s.__node_ = this->first(); } // __empty_non_own_state template class __empty_non_own_state : public __has_one_state<_CharT> { typedef __has_one_state<_CharT> base; public: typedef _VSTD::__state<_CharT> __state; _LIBCPP_INLINE_VISIBILITY explicit __empty_non_own_state(__node<_CharT>* __s) : base(__s) {} virtual void __exec(__state&) const; }; template void __empty_non_own_state<_CharT>::__exec(__state& __s) const { __s.__do_ = __state::__accept_but_not_consume; __s.__node_ = this->first(); } // __repeat_one_loop template class __repeat_one_loop : public __has_one_state<_CharT> { typedef __has_one_state<_CharT> base; public: typedef _VSTD::__state<_CharT> __state; _LIBCPP_INLINE_VISIBILITY explicit __repeat_one_loop(__node<_CharT>* __s) : base(__s) {} virtual void __exec(__state&) const; }; template void __repeat_one_loop<_CharT>::__exec(__state& __s) const { __s.__do_ = __state::__repeat; __s.__node_ = this->first(); } // __owns_two_states template class __owns_two_states : public __owns_one_state<_CharT> { typedef __owns_one_state<_CharT> base; base* __second_; public: _LIBCPP_INLINE_VISIBILITY explicit __owns_two_states(__node<_CharT>* __s1, base* __s2) : base(__s1), __second_(__s2) {} virtual ~__owns_two_states(); _LIBCPP_INLINE_VISIBILITY base* second() const {return __second_;} _LIBCPP_INLINE_VISIBILITY base*& second() {return __second_;} }; template __owns_two_states<_CharT>::~__owns_two_states() { delete __second_; } // __loop template class __loop : public __owns_two_states<_CharT> { typedef __owns_two_states<_CharT> base; size_t __min_; size_t __max_; unsigned __loop_id_; unsigned __mexp_begin_; unsigned __mexp_end_; bool __greedy_; public: typedef _VSTD::__state<_CharT> __state; _LIBCPP_INLINE_VISIBILITY explicit __loop(unsigned __loop_id, __node<_CharT>* __s1, __owns_one_state<_CharT>* __s2, unsigned __mexp_begin, unsigned __mexp_end, bool __greedy = true, size_t __min = 0, size_t __max = numeric_limits::max()) : base(__s1, __s2), __min_(__min), __max_(__max), __loop_id_(__loop_id), __mexp_begin_(__mexp_begin), __mexp_end_(__mexp_end), __greedy_(__greedy) {} virtual void __exec(__state& __s) const; virtual void __exec_split(bool __second, __state& __s) const; private: _LIBCPP_INLINE_VISIBILITY void __init_repeat(__state& __s) const { __s.__loop_data_[__loop_id_].second = __s.__current_; for (size_t __i = __mexp_begin_-1; __i != __mexp_end_-1; ++__i) { __s.__sub_matches_[__i].first = __s.__last_; __s.__sub_matches_[__i].second = __s.__last_; __s.__sub_matches_[__i].matched = false; } } }; template void __loop<_CharT>::__exec(__state& __s) const { if (__s.__do_ == __state::__repeat) { bool __do_repeat = ++__s.__loop_data_[__loop_id_].first < __max_; bool __do_alt = __s.__loop_data_[__loop_id_].first >= __min_; if (__do_repeat && __do_alt && __s.__loop_data_[__loop_id_].second == __s.__current_) __do_repeat = false; if (__do_repeat && __do_alt) __s.__do_ = __state::__split; else if (__do_repeat) { __s.__do_ = __state::__accept_but_not_consume; __s.__node_ = this->first(); __init_repeat(__s); } else { __s.__do_ = __state::__accept_but_not_consume; __s.__node_ = this->second(); } } else { __s.__loop_data_[__loop_id_].first = 0; bool __do_repeat = 0 < __max_; bool __do_alt = 0 >= __min_; if (__do_repeat && __do_alt) __s.__do_ = __state::__split; else if (__do_repeat) { __s.__do_ = __state::__accept_but_not_consume; __s.__node_ = this->first(); __init_repeat(__s); } else { __s.__do_ = __state::__accept_but_not_consume; __s.__node_ = this->second(); } } } template void __loop<_CharT>::__exec_split(bool __second, __state& __s) const { __s.__do_ = __state::__accept_but_not_consume; if (__greedy_ != __second) { __s.__node_ = this->first(); __init_repeat(__s); } else __s.__node_ = this->second(); } // __alternate template class __alternate : public __owns_two_states<_CharT> { typedef __owns_two_states<_CharT> base; public: typedef _VSTD::__state<_CharT> __state; _LIBCPP_INLINE_VISIBILITY explicit __alternate(__owns_one_state<_CharT>* __s1, __owns_one_state<_CharT>* __s2) : base(__s1, __s2) {} virtual void __exec(__state& __s) const; virtual void __exec_split(bool __second, __state& __s) const; }; template void __alternate<_CharT>::__exec(__state& __s) const { __s.__do_ = __state::__split; } template void __alternate<_CharT>::__exec_split(bool __second, __state& __s) const { __s.__do_ = __state::__accept_but_not_consume; if (__second) __s.__node_ = this->second(); else __s.__node_ = this->first(); } // __begin_marked_subexpression template class __begin_marked_subexpression : public __owns_one_state<_CharT> { typedef __owns_one_state<_CharT> base; unsigned __mexp_; public: typedef _VSTD::__state<_CharT> __state; _LIBCPP_INLINE_VISIBILITY explicit __begin_marked_subexpression(unsigned __mexp, __node<_CharT>* __s) : base(__s), __mexp_(__mexp) {} virtual void __exec(__state&) const; }; template void __begin_marked_subexpression<_CharT>::__exec(__state& __s) const { __s.__do_ = __state::__accept_but_not_consume; __s.__sub_matches_[__mexp_-1].first = __s.__current_; __s.__node_ = this->first(); } // __end_marked_subexpression template class __end_marked_subexpression : public __owns_one_state<_CharT> { typedef __owns_one_state<_CharT> base; unsigned __mexp_; public: typedef _VSTD::__state<_CharT> __state; _LIBCPP_INLINE_VISIBILITY explicit __end_marked_subexpression(unsigned __mexp, __node<_CharT>* __s) : base(__s), __mexp_(__mexp) {} virtual void __exec(__state&) const; }; template void __end_marked_subexpression<_CharT>::__exec(__state& __s) const { __s.__do_ = __state::__accept_but_not_consume; __s.__sub_matches_[__mexp_-1].second = __s.__current_; __s.__sub_matches_[__mexp_-1].matched = true; __s.__node_ = this->first(); } // __back_ref template class __back_ref : public __owns_one_state<_CharT> { typedef __owns_one_state<_CharT> base; unsigned __mexp_; public: typedef _VSTD::__state<_CharT> __state; _LIBCPP_INLINE_VISIBILITY explicit __back_ref(unsigned __mexp, __node<_CharT>* __s) : base(__s), __mexp_(__mexp) {} virtual void __exec(__state&) const; }; template void __back_ref<_CharT>::__exec(__state& __s) const { if (__mexp_ > __s.__sub_matches_.size()) __throw_regex_error(); sub_match& __sm = __s.__sub_matches_[__mexp_-1]; if (__sm.matched) { ptrdiff_t __len = __sm.second - __sm.first; if (__s.__last_ - __s.__current_ >= __len && _VSTD::equal(__sm.first, __sm.second, __s.__current_)) { __s.__do_ = __state::__accept_but_not_consume; __s.__current_ += __len; __s.__node_ = this->first(); } else { __s.__do_ = __state::__reject; __s.__node_ = nullptr; } } else { __s.__do_ = __state::__reject; __s.__node_ = nullptr; } } // __back_ref_icase template class __back_ref_icase : public __owns_one_state<_CharT> { typedef __owns_one_state<_CharT> base; _Traits __traits_; unsigned __mexp_; public: typedef _VSTD::__state<_CharT> __state; _LIBCPP_INLINE_VISIBILITY explicit __back_ref_icase(const _Traits& __traits, unsigned __mexp, __node<_CharT>* __s) : base(__s), __traits_(__traits), __mexp_(__mexp) {} virtual void __exec(__state&) const; }; template void __back_ref_icase<_CharT, _Traits>::__exec(__state& __s) const { sub_match& __sm = __s.__sub_matches_[__mexp_-1]; if (__sm.matched) { ptrdiff_t __len = __sm.second - __sm.first; if (__s.__last_ - __s.__current_ >= __len) { for (ptrdiff_t __i = 0; __i < __len; ++__i) { if (__traits_.translate_nocase(__sm.first[__i]) != __traits_.translate_nocase(__s.__current_[__i])) goto __not_equal; } __s.__do_ = __state::__accept_but_not_consume; __s.__current_ += __len; __s.__node_ = this->first(); } else { __s.__do_ = __state::__reject; __s.__node_ = nullptr; } } else { __not_equal: __s.__do_ = __state::__reject; __s.__node_ = nullptr; } } // __back_ref_collate template class __back_ref_collate : public __owns_one_state<_CharT> { typedef __owns_one_state<_CharT> base; _Traits __traits_; unsigned __mexp_; public: typedef _VSTD::__state<_CharT> __state; _LIBCPP_INLINE_VISIBILITY explicit __back_ref_collate(const _Traits& __traits, unsigned __mexp, __node<_CharT>* __s) : base(__s), __traits_(__traits), __mexp_(__mexp) {} virtual void __exec(__state&) const; }; template void __back_ref_collate<_CharT, _Traits>::__exec(__state& __s) const { sub_match& __sm = __s.__sub_matches_[__mexp_-1]; if (__sm.matched) { ptrdiff_t __len = __sm.second - __sm.first; if (__s.__last_ - __s.__current_ >= __len) { for (ptrdiff_t __i = 0; __i < __len; ++__i) { if (__traits_.translate(__sm.first[__i]) != __traits_.translate(__s.__current_[__i])) goto __not_equal; } __s.__do_ = __state::__accept_but_not_consume; __s.__current_ += __len; __s.__node_ = this->first(); } else { __s.__do_ = __state::__reject; __s.__node_ = nullptr; } } else { __not_equal: __s.__do_ = __state::__reject; __s.__node_ = nullptr; } } // __word_boundary template class __word_boundary : public __owns_one_state<_CharT> { typedef __owns_one_state<_CharT> base; _Traits __traits_; bool __invert_; public: typedef _VSTD::__state<_CharT> __state; _LIBCPP_INLINE_VISIBILITY explicit __word_boundary(const _Traits& __traits, bool __invert, __node<_CharT>* __s) : base(__s), __traits_(__traits), __invert_(__invert) {} virtual void __exec(__state&) const; }; template void __word_boundary<_CharT, _Traits>::__exec(__state& __s) const { bool __is_word_b = false; if (__s.__first_ != __s.__last_) { if (__s.__current_ == __s.__last_) { if (!(__s.__flags_ & regex_constants::match_not_eow)) { _CharT __c = __s.__current_[-1]; __is_word_b = __c == '_' || __traits_.isctype(__c, ctype_base::alnum); } } else if (__s.__current_ == __s.__first_ && !(__s.__flags_ & regex_constants::match_prev_avail)) { if (!(__s.__flags_ & regex_constants::match_not_bow)) { _CharT __c = *__s.__current_; __is_word_b = __c == '_' || __traits_.isctype(__c, ctype_base::alnum); } } else { _CharT __c1 = __s.__current_[-1]; _CharT __c2 = *__s.__current_; bool __is_c1_b = __c1 == '_' || __traits_.isctype(__c1, ctype_base::alnum); bool __is_c2_b = __c2 == '_' || __traits_.isctype(__c2, ctype_base::alnum); __is_word_b = __is_c1_b != __is_c2_b; } } if (__is_word_b != __invert_) { __s.__do_ = __state::__accept_but_not_consume; __s.__node_ = this->first(); } else { __s.__do_ = __state::__reject; __s.__node_ = nullptr; } } // __l_anchor template class __l_anchor : public __owns_one_state<_CharT> { typedef __owns_one_state<_CharT> base; public: typedef _VSTD::__state<_CharT> __state; _LIBCPP_INLINE_VISIBILITY __l_anchor(__node<_CharT>* __s) : base(__s) {} virtual void __exec(__state&) const; }; template void __l_anchor<_CharT>::__exec(__state& __s) const { if (__s.__at_first_ && __s.__current_ == __s.__first_ && !(__s.__flags_ & regex_constants::match_not_bol)) { __s.__do_ = __state::__accept_but_not_consume; __s.__node_ = this->first(); } else { __s.__do_ = __state::__reject; __s.__node_ = nullptr; } } // __r_anchor template class __r_anchor : public __owns_one_state<_CharT> { typedef __owns_one_state<_CharT> base; public: typedef _VSTD::__state<_CharT> __state; _LIBCPP_INLINE_VISIBILITY __r_anchor(__node<_CharT>* __s) : base(__s) {} virtual void __exec(__state&) const; }; template void __r_anchor<_CharT>::__exec(__state& __s) const { if (__s.__current_ == __s.__last_ && !(__s.__flags_ & regex_constants::match_not_eol)) { __s.__do_ = __state::__accept_but_not_consume; __s.__node_ = this->first(); } else { __s.__do_ = __state::__reject; __s.__node_ = nullptr; } } // __match_any template class __match_any : public __owns_one_state<_CharT> { typedef __owns_one_state<_CharT> base; public: typedef _VSTD::__state<_CharT> __state; _LIBCPP_INLINE_VISIBILITY __match_any(__node<_CharT>* __s) : base(__s) {} virtual void __exec(__state&) const; }; template void __match_any<_CharT>::__exec(__state& __s) const { if (__s.__current_ != __s.__last_ && *__s.__current_ != 0) { __s.__do_ = __state::__accept_and_consume; ++__s.__current_; __s.__node_ = this->first(); } else { __s.__do_ = __state::__reject; __s.__node_ = nullptr; } } // __match_any_but_newline template class __match_any_but_newline : public __owns_one_state<_CharT> { typedef __owns_one_state<_CharT> base; public: typedef _VSTD::__state<_CharT> __state; _LIBCPP_INLINE_VISIBILITY __match_any_but_newline(__node<_CharT>* __s) : base(__s) {} virtual void __exec(__state&) const; }; template <> _LIBCPP_FUNC_VIS void __match_any_but_newline::__exec(__state&) const; template <> _LIBCPP_FUNC_VIS void __match_any_but_newline::__exec(__state&) const; // __match_char template class __match_char : public __owns_one_state<_CharT> { typedef __owns_one_state<_CharT> base; _CharT __c_; __match_char(const __match_char&); __match_char& operator=(const __match_char&); public: typedef _VSTD::__state<_CharT> __state; _LIBCPP_INLINE_VISIBILITY __match_char(_CharT __c, __node<_CharT>* __s) : base(__s), __c_(__c) {} virtual void __exec(__state&) const; }; template void __match_char<_CharT>::__exec(__state& __s) const { if (__s.__current_ != __s.__last_ && *__s.__current_ == __c_) { __s.__do_ = __state::__accept_and_consume; ++__s.__current_; __s.__node_ = this->first(); } else { __s.__do_ = __state::__reject; __s.__node_ = nullptr; } } // __match_char_icase template class __match_char_icase : public __owns_one_state<_CharT> { typedef __owns_one_state<_CharT> base; _Traits __traits_; _CharT __c_; __match_char_icase(const __match_char_icase&); __match_char_icase& operator=(const __match_char_icase&); public: typedef _VSTD::__state<_CharT> __state; _LIBCPP_INLINE_VISIBILITY __match_char_icase(const _Traits& __traits, _CharT __c, __node<_CharT>* __s) : base(__s), __traits_(__traits), __c_(__traits.translate_nocase(__c)) {} virtual void __exec(__state&) const; }; template void __match_char_icase<_CharT, _Traits>::__exec(__state& __s) const { if (__s.__current_ != __s.__last_ && __traits_.translate_nocase(*__s.__current_) == __c_) { __s.__do_ = __state::__accept_and_consume; ++__s.__current_; __s.__node_ = this->first(); } else { __s.__do_ = __state::__reject; __s.__node_ = nullptr; } } // __match_char_collate template class __match_char_collate : public __owns_one_state<_CharT> { typedef __owns_one_state<_CharT> base; _Traits __traits_; _CharT __c_; __match_char_collate(const __match_char_collate&); __match_char_collate& operator=(const __match_char_collate&); public: typedef _VSTD::__state<_CharT> __state; _LIBCPP_INLINE_VISIBILITY __match_char_collate(const _Traits& __traits, _CharT __c, __node<_CharT>* __s) : base(__s), __traits_(__traits), __c_(__traits.translate(__c)) {} virtual void __exec(__state&) const; }; template void __match_char_collate<_CharT, _Traits>::__exec(__state& __s) const { if (__s.__current_ != __s.__last_ && __traits_.translate(*__s.__current_) == __c_) { __s.__do_ = __state::__accept_and_consume; ++__s.__current_; __s.__node_ = this->first(); } else { __s.__do_ = __state::__reject; __s.__node_ = nullptr; } } // __bracket_expression template class __bracket_expression : public __owns_one_state<_CharT> { typedef __owns_one_state<_CharT> base; typedef typename _Traits::string_type string_type; _Traits __traits_; vector<_CharT> __chars_; vector<_CharT> __neg_chars_; vector > __ranges_; vector > __digraphs_; vector __equivalences_; typename regex_traits<_CharT>::char_class_type __mask_; typename regex_traits<_CharT>::char_class_type __neg_mask_; bool __negate_; bool __icase_; bool __collate_; bool __might_have_digraph_; __bracket_expression(const __bracket_expression&); __bracket_expression& operator=(const __bracket_expression&); public: typedef _VSTD::__state<_CharT> __state; _LIBCPP_INLINE_VISIBILITY __bracket_expression(const _Traits& __traits, __node<_CharT>* __s, bool __negate, bool __icase, bool __collate) : base(__s), __traits_(__traits), __mask_(), __neg_mask_(), __negate_(__negate), __icase_(__icase), __collate_(__collate), __might_have_digraph_(__traits_.getloc().name() != "C") {} virtual void __exec(__state&) const; _LIBCPP_INLINE_VISIBILITY bool __negated() const {return __negate_;} _LIBCPP_INLINE_VISIBILITY void __add_char(_CharT __c) { if (__icase_) __chars_.push_back(__traits_.translate_nocase(__c)); else if (__collate_) __chars_.push_back(__traits_.translate(__c)); else __chars_.push_back(__c); } _LIBCPP_INLINE_VISIBILITY void __add_neg_char(_CharT __c) { if (__icase_) __neg_chars_.push_back(__traits_.translate_nocase(__c)); else if (__collate_) __neg_chars_.push_back(__traits_.translate(__c)); else __neg_chars_.push_back(__c); } _LIBCPP_INLINE_VISIBILITY void __add_range(string_type __b, string_type __e) { if (__collate_) { if (__icase_) { for (size_t __i = 0; __i < __b.size(); ++__i) __b[__i] = __traits_.translate_nocase(__b[__i]); for (size_t __i = 0; __i < __e.size(); ++__i) __e[__i] = __traits_.translate_nocase(__e[__i]); } else { for (size_t __i = 0; __i < __b.size(); ++__i) __b[__i] = __traits_.translate(__b[__i]); for (size_t __i = 0; __i < __e.size(); ++__i) __e[__i] = __traits_.translate(__e[__i]); } __ranges_.push_back(make_pair( __traits_.transform(__b.begin(), __b.end()), __traits_.transform(__e.begin(), __e.end()))); } else { if (__b.size() != 1 || __e.size() != 1) __throw_regex_error(); if (__icase_) { __b[0] = __traits_.translate_nocase(__b[0]); __e[0] = __traits_.translate_nocase(__e[0]); } __ranges_.push_back(make_pair(_VSTD::move(__b), _VSTD::move(__e))); } } _LIBCPP_INLINE_VISIBILITY void __add_digraph(_CharT __c1, _CharT __c2) { if (__icase_) __digraphs_.push_back(make_pair(__traits_.translate_nocase(__c1), __traits_.translate_nocase(__c2))); else if (__collate_) __digraphs_.push_back(make_pair(__traits_.translate(__c1), __traits_.translate(__c2))); else __digraphs_.push_back(make_pair(__c1, __c2)); } _LIBCPP_INLINE_VISIBILITY void __add_equivalence(const string_type& __s) {__equivalences_.push_back(__s);} _LIBCPP_INLINE_VISIBILITY void __add_class(typename regex_traits<_CharT>::char_class_type __mask) {__mask_ |= __mask;} _LIBCPP_INLINE_VISIBILITY void __add_neg_class(typename regex_traits<_CharT>::char_class_type __mask) {__neg_mask_ |= __mask;} }; template void __bracket_expression<_CharT, _Traits>::__exec(__state& __s) const { bool __found = false; unsigned __consumed = 0; if (__s.__current_ != __s.__last_) { ++__consumed; if (__might_have_digraph_) { const _CharT* __next = _VSTD::next(__s.__current_); if (__next != __s.__last_) { pair<_CharT, _CharT> __ch2(*__s.__current_, *__next); if (__icase_) { __ch2.first = __traits_.translate_nocase(__ch2.first); __ch2.second = __traits_.translate_nocase(__ch2.second); } else if (__collate_) { __ch2.first = __traits_.translate(__ch2.first); __ch2.second = __traits_.translate(__ch2.second); } if (!__traits_.lookup_collatename(&__ch2.first, &__ch2.first+2).empty()) { // __ch2 is a digraph in this locale ++__consumed; for (size_t __i = 0; __i < __digraphs_.size(); ++__i) { if (__ch2 == __digraphs_[__i]) { __found = true; goto __exit; } } if (__collate_ && !__ranges_.empty()) { string_type __s2 = __traits_.transform(&__ch2.first, &__ch2.first + 2); for (size_t __i = 0; __i < __ranges_.size(); ++__i) { if (__ranges_[__i].first <= __s2 && __s2 <= __ranges_[__i].second) { __found = true; goto __exit; } } } if (!__equivalences_.empty()) { string_type __s2 = __traits_.transform_primary(&__ch2.first, &__ch2.first + 2); for (size_t __i = 0; __i < __equivalences_.size(); ++__i) { if (__s2 == __equivalences_[__i]) { __found = true; goto __exit; } } } if (__traits_.isctype(__ch2.first, __mask_) && __traits_.isctype(__ch2.second, __mask_)) { __found = true; goto __exit; } if (!__traits_.isctype(__ch2.first, __neg_mask_) && !__traits_.isctype(__ch2.second, __neg_mask_)) { __found = true; goto __exit; } goto __exit; } } } // test *__s.__current_ as not a digraph _CharT __ch = *__s.__current_; if (__icase_) __ch = __traits_.translate_nocase(__ch); else if (__collate_) __ch = __traits_.translate(__ch); for (size_t __i = 0; __i < __chars_.size(); ++__i) { if (__ch == __chars_[__i]) { __found = true; goto __exit; } } if (!__neg_chars_.empty()) { for (size_t __i = 0; __i < __neg_chars_.size(); ++__i) { if (__ch == __neg_chars_[__i]) goto __is_neg_char; } __found = true; goto __exit; } __is_neg_char: if (!__ranges_.empty()) { string_type __s2 = __collate_ ? __traits_.transform(&__ch, &__ch + 1) : string_type(1, __ch); for (size_t __i = 0; __i < __ranges_.size(); ++__i) { if (__ranges_[__i].first <= __s2 && __s2 <= __ranges_[__i].second) { __found = true; goto __exit; } } } if (!__equivalences_.empty()) { string_type __s2 = __traits_.transform_primary(&__ch, &__ch + 1); for (size_t __i = 0; __i < __equivalences_.size(); ++__i) { if (__s2 == __equivalences_[__i]) { __found = true; goto __exit; } } } if (__traits_.isctype(__ch, __mask_)) { __found = true; goto __exit; } if (__neg_mask_ && !__traits_.isctype(__ch, __neg_mask_)) { __found = true; goto __exit; } } else __found = __negate_; // force reject __exit: if (__found != __negate_) { __s.__do_ = __state::__accept_and_consume; __s.__current_ += __consumed; __s.__node_ = this->first(); } else { __s.__do_ = __state::__reject; __s.__node_ = nullptr; } } template class __lookahead; template > class _LIBCPP_TEMPLATE_VIS basic_regex { public: // types: typedef _CharT value_type; typedef _Traits traits_type; typedef typename _Traits::string_type string_type; typedef regex_constants::syntax_option_type flag_type; typedef typename _Traits::locale_type locale_type; private: _Traits __traits_; flag_type __flags_; unsigned __marked_count_; unsigned __loop_count_; int __open_count_; shared_ptr<__empty_state<_CharT> > __start_; __owns_one_state<_CharT>* __end_; typedef _VSTD::__state<_CharT> __state; typedef _VSTD::__node<_CharT> __node; public: // constants: static const regex_constants::syntax_option_type icase = regex_constants::icase; static const regex_constants::syntax_option_type nosubs = regex_constants::nosubs; static const regex_constants::syntax_option_type optimize = regex_constants::optimize; static const regex_constants::syntax_option_type collate = regex_constants::collate; static const regex_constants::syntax_option_type ECMAScript = regex_constants::ECMAScript; static const regex_constants::syntax_option_type basic = regex_constants::basic; static const regex_constants::syntax_option_type extended = regex_constants::extended; static const regex_constants::syntax_option_type awk = regex_constants::awk; static const regex_constants::syntax_option_type grep = regex_constants::grep; static const regex_constants::syntax_option_type egrep = regex_constants::egrep; // construct/copy/destroy: _LIBCPP_INLINE_VISIBILITY basic_regex() : __flags_(), __marked_count_(0), __loop_count_(0), __open_count_(0), __end_(0) {} _LIBCPP_INLINE_VISIBILITY explicit basic_regex(const value_type* __p, flag_type __f = regex_constants::ECMAScript) : __flags_(__f), __marked_count_(0), __loop_count_(0), __open_count_(0), __end_(0) {__parse(__p, __p + __traits_.length(__p));} _LIBCPP_INLINE_VISIBILITY basic_regex(const value_type* __p, size_t __len, flag_type __f = regex_constants::ECMAScript) : __flags_(__f), __marked_count_(0), __loop_count_(0), __open_count_(0), __end_(0) {__parse(__p, __p + __len);} // basic_regex(const basic_regex&) = default; // basic_regex(basic_regex&&) = default; template _LIBCPP_INLINE_VISIBILITY explicit basic_regex(const basic_string& __p, flag_type __f = regex_constants::ECMAScript) : __flags_(__f), __marked_count_(0), __loop_count_(0), __open_count_(0), __end_(0) {__parse(__p.begin(), __p.end());} template _LIBCPP_INLINE_VISIBILITY basic_regex(_ForwardIterator __first, _ForwardIterator __last, flag_type __f = regex_constants::ECMAScript) : __flags_(__f), __marked_count_(0), __loop_count_(0), __open_count_(0), __end_(0) {__parse(__first, __last);} #ifndef _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY basic_regex(initializer_list __il, flag_type __f = regex_constants::ECMAScript) : __flags_(__f), __marked_count_(0), __loop_count_(0), __open_count_(0), __end_(0) {__parse(__il.begin(), __il.end());} #endif // _LIBCPP_CXX03_LANG // ~basic_regex() = default; // basic_regex& operator=(const basic_regex&) = default; // basic_regex& operator=(basic_regex&&) = default; _LIBCPP_INLINE_VISIBILITY basic_regex& operator=(const value_type* __p) {return assign(__p);} #ifndef _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY basic_regex& operator=(initializer_list __il) {return assign(__il);} #endif // _LIBCPP_CXX03_LANG template _LIBCPP_INLINE_VISIBILITY basic_regex& operator=(const basic_string& __p) {return assign(__p);} // assign: _LIBCPP_INLINE_VISIBILITY basic_regex& assign(const basic_regex& __that) {return *this = __that;} #ifndef _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY basic_regex& assign(basic_regex&& __that) _NOEXCEPT {return *this = _VSTD::move(__that);} #endif _LIBCPP_INLINE_VISIBILITY basic_regex& assign(const value_type* __p, flag_type __f = regex_constants::ECMAScript) {return assign(__p, __p + __traits_.length(__p), __f);} _LIBCPP_INLINE_VISIBILITY basic_regex& assign(const value_type* __p, size_t __len, flag_type __f) {return assign(__p, __p + __len, __f);} template _LIBCPP_INLINE_VISIBILITY basic_regex& assign(const basic_string& __s, flag_type __f = regex_constants::ECMAScript) {return assign(__s.begin(), __s.end(), __f);} template _LIBCPP_INLINE_VISIBILITY typename enable_if < __is_input_iterator <_InputIterator>::value && !__is_forward_iterator<_InputIterator>::value, basic_regex& >::type assign(_InputIterator __first, _InputIterator __last, flag_type __f = regex_constants::ECMAScript) { basic_string<_CharT> __t(__first, __last); return assign(__t.begin(), __t.end(), __f); } private: _LIBCPP_INLINE_VISIBILITY void __member_init(flag_type __f) { __flags_ = __f; __marked_count_ = 0; __loop_count_ = 0; __open_count_ = 0; __end_ = nullptr; } public: template _LIBCPP_INLINE_VISIBILITY typename enable_if < __is_forward_iterator<_ForwardIterator>::value, basic_regex& >::type assign(_ForwardIterator __first, _ForwardIterator __last, flag_type __f = regex_constants::ECMAScript) { return assign(basic_regex(__first, __last, __f)); } #ifndef _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY basic_regex& assign(initializer_list __il, flag_type __f = regex_constants::ECMAScript) {return assign(__il.begin(), __il.end(), __f);} #endif // _LIBCPP_CXX03_LANG // const operations: _LIBCPP_INLINE_VISIBILITY unsigned mark_count() const {return __marked_count_;} _LIBCPP_INLINE_VISIBILITY flag_type flags() const {return __flags_;} // locale: _LIBCPP_INLINE_VISIBILITY locale_type imbue(locale_type __loc) { __member_init(ECMAScript); __start_.reset(); return __traits_.imbue(__loc); } _LIBCPP_INLINE_VISIBILITY locale_type getloc() const {return __traits_.getloc();} // swap: void swap(basic_regex& __r); private: _LIBCPP_INLINE_VISIBILITY unsigned __loop_count() const {return __loop_count_;} template _ForwardIterator __parse(_ForwardIterator __first, _ForwardIterator __last); template _ForwardIterator __parse_basic_reg_exp(_ForwardIterator __first, _ForwardIterator __last); template _ForwardIterator __parse_RE_expression(_ForwardIterator __first, _ForwardIterator __last); template _ForwardIterator __parse_simple_RE(_ForwardIterator __first, _ForwardIterator __last); template _ForwardIterator __parse_nondupl_RE(_ForwardIterator __first, _ForwardIterator __last); template _ForwardIterator __parse_one_char_or_coll_elem_RE(_ForwardIterator __first, _ForwardIterator __last); template _ForwardIterator __parse_Back_open_paren(_ForwardIterator __first, _ForwardIterator __last); template _ForwardIterator __parse_Back_close_paren(_ForwardIterator __first, _ForwardIterator __last); template _ForwardIterator __parse_Back_open_brace(_ForwardIterator __first, _ForwardIterator __last); template _ForwardIterator __parse_Back_close_brace(_ForwardIterator __first, _ForwardIterator __last); template _ForwardIterator __parse_BACKREF(_ForwardIterator __first, _ForwardIterator __last); template _ForwardIterator __parse_ORD_CHAR(_ForwardIterator __first, _ForwardIterator __last); template _ForwardIterator __parse_QUOTED_CHAR(_ForwardIterator __first, _ForwardIterator __last); template _ForwardIterator __parse_RE_dupl_symbol(_ForwardIterator __first, _ForwardIterator __last, __owns_one_state<_CharT>* __s, unsigned __mexp_begin, unsigned __mexp_end); template _ForwardIterator __parse_ERE_dupl_symbol(_ForwardIterator __first, _ForwardIterator __last, __owns_one_state<_CharT>* __s, unsigned __mexp_begin, unsigned __mexp_end); template _ForwardIterator __parse_bracket_expression(_ForwardIterator __first, _ForwardIterator __last); template _ForwardIterator __parse_follow_list(_ForwardIterator __first, _ForwardIterator __last, __bracket_expression<_CharT, _Traits>* __ml); template _ForwardIterator __parse_expression_term(_ForwardIterator __first, _ForwardIterator __last, __bracket_expression<_CharT, _Traits>* __ml); template _ForwardIterator __parse_equivalence_class(_ForwardIterator __first, _ForwardIterator __last, __bracket_expression<_CharT, _Traits>* __ml); template _ForwardIterator __parse_character_class(_ForwardIterator __first, _ForwardIterator __last, __bracket_expression<_CharT, _Traits>* __ml); template _ForwardIterator __parse_collating_symbol(_ForwardIterator __first, _ForwardIterator __last, basic_string<_CharT>& __col_sym); template _ForwardIterator __parse_DUP_COUNT(_ForwardIterator __first, _ForwardIterator __last, int& __c); template _ForwardIterator __parse_extended_reg_exp(_ForwardIterator __first, _ForwardIterator __last); template _ForwardIterator __parse_ERE_branch(_ForwardIterator __first, _ForwardIterator __last); template _ForwardIterator __parse_ERE_expression(_ForwardIterator __first, _ForwardIterator __last); template _ForwardIterator __parse_one_char_or_coll_elem_ERE(_ForwardIterator __first, _ForwardIterator __last); template _ForwardIterator __parse_ORD_CHAR_ERE(_ForwardIterator __first, _ForwardIterator __last); template _ForwardIterator __parse_QUOTED_CHAR_ERE(_ForwardIterator __first, _ForwardIterator __last); template _ForwardIterator __parse_ecma_exp(_ForwardIterator __first, _ForwardIterator __last); template _ForwardIterator __parse_alternative(_ForwardIterator __first, _ForwardIterator __last); template _ForwardIterator __parse_term(_ForwardIterator __first, _ForwardIterator __last); template _ForwardIterator __parse_assertion(_ForwardIterator __first, _ForwardIterator __last); template _ForwardIterator __parse_atom(_ForwardIterator __first, _ForwardIterator __last); template _ForwardIterator __parse_atom_escape(_ForwardIterator __first, _ForwardIterator __last); template _ForwardIterator __parse_decimal_escape(_ForwardIterator __first, _ForwardIterator __last); template _ForwardIterator __parse_character_class_escape(_ForwardIterator __first, _ForwardIterator __last); template _ForwardIterator __parse_character_escape(_ForwardIterator __first, _ForwardIterator __last, basic_string<_CharT>* __str = nullptr); template _ForwardIterator __parse_pattern_character(_ForwardIterator __first, _ForwardIterator __last); template _ForwardIterator __parse_grep(_ForwardIterator __first, _ForwardIterator __last); template _ForwardIterator __parse_egrep(_ForwardIterator __first, _ForwardIterator __last); template _ForwardIterator __parse_class_escape(_ForwardIterator __first, _ForwardIterator __last, basic_string<_CharT>& __str, __bracket_expression<_CharT, _Traits>* __ml); template _ForwardIterator __parse_awk_escape(_ForwardIterator __first, _ForwardIterator __last, basic_string<_CharT>* __str = nullptr); _LIBCPP_INLINE_VISIBILITY void __push_l_anchor(); void __push_r_anchor(); void __push_match_any(); void __push_match_any_but_newline(); _LIBCPP_INLINE_VISIBILITY void __push_greedy_inf_repeat(size_t __min, __owns_one_state<_CharT>* __s, unsigned __mexp_begin = 0, unsigned __mexp_end = 0) {__push_loop(__min, numeric_limits::max(), __s, __mexp_begin, __mexp_end);} _LIBCPP_INLINE_VISIBILITY void __push_nongreedy_inf_repeat(size_t __min, __owns_one_state<_CharT>* __s, unsigned __mexp_begin = 0, unsigned __mexp_end = 0) {__push_loop(__min, numeric_limits::max(), __s, __mexp_begin, __mexp_end, false);} void __push_loop(size_t __min, size_t __max, __owns_one_state<_CharT>* __s, size_t __mexp_begin = 0, size_t __mexp_end = 0, bool __greedy = true); __bracket_expression<_CharT, _Traits>* __start_matching_list(bool __negate); void __push_char(value_type __c); void __push_back_ref(int __i); void __push_alternation(__owns_one_state<_CharT>* __sa, __owns_one_state<_CharT>* __sb); void __push_begin_marked_subexpression(); void __push_end_marked_subexpression(unsigned); void __push_empty(); void __push_word_boundary(bool); void __push_lookahead(const basic_regex&, bool, unsigned); template bool __search(const _CharT* __first, const _CharT* __last, match_results& __m, regex_constants::match_flag_type __flags) const; template bool __match_at_start(const _CharT* __first, const _CharT* __last, match_results& __m, regex_constants::match_flag_type __flags, bool) const; template bool __match_at_start_ecma(const _CharT* __first, const _CharT* __last, match_results& __m, regex_constants::match_flag_type __flags, bool) const; template bool __match_at_start_posix_nosubs(const _CharT* __first, const _CharT* __last, match_results& __m, regex_constants::match_flag_type __flags, bool) const; template bool __match_at_start_posix_subs(const _CharT* __first, const _CharT* __last, match_results& __m, regex_constants::match_flag_type __flags, bool) const; template friend bool regex_search(_Bp, _Bp, match_results<_Bp, _Ap>&, const basic_regex<_Cp, _Tp>&, regex_constants::match_flag_type); template friend bool regex_search(const _Cp*, const _Cp*, match_results&, const basic_regex<_Cp, _Tp>&, regex_constants::match_flag_type); template friend bool regex_search(_Bp, _Bp, const basic_regex<_Cp, _Tp>&, regex_constants::match_flag_type); template friend bool regex_search(const _Cp*, const _Cp*, const basic_regex<_Cp, _Tp>&, regex_constants::match_flag_type); template friend bool regex_search(const _Cp*, match_results&, const basic_regex<_Cp, _Tp>&, regex_constants::match_flag_type); template friend bool regex_search(const basic_string<_Cp, _ST, _SA>& __s, const basic_regex<_Cp, _Tp>& __e, regex_constants::match_flag_type __flags); template friend bool regex_search(const basic_string<_Cp, _ST, _SA>& __s, match_results::const_iterator, _Ap>&, const basic_regex<_Cp, _Tp>& __e, regex_constants::match_flag_type __flags); template friend bool regex_search(__wrap_iter<_Iter> __first, __wrap_iter<_Iter> __last, match_results<__wrap_iter<_Iter>, _Ap>& __m, const basic_regex<_Cp, _Tp>& __e, regex_constants::match_flag_type __flags); template friend class __lookahead; }; template const regex_constants::syntax_option_type basic_regex<_CharT, _Traits>::icase; template const regex_constants::syntax_option_type basic_regex<_CharT, _Traits>::nosubs; template const regex_constants::syntax_option_type basic_regex<_CharT, _Traits>::optimize; template const regex_constants::syntax_option_type basic_regex<_CharT, _Traits>::collate; template const regex_constants::syntax_option_type basic_regex<_CharT, _Traits>::ECMAScript; template const regex_constants::syntax_option_type basic_regex<_CharT, _Traits>::basic; template const regex_constants::syntax_option_type basic_regex<_CharT, _Traits>::extended; template const regex_constants::syntax_option_type basic_regex<_CharT, _Traits>::awk; template const regex_constants::syntax_option_type basic_regex<_CharT, _Traits>::grep; template const regex_constants::syntax_option_type basic_regex<_CharT, _Traits>::egrep; template void basic_regex<_CharT, _Traits>::swap(basic_regex& __r) { using _VSTD::swap; swap(__traits_, __r.__traits_); swap(__flags_, __r.__flags_); swap(__marked_count_, __r.__marked_count_); swap(__loop_count_, __r.__loop_count_); swap(__open_count_, __r.__open_count_); swap(__start_, __r.__start_); swap(__end_, __r.__end_); } template inline _LIBCPP_INLINE_VISIBILITY void swap(basic_regex<_CharT, _Traits>& __x, basic_regex<_CharT, _Traits>& __y) { return __x.swap(__y); } // __lookahead template class __lookahead : public __owns_one_state<_CharT> { typedef __owns_one_state<_CharT> base; basic_regex<_CharT, _Traits> __exp_; unsigned __mexp_; bool __invert_; __lookahead(const __lookahead&); __lookahead& operator=(const __lookahead&); public: typedef _VSTD::__state<_CharT> __state; _LIBCPP_INLINE_VISIBILITY __lookahead(const basic_regex<_CharT, _Traits>& __exp, bool __invert, __node<_CharT>* __s, unsigned __mexp) : base(__s), __exp_(__exp), __mexp_(__mexp), __invert_(__invert) {} virtual void __exec(__state&) const; }; template void __lookahead<_CharT, _Traits>::__exec(__state& __s) const { match_results __m; __m.__init(1 + __exp_.mark_count(), __s.__current_, __s.__last_); bool __matched = __exp_.__match_at_start_ecma( __s.__current_, __s.__last_, __m, (__s.__flags_ | regex_constants::match_continuous) & ~regex_constants::__full_match, __s.__at_first_ && __s.__current_ == __s.__first_); if (__matched != __invert_) { __s.__do_ = __state::__accept_but_not_consume; __s.__node_ = this->first(); for (unsigned __i = 1; __i < __m.size(); ++__i) { __s.__sub_matches_[__mexp_ + __i - 1] = __m.__matches_[__i]; } } else { __s.__do_ = __state::__reject; __s.__node_ = nullptr; } } template template _ForwardIterator basic_regex<_CharT, _Traits>::__parse(_ForwardIterator __first, _ForwardIterator __last) { { unique_ptr<__node> __h(new __end_state<_CharT>); __start_.reset(new __empty_state<_CharT>(__h.get())); __h.release(); __end_ = __start_.get(); } switch (__flags_ & 0x1F0) { case ECMAScript: __first = __parse_ecma_exp(__first, __last); break; case basic: __first = __parse_basic_reg_exp(__first, __last); break; case extended: case awk: __first = __parse_extended_reg_exp(__first, __last); break; case grep: __first = __parse_grep(__first, __last); break; case egrep: __first = __parse_egrep(__first, __last); break; default: __throw_regex_error(); } return __first; } template template _ForwardIterator basic_regex<_CharT, _Traits>::__parse_basic_reg_exp(_ForwardIterator __first, _ForwardIterator __last) { if (__first != __last) { if (*__first == '^') { __push_l_anchor(); ++__first; } if (__first != __last) { __first = __parse_RE_expression(__first, __last); if (__first != __last) { _ForwardIterator __temp = _VSTD::next(__first); if (__temp == __last && *__first == '$') { __push_r_anchor(); ++__first; } } } if (__first != __last) __throw_regex_error(); } return __first; } template template _ForwardIterator basic_regex<_CharT, _Traits>::__parse_extended_reg_exp(_ForwardIterator __first, _ForwardIterator __last) { __owns_one_state<_CharT>* __sa = __end_; _ForwardIterator __temp = __parse_ERE_branch(__first, __last); if (__temp == __first) __throw_regex_error(); __first = __temp; while (__first != __last && *__first == '|') { __owns_one_state<_CharT>* __sb = __end_; __temp = __parse_ERE_branch(++__first, __last); if (__temp == __first) __throw_regex_error(); __push_alternation(__sa, __sb); __first = __temp; } return __first; } template template _ForwardIterator basic_regex<_CharT, _Traits>::__parse_ERE_branch(_ForwardIterator __first, _ForwardIterator __last) { _ForwardIterator __temp = __parse_ERE_expression(__first, __last); if (__temp == __first) __throw_regex_error(); do { __first = __temp; __temp = __parse_ERE_expression(__first, __last); } while (__temp != __first); return __first; } template template _ForwardIterator basic_regex<_CharT, _Traits>::__parse_ERE_expression(_ForwardIterator __first, _ForwardIterator __last) { __owns_one_state<_CharT>* __e = __end_; unsigned __mexp_begin = __marked_count_; _ForwardIterator __temp = __parse_one_char_or_coll_elem_ERE(__first, __last); if (__temp == __first && __temp != __last) { switch (*__temp) { case '^': __push_l_anchor(); ++__temp; break; case '$': __push_r_anchor(); ++__temp; break; case '(': __push_begin_marked_subexpression(); unsigned __temp_count = __marked_count_; ++__open_count_; __temp = __parse_extended_reg_exp(++__temp, __last); if (__temp == __last || *__temp != ')') __throw_regex_error(); __push_end_marked_subexpression(__temp_count); --__open_count_; ++__temp; break; } } if (__temp != __first) __temp = __parse_ERE_dupl_symbol(__temp, __last, __e, __mexp_begin+1, __marked_count_+1); __first = __temp; return __first; } template template _ForwardIterator basic_regex<_CharT, _Traits>::__parse_RE_expression(_ForwardIterator __first, _ForwardIterator __last) { while (true) { _ForwardIterator __temp = __parse_simple_RE(__first, __last); if (__temp == __first) break; __first = __temp; } return __first; } template template _ForwardIterator basic_regex<_CharT, _Traits>::__parse_simple_RE(_ForwardIterator __first, _ForwardIterator __last) { if (__first != __last) { __owns_one_state<_CharT>* __e = __end_; unsigned __mexp_begin = __marked_count_; _ForwardIterator __temp = __parse_nondupl_RE(__first, __last); if (__temp != __first) __first = __parse_RE_dupl_symbol(__temp, __last, __e, __mexp_begin+1, __marked_count_+1); } return __first; } template template _ForwardIterator basic_regex<_CharT, _Traits>::__parse_nondupl_RE(_ForwardIterator __first, _ForwardIterator __last) { _ForwardIterator __temp = __first; __first = __parse_one_char_or_coll_elem_RE(__first, __last); if (__temp == __first) { __temp = __parse_Back_open_paren(__first, __last); if (__temp != __first) { __push_begin_marked_subexpression(); unsigned __temp_count = __marked_count_; __first = __parse_RE_expression(__temp, __last); __temp = __parse_Back_close_paren(__first, __last); if (__temp == __first) __throw_regex_error(); __push_end_marked_subexpression(__temp_count); __first = __temp; } else __first = __parse_BACKREF(__first, __last); } return __first; } template template _ForwardIterator basic_regex<_CharT, _Traits>::__parse_one_char_or_coll_elem_RE( _ForwardIterator __first, _ForwardIterator __last) { _ForwardIterator __temp = __parse_ORD_CHAR(__first, __last); if (__temp == __first) { __temp = __parse_QUOTED_CHAR(__first, __last); if (__temp == __first) { if (__temp != __last && *__temp == '.') { __push_match_any(); ++__temp; } else __temp = __parse_bracket_expression(__first, __last); } } __first = __temp; return __first; } template template _ForwardIterator basic_regex<_CharT, _Traits>::__parse_one_char_or_coll_elem_ERE( _ForwardIterator __first, _ForwardIterator __last) { _ForwardIterator __temp = __parse_ORD_CHAR_ERE(__first, __last); if (__temp == __first) { __temp = __parse_QUOTED_CHAR_ERE(__first, __last); if (__temp == __first) { if (__temp != __last && *__temp == '.') { __push_match_any(); ++__temp; } else __temp = __parse_bracket_expression(__first, __last); } } __first = __temp; return __first; } template template _ForwardIterator basic_regex<_CharT, _Traits>::__parse_Back_open_paren(_ForwardIterator __first, _ForwardIterator __last) { if (__first != __last) { _ForwardIterator __temp = _VSTD::next(__first); if (__temp != __last) { if (*__first == '\\' && *__temp == '(') __first = ++__temp; } } return __first; } template template _ForwardIterator basic_regex<_CharT, _Traits>::__parse_Back_close_paren(_ForwardIterator __first, _ForwardIterator __last) { if (__first != __last) { _ForwardIterator __temp = _VSTD::next(__first); if (__temp != __last) { if (*__first == '\\' && *__temp == ')') __first = ++__temp; } } return __first; } template template _ForwardIterator basic_regex<_CharT, _Traits>::__parse_Back_open_brace(_ForwardIterator __first, _ForwardIterator __last) { if (__first != __last) { _ForwardIterator __temp = _VSTD::next(__first); if (__temp != __last) { if (*__first == '\\' && *__temp == '{') __first = ++__temp; } } return __first; } template template _ForwardIterator basic_regex<_CharT, _Traits>::__parse_Back_close_brace(_ForwardIterator __first, _ForwardIterator __last) { if (__first != __last) { _ForwardIterator __temp = _VSTD::next(__first); if (__temp != __last) { if (*__first == '\\' && *__temp == '}') __first = ++__temp; } } return __first; } template template _ForwardIterator basic_regex<_CharT, _Traits>::__parse_BACKREF(_ForwardIterator __first, _ForwardIterator __last) { if (__first != __last) { _ForwardIterator __temp = _VSTD::next(__first); if (__temp != __last) { if (*__first == '\\') { int __val = __traits_.value(*__temp, 10); if (__val >= 1 && __val <= 9) { __push_back_ref(__val); __first = ++__temp; } } } } return __first; } template template _ForwardIterator basic_regex<_CharT, _Traits>::__parse_ORD_CHAR(_ForwardIterator __first, _ForwardIterator __last) { if (__first != __last) { _ForwardIterator __temp = _VSTD::next(__first); if (__temp == __last && *__first == '$') return __first; // Not called inside a bracket if (*__first == '.' || *__first == '\\' || *__first == '[') return __first; __push_char(*__first); ++__first; } return __first; } template template _ForwardIterator basic_regex<_CharT, _Traits>::__parse_ORD_CHAR_ERE(_ForwardIterator __first, _ForwardIterator __last) { if (__first != __last) { switch (*__first) { case '^': case '.': case '[': case '$': case '(': case '|': case '*': case '+': case '?': case '{': case '\\': break; case ')': if (__open_count_ == 0) { __push_char(*__first); ++__first; } break; default: __push_char(*__first); ++__first; break; } } return __first; } template template _ForwardIterator basic_regex<_CharT, _Traits>::__parse_QUOTED_CHAR(_ForwardIterator __first, _ForwardIterator __last) { if (__first != __last) { _ForwardIterator __temp = _VSTD::next(__first); if (__temp != __last) { if (*__first == '\\') { switch (*__temp) { case '^': case '.': case '*': case '[': case '$': case '\\': __push_char(*__temp); __first = ++__temp; break; } } } } return __first; } template template _ForwardIterator basic_regex<_CharT, _Traits>::__parse_QUOTED_CHAR_ERE(_ForwardIterator __first, _ForwardIterator __last) { if (__first != __last) { _ForwardIterator __temp = _VSTD::next(__first); if (__temp != __last) { if (*__first == '\\') { switch (*__temp) { case '^': case '.': case '*': case '[': case '$': case '\\': case '(': case ')': case '|': case '+': case '?': case '{': case '}': __push_char(*__temp); __first = ++__temp; break; default: if ((__flags_ & 0x1F0) == awk) __first = __parse_awk_escape(++__first, __last); break; } } } } return __first; } template template _ForwardIterator basic_regex<_CharT, _Traits>::__parse_RE_dupl_symbol(_ForwardIterator __first, _ForwardIterator __last, __owns_one_state<_CharT>* __s, unsigned __mexp_begin, unsigned __mexp_end) { if (__first != __last) { if (*__first == '*') { __push_greedy_inf_repeat(0, __s, __mexp_begin, __mexp_end); ++__first; } else { _ForwardIterator __temp = __parse_Back_open_brace(__first, __last); if (__temp != __first) { int __min = 0; __first = __temp; __temp = __parse_DUP_COUNT(__first, __last, __min); if (__temp == __first) __throw_regex_error(); __first = __temp; if (__first == __last) __throw_regex_error(); if (*__first != ',') { __temp = __parse_Back_close_brace(__first, __last); if (__temp == __first) __throw_regex_error(); __push_loop(__min, __min, __s, __mexp_begin, __mexp_end, true); __first = __temp; } else { ++__first; // consume ',' int __max = -1; __first = __parse_DUP_COUNT(__first, __last, __max); __temp = __parse_Back_close_brace(__first, __last); if (__temp == __first) __throw_regex_error(); if (__max == -1) __push_greedy_inf_repeat(__min, __s, __mexp_begin, __mexp_end); else { if (__max < __min) __throw_regex_error(); __push_loop(__min, __max, __s, __mexp_begin, __mexp_end, true); } __first = __temp; } } } } return __first; } template template _ForwardIterator basic_regex<_CharT, _Traits>::__parse_ERE_dupl_symbol(_ForwardIterator __first, _ForwardIterator __last, __owns_one_state<_CharT>* __s, unsigned __mexp_begin, unsigned __mexp_end) { if (__first != __last) { unsigned __grammar = __flags_ & 0x1F0; switch (*__first) { case '*': ++__first; if (__grammar == ECMAScript && __first != __last && *__first == '?') { ++__first; __push_nongreedy_inf_repeat(0, __s, __mexp_begin, __mexp_end); } else __push_greedy_inf_repeat(0, __s, __mexp_begin, __mexp_end); break; case '+': ++__first; if (__grammar == ECMAScript && __first != __last && *__first == '?') { ++__first; __push_nongreedy_inf_repeat(1, __s, __mexp_begin, __mexp_end); } else __push_greedy_inf_repeat(1, __s, __mexp_begin, __mexp_end); break; case '?': ++__first; if (__grammar == ECMAScript && __first != __last && *__first == '?') { ++__first; __push_loop(0, 1, __s, __mexp_begin, __mexp_end, false); } else __push_loop(0, 1, __s, __mexp_begin, __mexp_end); break; case '{': { int __min; _ForwardIterator __temp = __parse_DUP_COUNT(++__first, __last, __min); if (__temp == __first) __throw_regex_error(); __first = __temp; if (__first == __last) __throw_regex_error(); switch (*__first) { case '}': ++__first; if (__grammar == ECMAScript && __first != __last && *__first == '?') { ++__first; __push_loop(__min, __min, __s, __mexp_begin, __mexp_end, false); } else __push_loop(__min, __min, __s, __mexp_begin, __mexp_end); break; case ',': ++__first; if (__first == __last) __throw_regex_error(); if (*__first == '}') { ++__first; if (__grammar == ECMAScript && __first != __last && *__first == '?') { ++__first; __push_nongreedy_inf_repeat(__min, __s, __mexp_begin, __mexp_end); } else __push_greedy_inf_repeat(__min, __s, __mexp_begin, __mexp_end); } else { int __max = -1; __temp = __parse_DUP_COUNT(__first, __last, __max); if (__temp == __first) __throw_regex_error(); __first = __temp; if (__first == __last || *__first != '}') __throw_regex_error(); ++__first; if (__max < __min) __throw_regex_error(); if (__grammar == ECMAScript && __first != __last && *__first == '?') { ++__first; __push_loop(__min, __max, __s, __mexp_begin, __mexp_end, false); } else __push_loop(__min, __max, __s, __mexp_begin, __mexp_end); } break; default: __throw_regex_error(); } } break; } } return __first; } template template _ForwardIterator basic_regex<_CharT, _Traits>::__parse_bracket_expression(_ForwardIterator __first, _ForwardIterator __last) { if (__first != __last && *__first == '[') { ++__first; if (__first == __last) __throw_regex_error(); bool __negate = false; if (*__first == '^') { ++__first; __negate = true; } __bracket_expression<_CharT, _Traits>* __ml = __start_matching_list(__negate); // __ml owned by *this if (__first == __last) __throw_regex_error(); if ((__flags_ & 0x1F0) != ECMAScript && *__first == ']') { __ml->__add_char(']'); ++__first; } __first = __parse_follow_list(__first, __last, __ml); if (__first == __last) __throw_regex_error(); if (*__first == '-') { __ml->__add_char('-'); ++__first; } if (__first == __last || *__first != ']') __throw_regex_error(); ++__first; } return __first; } template template _ForwardIterator basic_regex<_CharT, _Traits>::__parse_follow_list(_ForwardIterator __first, _ForwardIterator __last, __bracket_expression<_CharT, _Traits>* __ml) { if (__first != __last) { while (true) { _ForwardIterator __temp = __parse_expression_term(__first, __last, __ml); if (__temp == __first) break; __first = __temp; } } return __first; } template template _ForwardIterator basic_regex<_CharT, _Traits>::__parse_expression_term(_ForwardIterator __first, _ForwardIterator __last, __bracket_expression<_CharT, _Traits>* __ml) { if (__first != __last && *__first != ']') { _ForwardIterator __temp = _VSTD::next(__first); basic_string<_CharT> __start_range; if (__temp != __last && *__first == '[') { if (*__temp == '=') return __parse_equivalence_class(++__temp, __last, __ml); else if (*__temp == ':') return __parse_character_class(++__temp, __last, __ml); else if (*__temp == '.') __first = __parse_collating_symbol(++__temp, __last, __start_range); } unsigned __grammar = __flags_ & 0x1F0; if (__start_range.empty()) { if ((__grammar == ECMAScript || __grammar == awk) && *__first == '\\') { if (__grammar == ECMAScript) __first = __parse_class_escape(++__first, __last, __start_range, __ml); else __first = __parse_awk_escape(++__first, __last, &__start_range); } else { __start_range = *__first; ++__first; } } if (__first != __last && *__first != ']') { __temp = _VSTD::next(__first); if (__temp != __last && *__first == '-' && *__temp != ']') { // parse a range basic_string<_CharT> __end_range; __first = __temp; ++__temp; if (__temp != __last && *__first == '[' && *__temp == '.') __first = __parse_collating_symbol(++__temp, __last, __end_range); else { if ((__grammar == ECMAScript || __grammar == awk) && *__first == '\\') { if (__grammar == ECMAScript) __first = __parse_class_escape(++__first, __last, __end_range, __ml); else __first = __parse_awk_escape(++__first, __last, &__end_range); } else { __end_range = *__first; ++__first; } } __ml->__add_range(_VSTD::move(__start_range), _VSTD::move(__end_range)); } else if (!__start_range.empty()) { if (__start_range.size() == 1) __ml->__add_char(__start_range[0]); else __ml->__add_digraph(__start_range[0], __start_range[1]); } } else if (!__start_range.empty()) { if (__start_range.size() == 1) __ml->__add_char(__start_range[0]); else __ml->__add_digraph(__start_range[0], __start_range[1]); } } return __first; } template template _ForwardIterator basic_regex<_CharT, _Traits>::__parse_class_escape(_ForwardIterator __first, _ForwardIterator __last, basic_string<_CharT>& __str, __bracket_expression<_CharT, _Traits>* __ml) { if (__first == __last) __throw_regex_error(); switch (*__first) { case 0: __str = *__first; return ++__first; case 'b': __str = _CharT(8); return ++__first; case 'd': __ml->__add_class(ctype_base::digit); return ++__first; case 'D': __ml->__add_neg_class(ctype_base::digit); return ++__first; case 's': __ml->__add_class(ctype_base::space); return ++__first; case 'S': __ml->__add_neg_class(ctype_base::space); return ++__first; case 'w': __ml->__add_class(ctype_base::alnum); __ml->__add_char('_'); return ++__first; case 'W': __ml->__add_neg_class(ctype_base::alnum); __ml->__add_neg_char('_'); return ++__first; } __first = __parse_character_escape(__first, __last, &__str); return __first; } template template _ForwardIterator basic_regex<_CharT, _Traits>::__parse_awk_escape(_ForwardIterator __first, _ForwardIterator __last, basic_string<_CharT>* __str) { if (__first == __last) __throw_regex_error(); switch (*__first) { case '\\': case '"': case '/': if (__str) *__str = *__first; else __push_char(*__first); return ++__first; case 'a': if (__str) *__str = _CharT(7); else __push_char(_CharT(7)); return ++__first; case 'b': if (__str) *__str = _CharT(8); else __push_char(_CharT(8)); return ++__first; case 'f': if (__str) *__str = _CharT(0xC); else __push_char(_CharT(0xC)); return ++__first; case 'n': if (__str) *__str = _CharT(0xA); else __push_char(_CharT(0xA)); return ++__first; case 'r': if (__str) *__str = _CharT(0xD); else __push_char(_CharT(0xD)); return ++__first; case 't': if (__str) *__str = _CharT(0x9); else __push_char(_CharT(0x9)); return ++__first; case 'v': if (__str) *__str = _CharT(0xB); else __push_char(_CharT(0xB)); return ++__first; } if ('0' <= *__first && *__first <= '7') { unsigned __val = *__first - '0'; if (++__first != __last && ('0' <= *__first && *__first <= '7')) { __val = 8 * __val + *__first - '0'; if (++__first != __last && ('0' <= *__first && *__first <= '7')) __val = 8 * __val + *__first++ - '0'; } if (__str) *__str = _CharT(__val); else __push_char(_CharT(__val)); } else __throw_regex_error(); return __first; } template template _ForwardIterator basic_regex<_CharT, _Traits>::__parse_equivalence_class(_ForwardIterator __first, _ForwardIterator __last, __bracket_expression<_CharT, _Traits>* __ml) { // Found [= // This means =] must exist value_type _Equal_close[2] = {'=', ']'}; _ForwardIterator __temp = _VSTD::search(__first, __last, _Equal_close, _Equal_close+2); if (__temp == __last) __throw_regex_error(); // [__first, __temp) contains all text in [= ... =] string_type __collate_name = __traits_.lookup_collatename(__first, __temp); if (__collate_name.empty()) __throw_regex_error(); string_type __equiv_name = __traits_.transform_primary(__collate_name.begin(), __collate_name.end()); if (!__equiv_name.empty()) __ml->__add_equivalence(__equiv_name); else { switch (__collate_name.size()) { case 1: __ml->__add_char(__collate_name[0]); break; case 2: __ml->__add_digraph(__collate_name[0], __collate_name[1]); break; default: __throw_regex_error(); } } __first = _VSTD::next(__temp, 2); return __first; } template template _ForwardIterator basic_regex<_CharT, _Traits>::__parse_character_class(_ForwardIterator __first, _ForwardIterator __last, __bracket_expression<_CharT, _Traits>* __ml) { // Found [: // This means :] must exist value_type _Colon_close[2] = {':', ']'}; _ForwardIterator __temp = _VSTD::search(__first, __last, _Colon_close, _Colon_close+2); if (__temp == __last) __throw_regex_error(); // [__first, __temp) contains all text in [: ... :] typedef typename _Traits::char_class_type char_class_type; char_class_type __class_type = __traits_.lookup_classname(__first, __temp, __flags_ & icase); if (__class_type == 0) __throw_regex_error(); __ml->__add_class(__class_type); __first = _VSTD::next(__temp, 2); return __first; } template template _ForwardIterator basic_regex<_CharT, _Traits>::__parse_collating_symbol(_ForwardIterator __first, _ForwardIterator __last, basic_string<_CharT>& __col_sym) { // Found [. // This means .] must exist value_type _Dot_close[2] = {'.', ']'}; _ForwardIterator __temp = _VSTD::search(__first, __last, _Dot_close, _Dot_close+2); if (__temp == __last) __throw_regex_error(); // [__first, __temp) contains all text in [. ... .] __col_sym = __traits_.lookup_collatename(__first, __temp); switch (__col_sym.size()) { case 1: case 2: break; default: __throw_regex_error(); } __first = _VSTD::next(__temp, 2); return __first; } template template _ForwardIterator basic_regex<_CharT, _Traits>::__parse_DUP_COUNT(_ForwardIterator __first, _ForwardIterator __last, int& __c) { if (__first != __last ) { int __val = __traits_.value(*__first, 10); if ( __val != -1 ) { __c = __val; for (++__first; __first != __last && ( __val = __traits_.value(*__first, 10)) != -1; ++__first) { __c *= 10; __c += __val; } } } return __first; } template template _ForwardIterator basic_regex<_CharT, _Traits>::__parse_ecma_exp(_ForwardIterator __first, _ForwardIterator __last) { __owns_one_state<_CharT>* __sa = __end_; _ForwardIterator __temp = __parse_alternative(__first, __last); if (__temp == __first) __push_empty(); __first = __temp; while (__first != __last && *__first == '|') { __owns_one_state<_CharT>* __sb = __end_; __temp = __parse_alternative(++__first, __last); if (__temp == __first) __push_empty(); __push_alternation(__sa, __sb); __first = __temp; } return __first; } template template _ForwardIterator basic_regex<_CharT, _Traits>::__parse_alternative(_ForwardIterator __first, _ForwardIterator __last) { while (true) { _ForwardIterator __temp = __parse_term(__first, __last); if (__temp == __first) break; __first = __temp; } return __first; } template template _ForwardIterator basic_regex<_CharT, _Traits>::__parse_term(_ForwardIterator __first, _ForwardIterator __last) { _ForwardIterator __temp = __parse_assertion(__first, __last); if (__temp == __first) { __owns_one_state<_CharT>* __e = __end_; unsigned __mexp_begin = __marked_count_; __temp = __parse_atom(__first, __last); if (__temp != __first) __first = __parse_ERE_dupl_symbol(__temp, __last, __e, __mexp_begin+1, __marked_count_+1); } else __first = __temp; return __first; } template template _ForwardIterator basic_regex<_CharT, _Traits>::__parse_assertion(_ForwardIterator __first, _ForwardIterator __last) { if (__first != __last) { switch (*__first) { case '^': __push_l_anchor(); ++__first; break; case '$': __push_r_anchor(); ++__first; break; case '\\': { _ForwardIterator __temp = _VSTD::next(__first); if (__temp != __last) { if (*__temp == 'b') { __push_word_boundary(false); __first = ++__temp; } else if (*__temp == 'B') { __push_word_boundary(true); __first = ++__temp; } } } break; case '(': { _ForwardIterator __temp = _VSTD::next(__first); if (__temp != __last && *__temp == '?') { if (++__temp != __last) { switch (*__temp) { case '=': { basic_regex __exp; __exp.__flags_ = __flags_; __temp = __exp.__parse(++__temp, __last); unsigned __mexp = __exp.__marked_count_; __push_lookahead(_VSTD::move(__exp), false, __marked_count_); __marked_count_ += __mexp; if (__temp == __last || *__temp != ')') __throw_regex_error(); __first = ++__temp; } break; case '!': { basic_regex __exp; __exp.__flags_ = __flags_; __temp = __exp.__parse(++__temp, __last); unsigned __mexp = __exp.__marked_count_; __push_lookahead(_VSTD::move(__exp), true, __marked_count_); __marked_count_ += __mexp; if (__temp == __last || *__temp != ')') __throw_regex_error(); __first = ++__temp; } break; } } } } break; } } return __first; } template template _ForwardIterator basic_regex<_CharT, _Traits>::__parse_atom(_ForwardIterator __first, _ForwardIterator __last) { if (__first != __last) { switch (*__first) { case '.': __push_match_any_but_newline(); ++__first; break; case '\\': __first = __parse_atom_escape(__first, __last); break; case '[': __first = __parse_bracket_expression(__first, __last); break; case '(': { ++__first; if (__first == __last) __throw_regex_error(); _ForwardIterator __temp = _VSTD::next(__first); if (__temp != __last && *__first == '?' && *__temp == ':') { ++__open_count_; __first = __parse_ecma_exp(++__temp, __last); if (__first == __last || *__first != ')') __throw_regex_error(); --__open_count_; ++__first; } else { __push_begin_marked_subexpression(); unsigned __temp_count = __marked_count_; ++__open_count_; __first = __parse_ecma_exp(__first, __last); if (__first == __last || *__first != ')') __throw_regex_error(); __push_end_marked_subexpression(__temp_count); --__open_count_; ++__first; } } break; case '*': case '+': case '?': case '{': __throw_regex_error(); break; default: __first = __parse_pattern_character(__first, __last); break; } } return __first; } template template _ForwardIterator basic_regex<_CharT, _Traits>::__parse_atom_escape(_ForwardIterator __first, _ForwardIterator __last) { if (__first != __last && *__first == '\\') { _ForwardIterator __t1 = _VSTD::next(__first); if (__t1 == __last) __throw_regex_error(); _ForwardIterator __t2 = __parse_decimal_escape(__t1, __last); if (__t2 != __t1) __first = __t2; else { __t2 = __parse_character_class_escape(__t1, __last); if (__t2 != __t1) __first = __t2; else { __t2 = __parse_character_escape(__t1, __last); if (__t2 != __t1) __first = __t2; } } } return __first; } template template _ForwardIterator basic_regex<_CharT, _Traits>::__parse_decimal_escape(_ForwardIterator __first, _ForwardIterator __last) { if (__first != __last) { if (*__first == '0') { __push_char(_CharT()); ++__first; } else if ('1' <= *__first && *__first <= '9') { unsigned __v = *__first - '0'; for (++__first; __first != __last && '0' <= *__first && *__first <= '9'; ++__first) __v = 10 * __v + *__first - '0'; if (__v > mark_count()) __throw_regex_error(); __push_back_ref(__v); } } return __first; } template template _ForwardIterator basic_regex<_CharT, _Traits>::__parse_character_class_escape(_ForwardIterator __first, _ForwardIterator __last) { if (__first != __last) { __bracket_expression<_CharT, _Traits>* __ml; switch (*__first) { case 'd': __ml = __start_matching_list(false); __ml->__add_class(ctype_base::digit); ++__first; break; case 'D': __ml = __start_matching_list(true); __ml->__add_class(ctype_base::digit); ++__first; break; case 's': __ml = __start_matching_list(false); __ml->__add_class(ctype_base::space); ++__first; break; case 'S': __ml = __start_matching_list(true); __ml->__add_class(ctype_base::space); ++__first; break; case 'w': __ml = __start_matching_list(false); __ml->__add_class(ctype_base::alnum); __ml->__add_char('_'); ++__first; break; case 'W': __ml = __start_matching_list(true); __ml->__add_class(ctype_base::alnum); __ml->__add_char('_'); ++__first; break; } } return __first; } template template _ForwardIterator basic_regex<_CharT, _Traits>::__parse_character_escape(_ForwardIterator __first, _ForwardIterator __last, basic_string<_CharT>* __str) { if (__first != __last) { _ForwardIterator __t; unsigned __sum = 0; int __hd; switch (*__first) { case 'f': if (__str) *__str = _CharT(0xC); else __push_char(_CharT(0xC)); ++__first; break; case 'n': if (__str) *__str = _CharT(0xA); else __push_char(_CharT(0xA)); ++__first; break; case 'r': if (__str) *__str = _CharT(0xD); else __push_char(_CharT(0xD)); ++__first; break; case 't': if (__str) *__str = _CharT(0x9); else __push_char(_CharT(0x9)); ++__first; break; case 'v': if (__str) *__str = _CharT(0xB); else __push_char(_CharT(0xB)); ++__first; break; case 'c': if ((__t = _VSTD::next(__first)) != __last) { if (('A' <= *__t && *__t <= 'Z') || ('a' <= *__t && *__t <= 'z')) { if (__str) *__str = _CharT(*__t % 32); else __push_char(_CharT(*__t % 32)); __first = ++__t; } else __throw_regex_error(); } else __throw_regex_error(); break; case 'u': ++__first; if (__first == __last) __throw_regex_error(); __hd = __traits_.value(*__first, 16); if (__hd == -1) __throw_regex_error(); __sum = 16 * __sum + static_cast(__hd); ++__first; if (__first == __last) __throw_regex_error(); __hd = __traits_.value(*__first, 16); if (__hd == -1) __throw_regex_error(); __sum = 16 * __sum + static_cast(__hd); // drop through case 'x': ++__first; if (__first == __last) __throw_regex_error(); __hd = __traits_.value(*__first, 16); if (__hd == -1) __throw_regex_error(); __sum = 16 * __sum + static_cast(__hd); ++__first; if (__first == __last) __throw_regex_error(); __hd = __traits_.value(*__first, 16); if (__hd == -1) __throw_regex_error(); __sum = 16 * __sum + static_cast(__hd); if (__str) *__str = _CharT(__sum); else __push_char(_CharT(__sum)); ++__first; break; case '0': if (__str) *__str = _CharT(0); else __push_char(_CharT(0)); ++__first; break; default: if (*__first != '_' && !__traits_.isctype(*__first, ctype_base::alnum)) { if (__str) *__str = *__first; else __push_char(*__first); ++__first; } else __throw_regex_error(); break; } } return __first; } template template _ForwardIterator basic_regex<_CharT, _Traits>::__parse_pattern_character(_ForwardIterator __first, _ForwardIterator __last) { if (__first != __last) { switch (*__first) { case '^': case '$': case '\\': case '.': case '*': case '+': case '?': case '(': case ')': case '[': case ']': case '{': case '}': case '|': break; default: __push_char(*__first); ++__first; break; } } return __first; } template template _ForwardIterator basic_regex<_CharT, _Traits>::__parse_grep(_ForwardIterator __first, _ForwardIterator __last) { __owns_one_state<_CharT>* __sa = __end_; _ForwardIterator __t1 = _VSTD::find(__first, __last, _CharT('\n')); if (__t1 != __first) __parse_basic_reg_exp(__first, __t1); else __push_empty(); __first = __t1; if (__first != __last) ++__first; while (__first != __last) { __t1 = _VSTD::find(__first, __last, _CharT('\n')); __owns_one_state<_CharT>* __sb = __end_; if (__t1 != __first) __parse_basic_reg_exp(__first, __t1); else __push_empty(); __push_alternation(__sa, __sb); __first = __t1; if (__first != __last) ++__first; } return __first; } template template _ForwardIterator basic_regex<_CharT, _Traits>::__parse_egrep(_ForwardIterator __first, _ForwardIterator __last) { __owns_one_state<_CharT>* __sa = __end_; _ForwardIterator __t1 = _VSTD::find(__first, __last, _CharT('\n')); if (__t1 != __first) __parse_extended_reg_exp(__first, __t1); else __push_empty(); __first = __t1; if (__first != __last) ++__first; while (__first != __last) { __t1 = _VSTD::find(__first, __last, _CharT('\n')); __owns_one_state<_CharT>* __sb = __end_; if (__t1 != __first) __parse_extended_reg_exp(__first, __t1); else __push_empty(); __push_alternation(__sa, __sb); __first = __t1; if (__first != __last) ++__first; } return __first; } template void basic_regex<_CharT, _Traits>::__push_loop(size_t __min, size_t __max, __owns_one_state<_CharT>* __s, size_t __mexp_begin, size_t __mexp_end, bool __greedy) { unique_ptr<__empty_state<_CharT> > __e1(new __empty_state<_CharT>(__end_->first())); __end_->first() = nullptr; unique_ptr<__loop<_CharT> > __e2(new __loop<_CharT>(__loop_count_, __s->first(), __e1.get(), __mexp_begin, __mexp_end, __greedy, __min, __max)); __s->first() = nullptr; __e1.release(); __end_->first() = new __repeat_one_loop<_CharT>(__e2.get()); __end_ = __e2->second(); __s->first() = __e2.release(); ++__loop_count_; } template void basic_regex<_CharT, _Traits>::__push_char(value_type __c) { if (flags() & icase) __end_->first() = new __match_char_icase<_CharT, _Traits> (__traits_, __c, __end_->first()); else if (flags() & collate) __end_->first() = new __match_char_collate<_CharT, _Traits> (__traits_, __c, __end_->first()); else __end_->first() = new __match_char<_CharT>(__c, __end_->first()); __end_ = static_cast<__owns_one_state<_CharT>*>(__end_->first()); } template void basic_regex<_CharT, _Traits>::__push_begin_marked_subexpression() { if (!(__flags_ & nosubs)) { __end_->first() = new __begin_marked_subexpression<_CharT>(++__marked_count_, __end_->first()); __end_ = static_cast<__owns_one_state<_CharT>*>(__end_->first()); } } template void basic_regex<_CharT, _Traits>::__push_end_marked_subexpression(unsigned __sub) { if (!(__flags_ & nosubs)) { __end_->first() = new __end_marked_subexpression<_CharT>(__sub, __end_->first()); __end_ = static_cast<__owns_one_state<_CharT>*>(__end_->first()); } } template void basic_regex<_CharT, _Traits>::__push_l_anchor() { __end_->first() = new __l_anchor<_CharT>(__end_->first()); __end_ = static_cast<__owns_one_state<_CharT>*>(__end_->first()); } template void basic_regex<_CharT, _Traits>::__push_r_anchor() { __end_->first() = new __r_anchor<_CharT>(__end_->first()); __end_ = static_cast<__owns_one_state<_CharT>*>(__end_->first()); } template void basic_regex<_CharT, _Traits>::__push_match_any() { __end_->first() = new __match_any<_CharT>(__end_->first()); __end_ = static_cast<__owns_one_state<_CharT>*>(__end_->first()); } template void basic_regex<_CharT, _Traits>::__push_match_any_but_newline() { __end_->first() = new __match_any_but_newline<_CharT>(__end_->first()); __end_ = static_cast<__owns_one_state<_CharT>*>(__end_->first()); } template void basic_regex<_CharT, _Traits>::__push_empty() { __end_->first() = new __empty_state<_CharT>(__end_->first()); __end_ = static_cast<__owns_one_state<_CharT>*>(__end_->first()); } template void basic_regex<_CharT, _Traits>::__push_word_boundary(bool __invert) { __end_->first() = new __word_boundary<_CharT, _Traits>(__traits_, __invert, __end_->first()); __end_ = static_cast<__owns_one_state<_CharT>*>(__end_->first()); } template void basic_regex<_CharT, _Traits>::__push_back_ref(int __i) { if (flags() & icase) __end_->first() = new __back_ref_icase<_CharT, _Traits> (__traits_, __i, __end_->first()); else if (flags() & collate) __end_->first() = new __back_ref_collate<_CharT, _Traits> (__traits_, __i, __end_->first()); else __end_->first() = new __back_ref<_CharT>(__i, __end_->first()); __end_ = static_cast<__owns_one_state<_CharT>*>(__end_->first()); } template void basic_regex<_CharT, _Traits>::__push_alternation(__owns_one_state<_CharT>* __sa, __owns_one_state<_CharT>* __ea) { __sa->first() = new __alternate<_CharT>( static_cast<__owns_one_state<_CharT>*>(__sa->first()), static_cast<__owns_one_state<_CharT>*>(__ea->first())); __ea->first() = nullptr; __ea->first() = new __empty_state<_CharT>(__end_->first()); __end_->first() = nullptr; __end_->first() = new __empty_non_own_state<_CharT>(__ea->first()); __end_ = static_cast<__owns_one_state<_CharT>*>(__ea->first()); } template __bracket_expression<_CharT, _Traits>* basic_regex<_CharT, _Traits>::__start_matching_list(bool __negate) { __bracket_expression<_CharT, _Traits>* __r = new __bracket_expression<_CharT, _Traits>(__traits_, __end_->first(), __negate, __flags_ & icase, __flags_ & collate); __end_->first() = __r; __end_ = __r; return __r; } template void basic_regex<_CharT, _Traits>::__push_lookahead(const basic_regex& __exp, bool __invert, unsigned __mexp) { __end_->first() = new __lookahead<_CharT, _Traits>(__exp, __invert, __end_->first(), __mexp); __end_ = static_cast<__owns_one_state<_CharT>*>(__end_->first()); } typedef basic_regex regex; typedef basic_regex wregex; // sub_match template class _LIBCPP_TEMPLATE_VIS sub_match : public pair<_BidirectionalIterator, _BidirectionalIterator> { public: typedef _BidirectionalIterator iterator; typedef typename iterator_traits::value_type value_type; typedef typename iterator_traits::difference_type difference_type; typedef basic_string string_type; bool matched; _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR sub_match() : matched() {} _LIBCPP_INLINE_VISIBILITY difference_type length() const {return matched ? _VSTD::distance(this->first, this->second) : 0;} _LIBCPP_INLINE_VISIBILITY string_type str() const {return matched ? string_type(this->first, this->second) : string_type();} _LIBCPP_INLINE_VISIBILITY operator string_type() const {return str();} _LIBCPP_INLINE_VISIBILITY int compare(const sub_match& __s) const {return str().compare(__s.str());} _LIBCPP_INLINE_VISIBILITY int compare(const string_type& __s) const {return str().compare(__s);} _LIBCPP_INLINE_VISIBILITY int compare(const value_type* __s) const {return str().compare(__s);} }; typedef sub_match csub_match; typedef sub_match wcsub_match; typedef sub_match ssub_match; typedef sub_match wssub_match; template inline _LIBCPP_INLINE_VISIBILITY bool operator==(const sub_match<_BiIter>& __x, const sub_match<_BiIter>& __y) { return __x.compare(__y) == 0; } template inline _LIBCPP_INLINE_VISIBILITY bool operator!=(const sub_match<_BiIter>& __x, const sub_match<_BiIter>& __y) { return !(__x == __y); } template inline _LIBCPP_INLINE_VISIBILITY bool operator<(const sub_match<_BiIter>& __x, const sub_match<_BiIter>& __y) { return __x.compare(__y) < 0; } template inline _LIBCPP_INLINE_VISIBILITY bool operator<=(const sub_match<_BiIter>& __x, const sub_match<_BiIter>& __y) { return !(__y < __x); } template inline _LIBCPP_INLINE_VISIBILITY bool operator>=(const sub_match<_BiIter>& __x, const sub_match<_BiIter>& __y) { return !(__x < __y); } template inline _LIBCPP_INLINE_VISIBILITY bool operator>(const sub_match<_BiIter>& __x, const sub_match<_BiIter>& __y) { return __y < __x; } template inline _LIBCPP_INLINE_VISIBILITY bool operator==(const basic_string::value_type, _ST, _SA>& __x, const sub_match<_BiIter>& __y) { return __y.compare(typename sub_match<_BiIter>::string_type(__x.data(), __x.size())) == 0; } template inline _LIBCPP_INLINE_VISIBILITY bool operator!=(const basic_string::value_type, _ST, _SA>& __x, const sub_match<_BiIter>& __y) { return !(__x == __y); } template inline _LIBCPP_INLINE_VISIBILITY bool operator<(const basic_string::value_type, _ST, _SA>& __x, const sub_match<_BiIter>& __y) { return __y.compare(typename sub_match<_BiIter>::string_type(__x.data(), __x.size())) > 0; } template inline _LIBCPP_INLINE_VISIBILITY bool operator>(const basic_string::value_type, _ST, _SA>& __x, const sub_match<_BiIter>& __y) { return __y < __x; } template inline _LIBCPP_INLINE_VISIBILITY bool operator>=(const basic_string::value_type, _ST, _SA>& __x, const sub_match<_BiIter>& __y) { return !(__x < __y); } template inline _LIBCPP_INLINE_VISIBILITY bool operator<=(const basic_string::value_type, _ST, _SA>& __x, const sub_match<_BiIter>& __y) { return !(__y < __x); } template inline _LIBCPP_INLINE_VISIBILITY bool operator==(const sub_match<_BiIter>& __x, const basic_string::value_type, _ST, _SA>& __y) { return __x.compare(typename sub_match<_BiIter>::string_type(__y.data(), __y.size())) == 0; } template inline _LIBCPP_INLINE_VISIBILITY bool operator!=(const sub_match<_BiIter>& __x, const basic_string::value_type, _ST, _SA>& __y) { return !(__x == __y); } template inline _LIBCPP_INLINE_VISIBILITY bool operator<(const sub_match<_BiIter>& __x, const basic_string::value_type, _ST, _SA>& __y) { return __x.compare(typename sub_match<_BiIter>::string_type(__y.data(), __y.size())) < 0; } template inline _LIBCPP_INLINE_VISIBILITY bool operator>(const sub_match<_BiIter>& __x, const basic_string::value_type, _ST, _SA>& __y) { return __y < __x; } template inline _LIBCPP_INLINE_VISIBILITY bool operator>=(const sub_match<_BiIter>& __x, const basic_string::value_type, _ST, _SA>& __y) { return !(__x < __y); } template inline _LIBCPP_INLINE_VISIBILITY bool operator<=(const sub_match<_BiIter>& __x, const basic_string::value_type, _ST, _SA>& __y) { return !(__y < __x); } template inline _LIBCPP_INLINE_VISIBILITY bool operator==(typename iterator_traits<_BiIter>::value_type const* __x, const sub_match<_BiIter>& __y) { return __y.compare(__x) == 0; } template inline _LIBCPP_INLINE_VISIBILITY bool operator!=(typename iterator_traits<_BiIter>::value_type const* __x, const sub_match<_BiIter>& __y) { return !(__x == __y); } template inline _LIBCPP_INLINE_VISIBILITY bool operator<(typename iterator_traits<_BiIter>::value_type const* __x, const sub_match<_BiIter>& __y) { return __y.compare(__x) > 0; } template inline _LIBCPP_INLINE_VISIBILITY bool operator>(typename iterator_traits<_BiIter>::value_type const* __x, const sub_match<_BiIter>& __y) { return __y < __x; } template inline _LIBCPP_INLINE_VISIBILITY bool operator>=(typename iterator_traits<_BiIter>::value_type const* __x, const sub_match<_BiIter>& __y) { return !(__x < __y); } template inline _LIBCPP_INLINE_VISIBILITY bool operator<=(typename iterator_traits<_BiIter>::value_type const* __x, const sub_match<_BiIter>& __y) { return !(__y < __x); } template inline _LIBCPP_INLINE_VISIBILITY bool operator==(const sub_match<_BiIter>& __x, typename iterator_traits<_BiIter>::value_type const* __y) { return __x.compare(__y) == 0; } template inline _LIBCPP_INLINE_VISIBILITY bool operator!=(const sub_match<_BiIter>& __x, typename iterator_traits<_BiIter>::value_type const* __y) { return !(__x == __y); } template inline _LIBCPP_INLINE_VISIBILITY bool operator<(const sub_match<_BiIter>& __x, typename iterator_traits<_BiIter>::value_type const* __y) { return __x.compare(__y) < 0; } template inline _LIBCPP_INLINE_VISIBILITY bool operator>(const sub_match<_BiIter>& __x, typename iterator_traits<_BiIter>::value_type const* __y) { return __y < __x; } template inline _LIBCPP_INLINE_VISIBILITY bool operator>=(const sub_match<_BiIter>& __x, typename iterator_traits<_BiIter>::value_type const* __y) { return !(__x < __y); } template inline _LIBCPP_INLINE_VISIBILITY bool operator<=(const sub_match<_BiIter>& __x, typename iterator_traits<_BiIter>::value_type const* __y) { return !(__y < __x); } template inline _LIBCPP_INLINE_VISIBILITY bool operator==(typename iterator_traits<_BiIter>::value_type const& __x, const sub_match<_BiIter>& __y) { typedef basic_string::value_type> string_type; return __y.compare(string_type(1, __x)) == 0; } template inline _LIBCPP_INLINE_VISIBILITY bool operator!=(typename iterator_traits<_BiIter>::value_type const& __x, const sub_match<_BiIter>& __y) { return !(__x == __y); } template inline _LIBCPP_INLINE_VISIBILITY bool operator<(typename iterator_traits<_BiIter>::value_type const& __x, const sub_match<_BiIter>& __y) { typedef basic_string::value_type> string_type; return __y.compare(string_type(1, __x)) > 0; } template inline _LIBCPP_INLINE_VISIBILITY bool operator>(typename iterator_traits<_BiIter>::value_type const& __x, const sub_match<_BiIter>& __y) { return __y < __x; } template inline _LIBCPP_INLINE_VISIBILITY bool operator>=(typename iterator_traits<_BiIter>::value_type const& __x, const sub_match<_BiIter>& __y) { return !(__x < __y); } template inline _LIBCPP_INLINE_VISIBILITY bool operator<=(typename iterator_traits<_BiIter>::value_type const& __x, const sub_match<_BiIter>& __y) { return !(__y < __x); } template inline _LIBCPP_INLINE_VISIBILITY bool operator==(const sub_match<_BiIter>& __x, typename iterator_traits<_BiIter>::value_type const& __y) { typedef basic_string::value_type> string_type; return __x.compare(string_type(1, __y)) == 0; } template inline _LIBCPP_INLINE_VISIBILITY bool operator!=(const sub_match<_BiIter>& __x, typename iterator_traits<_BiIter>::value_type const& __y) { return !(__x == __y); } template inline _LIBCPP_INLINE_VISIBILITY bool operator<(const sub_match<_BiIter>& __x, typename iterator_traits<_BiIter>::value_type const& __y) { typedef basic_string::value_type> string_type; return __x.compare(string_type(1, __y)) < 0; } template inline _LIBCPP_INLINE_VISIBILITY bool operator>(const sub_match<_BiIter>& __x, typename iterator_traits<_BiIter>::value_type const& __y) { return __y < __x; } template inline _LIBCPP_INLINE_VISIBILITY bool operator>=(const sub_match<_BiIter>& __x, typename iterator_traits<_BiIter>::value_type const& __y) { return !(__x < __y); } template inline _LIBCPP_INLINE_VISIBILITY bool operator<=(const sub_match<_BiIter>& __x, typename iterator_traits<_BiIter>::value_type const& __y) { return !(__y < __x); } template inline _LIBCPP_INLINE_VISIBILITY basic_ostream<_CharT, _ST>& operator<<(basic_ostream<_CharT, _ST>& __os, const sub_match<_BiIter>& __m) { return __os << __m.str(); } template class _LIBCPP_TEMPLATE_VIS match_results { public: typedef _Allocator allocator_type; typedef sub_match<_BidirectionalIterator> value_type; private: typedef vector __container_type; __container_type __matches_; value_type __unmatched_; value_type __prefix_; value_type __suffix_; bool __ready_; public: _BidirectionalIterator __position_start_; typedef const value_type& const_reference; typedef value_type& reference; typedef typename __container_type::const_iterator const_iterator; typedef const_iterator iterator; typedef typename iterator_traits<_BidirectionalIterator>::difference_type difference_type; typedef typename allocator_traits::size_type size_type; typedef typename iterator_traits<_BidirectionalIterator>::value_type char_type; typedef basic_string string_type; // construct/copy/destroy: explicit match_results(const allocator_type& __a = allocator_type()); // match_results(const match_results&) = default; // match_results& operator=(const match_results&) = default; // match_results(match_results&& __m) = default; // match_results& operator=(match_results&& __m) = default; // ~match_results() = default; _LIBCPP_INLINE_VISIBILITY bool ready() const {return __ready_;} // size: _LIBCPP_INLINE_VISIBILITY size_type size() const {return __matches_.size();} _LIBCPP_INLINE_VISIBILITY size_type max_size() const {return __matches_.max_size();} _LIBCPP_INLINE_VISIBILITY bool empty() const {return size() == 0;} // element access: _LIBCPP_INLINE_VISIBILITY difference_type length(size_type __sub = 0) const {return (*this)[__sub].length();} _LIBCPP_INLINE_VISIBILITY difference_type position(size_type __sub = 0) const {return _VSTD::distance(__position_start_, (*this)[__sub].first);} _LIBCPP_INLINE_VISIBILITY string_type str(size_type __sub = 0) const {return (*this)[__sub].str();} _LIBCPP_INLINE_VISIBILITY const_reference operator[](size_type __n) const {return __n < __matches_.size() ? __matches_[__n] : __unmatched_;} _LIBCPP_INLINE_VISIBILITY const_reference prefix() const {return __prefix_;} _LIBCPP_INLINE_VISIBILITY const_reference suffix() const {return __suffix_;} _LIBCPP_INLINE_VISIBILITY const_iterator begin() const {return empty() ? __matches_.end() : __matches_.begin();} _LIBCPP_INLINE_VISIBILITY const_iterator end() const {return __matches_.end();} _LIBCPP_INLINE_VISIBILITY const_iterator cbegin() const {return empty() ? __matches_.end() : __matches_.begin();} _LIBCPP_INLINE_VISIBILITY const_iterator cend() const {return __matches_.end();} // format: template _OutputIter format(_OutputIter __output, const char_type* __fmt_first, const char_type* __fmt_last, regex_constants::match_flag_type __flags = regex_constants::format_default) const; template _LIBCPP_INLINE_VISIBILITY _OutputIter format(_OutputIter __output, const basic_string& __fmt, regex_constants::match_flag_type __flags = regex_constants::format_default) const {return format(__output, __fmt.data(), __fmt.data() + __fmt.size(), __flags);} template _LIBCPP_INLINE_VISIBILITY basic_string format(const basic_string& __fmt, regex_constants::match_flag_type __flags = regex_constants::format_default) const { basic_string __r; format(back_inserter(__r), __fmt.data(), __fmt.data() + __fmt.size(), __flags); return __r; } _LIBCPP_INLINE_VISIBILITY string_type format(const char_type* __fmt, regex_constants::match_flag_type __flags = regex_constants::format_default) const { string_type __r; format(back_inserter(__r), __fmt, __fmt + char_traits::length(__fmt), __flags); return __r; } // allocator: _LIBCPP_INLINE_VISIBILITY allocator_type get_allocator() const {return __matches_.get_allocator();} // swap: void swap(match_results& __m); template _LIBCPP_INLINE_VISIBILITY void __assign(_BidirectionalIterator __f, _BidirectionalIterator __l, const match_results<_Bp, _Ap>& __m, bool __no_update_pos) { _Bp __mf = __m.prefix().first; __matches_.resize(__m.size()); for (size_type __i = 0; __i < __matches_.size(); ++__i) { __matches_[__i].first = _VSTD::next(__f, _VSTD::distance(__mf, __m[__i].first)); __matches_[__i].second = _VSTD::next(__f, _VSTD::distance(__mf, __m[__i].second)); __matches_[__i].matched = __m[__i].matched; } __unmatched_.first = __l; __unmatched_.second = __l; __unmatched_.matched = false; __prefix_.first = _VSTD::next(__f, _VSTD::distance(__mf, __m.prefix().first)); __prefix_.second = _VSTD::next(__f, _VSTD::distance(__mf, __m.prefix().second)); __prefix_.matched = __m.prefix().matched; __suffix_.first = _VSTD::next(__f, _VSTD::distance(__mf, __m.suffix().first)); __suffix_.second = _VSTD::next(__f, _VSTD::distance(__mf, __m.suffix().second)); __suffix_.matched = __m.suffix().matched; if (!__no_update_pos) __position_start_ = __prefix_.first; __ready_ = __m.ready(); } private: void __init(unsigned __s, _BidirectionalIterator __f, _BidirectionalIterator __l, bool __no_update_pos = false); template friend class basic_regex; template friend bool regex_match(_Bp, _Bp, match_results<_Bp, _Ap>&, const basic_regex<_Cp, _Tp>&, regex_constants::match_flag_type); template friend bool operator==(const match_results<_Bp, _Ap>&, const match_results<_Bp, _Ap>&); template friend class __lookahead; }; template match_results<_BidirectionalIterator, _Allocator>::match_results( const allocator_type& __a) : __matches_(__a), __unmatched_(), __prefix_(), __suffix_(), __ready_(false), __position_start_() { } template void match_results<_BidirectionalIterator, _Allocator>::__init(unsigned __s, _BidirectionalIterator __f, _BidirectionalIterator __l, bool __no_update_pos) { __unmatched_.first = __l; __unmatched_.second = __l; __unmatched_.matched = false; __matches_.assign(__s, __unmatched_); __prefix_.first = __f; __prefix_.second = __f; __prefix_.matched = false; __suffix_ = __unmatched_; if (!__no_update_pos) __position_start_ = __prefix_.first; __ready_ = true; } template template _OutputIter match_results<_BidirectionalIterator, _Allocator>::format(_OutputIter __output, const char_type* __fmt_first, const char_type* __fmt_last, regex_constants::match_flag_type __flags) const { if (__flags & regex_constants::format_sed) { for (; __fmt_first != __fmt_last; ++__fmt_first) { if (*__fmt_first == '&') __output = _VSTD::copy(__matches_[0].first, __matches_[0].second, __output); else if (*__fmt_first == '\\' && __fmt_first + 1 != __fmt_last) { ++__fmt_first; if ('0' <= *__fmt_first && *__fmt_first <= '9') { size_t __i = *__fmt_first - '0'; __output = _VSTD::copy((*this)[__i].first, (*this)[__i].second, __output); } else { *__output = *__fmt_first; ++__output; } } else { *__output = *__fmt_first; ++__output; } } } else { for (; __fmt_first != __fmt_last; ++__fmt_first) { if (*__fmt_first == '$' && __fmt_first + 1 != __fmt_last) { switch (__fmt_first[1]) { case '$': *__output = *++__fmt_first; ++__output; break; case '&': ++__fmt_first; __output = _VSTD::copy(__matches_[0].first, __matches_[0].second, __output); break; case '`': ++__fmt_first; __output = _VSTD::copy(__prefix_.first, __prefix_.second, __output); break; case '\'': ++__fmt_first; __output = _VSTD::copy(__suffix_.first, __suffix_.second, __output); break; default: if ('0' <= __fmt_first[1] && __fmt_first[1] <= '9') { ++__fmt_first; size_t __i = *__fmt_first - '0'; if (__fmt_first + 1 != __fmt_last && '0' <= __fmt_first[1] && __fmt_first[1] <= '9') { ++__fmt_first; __i = 10 * __i + *__fmt_first - '0'; } __output = _VSTD::copy((*this)[__i].first, (*this)[__i].second, __output); } else { *__output = *__fmt_first; ++__output; } break; } } else { *__output = *__fmt_first; ++__output; } } } return __output; } template void match_results<_BidirectionalIterator, _Allocator>::swap(match_results& __m) { using _VSTD::swap; swap(__matches_, __m.__matches_); swap(__unmatched_, __m.__unmatched_); swap(__prefix_, __m.__prefix_); swap(__suffix_, __m.__suffix_); swap(__position_start_, __m.__position_start_); swap(__ready_, __m.__ready_); } typedef match_results cmatch; typedef match_results wcmatch; typedef match_results smatch; typedef match_results wsmatch; template bool operator==(const match_results<_BidirectionalIterator, _Allocator>& __x, const match_results<_BidirectionalIterator, _Allocator>& __y) { if (__x.__ready_ != __y.__ready_) return false; if (!__x.__ready_) return true; return __x.__matches_ == __y.__matches_ && __x.__prefix_ == __y.__prefix_ && __x.__suffix_ == __y.__suffix_; } template inline _LIBCPP_INLINE_VISIBILITY bool operator!=(const match_results<_BidirectionalIterator, _Allocator>& __x, const match_results<_BidirectionalIterator, _Allocator>& __y) { return !(__x == __y); } template inline _LIBCPP_INLINE_VISIBILITY void swap(match_results<_BidirectionalIterator, _Allocator>& __x, match_results<_BidirectionalIterator, _Allocator>& __y) { __x.swap(__y); } // regex_search template template bool basic_regex<_CharT, _Traits>::__match_at_start_ecma( const _CharT* __first, const _CharT* __last, match_results& __m, regex_constants::match_flag_type __flags, bool __at_first) const { vector<__state> __states; __node* __st = __start_.get(); if (__st) { sub_match __unmatched; __unmatched.first = __last; __unmatched.second = __last; __unmatched.matched = false; __states.push_back(__state()); __states.back().__do_ = 0; __states.back().__first_ = __first; __states.back().__current_ = __first; __states.back().__last_ = __last; __states.back().__sub_matches_.resize(mark_count(), __unmatched); __states.back().__loop_data_.resize(__loop_count()); __states.back().__node_ = __st; __states.back().__flags_ = __flags; __states.back().__at_first_ = __at_first; do { __state& __s = __states.back(); if (__s.__node_) __s.__node_->__exec(__s); switch (__s.__do_) { case __state::__end_state: if ((__flags & regex_constants::match_not_null) && __s.__current_ == __first) { __states.pop_back(); break; } if ((__flags & regex_constants::__full_match) && __s.__current_ != __last) { __states.pop_back(); break; } __m.__matches_[0].first = __first; __m.__matches_[0].second = _VSTD::next(__first, __s.__current_ - __first); __m.__matches_[0].matched = true; for (unsigned __i = 0; __i < __s.__sub_matches_.size(); ++__i) __m.__matches_[__i+1] = __s.__sub_matches_[__i]; return true; case __state::__accept_and_consume: case __state::__repeat: case __state::__accept_but_not_consume: break; case __state::__split: { __state __snext = __s; __s.__node_->__exec_split(true, __s); __snext.__node_->__exec_split(false, __snext); __states.push_back(_VSTD::move(__snext)); } break; case __state::__reject: __states.pop_back(); break; default: __throw_regex_error(); break; } } while (!__states.empty()); } return false; } template template bool basic_regex<_CharT, _Traits>::__match_at_start_posix_nosubs( const _CharT* __first, const _CharT* __last, match_results& __m, regex_constants::match_flag_type __flags, bool __at_first) const { deque<__state> __states; ptrdiff_t __highest_j = 0; ptrdiff_t _Np = _VSTD::distance(__first, __last); __node* __st = __start_.get(); if (__st) { __states.push_back(__state()); __states.back().__do_ = 0; __states.back().__first_ = __first; __states.back().__current_ = __first; __states.back().__last_ = __last; __states.back().__loop_data_.resize(__loop_count()); __states.back().__node_ = __st; __states.back().__flags_ = __flags; __states.back().__at_first_ = __at_first; bool __matched = false; do { __state& __s = __states.back(); if (__s.__node_) __s.__node_->__exec(__s); switch (__s.__do_) { case __state::__end_state: if ((__flags & regex_constants::match_not_null) && __s.__current_ == __first) { __states.pop_back(); break; } if ((__flags & regex_constants::__full_match) && __s.__current_ != __last) { __states.pop_back(); break; } if (!__matched || __highest_j < __s.__current_ - __s.__first_) __highest_j = __s.__current_ - __s.__first_; __matched = true; if (__highest_j == _Np) __states.clear(); else __states.pop_back(); break; case __state::__consume_input: break; case __state::__accept_and_consume: __states.push_front(_VSTD::move(__s)); __states.pop_back(); break; case __state::__repeat: case __state::__accept_but_not_consume: break; case __state::__split: { __state __snext = __s; __s.__node_->__exec_split(true, __s); __snext.__node_->__exec_split(false, __snext); __states.push_back(_VSTD::move(__snext)); } break; case __state::__reject: __states.pop_back(); break; default: __throw_regex_error(); break; } } while (!__states.empty()); if (__matched) { __m.__matches_[0].first = __first; __m.__matches_[0].second = _VSTD::next(__first, __highest_j); __m.__matches_[0].matched = true; return true; } } return false; } template template bool basic_regex<_CharT, _Traits>::__match_at_start_posix_subs( const _CharT* __first, const _CharT* __last, match_results& __m, regex_constants::match_flag_type __flags, bool __at_first) const { vector<__state> __states; __state __best_state; ptrdiff_t __j = 0; ptrdiff_t __highest_j = 0; ptrdiff_t _Np = _VSTD::distance(__first, __last); __node* __st = __start_.get(); if (__st) { sub_match __unmatched; __unmatched.first = __last; __unmatched.second = __last; __unmatched.matched = false; __states.push_back(__state()); __states.back().__do_ = 0; __states.back().__first_ = __first; __states.back().__current_ = __first; __states.back().__last_ = __last; __states.back().__sub_matches_.resize(mark_count(), __unmatched); __states.back().__loop_data_.resize(__loop_count()); __states.back().__node_ = __st; __states.back().__flags_ = __flags; __states.back().__at_first_ = __at_first; const _CharT* __current = __first; bool __matched = false; do { __state& __s = __states.back(); if (__s.__node_) __s.__node_->__exec(__s); switch (__s.__do_) { case __state::__end_state: if ((__flags & regex_constants::match_not_null) && __s.__current_ == __first) { __states.pop_back(); break; } if ((__flags & regex_constants::__full_match) && __s.__current_ != __last) { __states.pop_back(); break; } if (!__matched || __highest_j < __s.__current_ - __s.__first_) { __highest_j = __s.__current_ - __s.__first_; __best_state = __s; } __matched = true; if (__highest_j == _Np) __states.clear(); else __states.pop_back(); break; case __state::__accept_and_consume: __j += __s.__current_ - __current; __current = __s.__current_; break; case __state::__repeat: case __state::__accept_but_not_consume: break; case __state::__split: { __state __snext = __s; __s.__node_->__exec_split(true, __s); __snext.__node_->__exec_split(false, __snext); __states.push_back(_VSTD::move(__snext)); } break; case __state::__reject: __states.pop_back(); break; default: __throw_regex_error(); break; } } while (!__states.empty()); if (__matched) { __m.__matches_[0].first = __first; __m.__matches_[0].second = _VSTD::next(__first, __highest_j); __m.__matches_[0].matched = true; for (unsigned __i = 0; __i < __best_state.__sub_matches_.size(); ++__i) __m.__matches_[__i+1] = __best_state.__sub_matches_[__i]; return true; } } return false; } template template bool basic_regex<_CharT, _Traits>::__match_at_start( const _CharT* __first, const _CharT* __last, match_results& __m, regex_constants::match_flag_type __flags, bool __at_first) const { if ((__flags_ & 0x1F0) == ECMAScript) return __match_at_start_ecma(__first, __last, __m, __flags, __at_first); if (mark_count() == 0) return __match_at_start_posix_nosubs(__first, __last, __m, __flags, __at_first); return __match_at_start_posix_subs(__first, __last, __m, __flags, __at_first); } template template bool basic_regex<_CharT, _Traits>::__search( const _CharT* __first, const _CharT* __last, match_results& __m, regex_constants::match_flag_type __flags) const { __m.__init(1 + mark_count(), __first, __last, __flags & regex_constants::__no_update_pos); if (__match_at_start(__first, __last, __m, __flags, !(__flags & regex_constants::__no_update_pos))) { __m.__prefix_.second = __m[0].first; __m.__prefix_.matched = __m.__prefix_.first != __m.__prefix_.second; __m.__suffix_.first = __m[0].second; __m.__suffix_.matched = __m.__suffix_.first != __m.__suffix_.second; return true; } if (__first != __last && !(__flags & regex_constants::match_continuous)) { __flags |= regex_constants::match_prev_avail; for (++__first; __first != __last; ++__first) { __m.__matches_.assign(__m.size(), __m.__unmatched_); if (__match_at_start(__first, __last, __m, __flags, false)) { __m.__prefix_.second = __m[0].first; __m.__prefix_.matched = __m.__prefix_.first != __m.__prefix_.second; __m.__suffix_.first = __m[0].second; __m.__suffix_.matched = __m.__suffix_.first != __m.__suffix_.second; return true; } __m.__matches_.assign(__m.size(), __m.__unmatched_); } } __m.__matches_.clear(); return false; } template inline _LIBCPP_INLINE_VISIBILITY bool regex_search(_BidirectionalIterator __first, _BidirectionalIterator __last, match_results<_BidirectionalIterator, _Allocator>& __m, const basic_regex<_CharT, _Traits>& __e, regex_constants::match_flag_type __flags = regex_constants::match_default) { int __offset = (__flags & regex_constants::match_prev_avail) ? 1 : 0; basic_string<_CharT> __s(_VSTD::prev(__first, __offset), __last); match_results __mc; bool __r = __e.__search(__s.data() + __offset, __s.data() + __s.size(), __mc, __flags); __m.__assign(__first, __last, __mc, __flags & regex_constants::__no_update_pos); return __r; } template inline _LIBCPP_INLINE_VISIBILITY bool regex_search(__wrap_iter<_Iter> __first, __wrap_iter<_Iter> __last, match_results<__wrap_iter<_Iter>, _Allocator>& __m, const basic_regex<_CharT, _Traits>& __e, regex_constants::match_flag_type __flags = regex_constants::match_default) { match_results __mc; bool __r = __e.__search(__first.base(), __last.base(), __mc, __flags); __m.__assign(__first, __last, __mc, __flags & regex_constants::__no_update_pos); return __r; } template inline _LIBCPP_INLINE_VISIBILITY bool regex_search(const _CharT* __first, const _CharT* __last, match_results& __m, const basic_regex<_CharT, _Traits>& __e, regex_constants::match_flag_type __flags = regex_constants::match_default) { return __e.__search(__first, __last, __m, __flags); } template inline _LIBCPP_INLINE_VISIBILITY bool regex_search(_BidirectionalIterator __first, _BidirectionalIterator __last, const basic_regex<_CharT, _Traits>& __e, regex_constants::match_flag_type __flags = regex_constants::match_default) { basic_string<_CharT> __s(__first, __last); match_results __mc; return __e.__search(__s.data(), __s.data() + __s.size(), __mc, __flags); } template inline _LIBCPP_INLINE_VISIBILITY bool regex_search(const _CharT* __first, const _CharT* __last, const basic_regex<_CharT, _Traits>& __e, regex_constants::match_flag_type __flags = regex_constants::match_default) { match_results __mc; return __e.__search(__first, __last, __mc, __flags); } template inline _LIBCPP_INLINE_VISIBILITY bool regex_search(const _CharT* __str, match_results& __m, const basic_regex<_CharT, _Traits>& __e, regex_constants::match_flag_type __flags = regex_constants::match_default) { return __e.__search(__str, __str + _Traits::length(__str), __m, __flags); } template inline _LIBCPP_INLINE_VISIBILITY bool regex_search(const _CharT* __str, const basic_regex<_CharT, _Traits>& __e, regex_constants::match_flag_type __flags = regex_constants::match_default) { match_results __m; return _VSTD::regex_search(__str, __m, __e, __flags); } template inline _LIBCPP_INLINE_VISIBILITY bool regex_search(const basic_string<_CharT, _ST, _SA>& __s, const basic_regex<_CharT, _Traits>& __e, regex_constants::match_flag_type __flags = regex_constants::match_default) { match_results __mc; return __e.__search(__s.data(), __s.data() + __s.size(), __mc, __flags); } template inline _LIBCPP_INLINE_VISIBILITY bool regex_search(const basic_string<_CharT, _ST, _SA>& __s, match_results::const_iterator, _Allocator>& __m, const basic_regex<_CharT, _Traits>& __e, regex_constants::match_flag_type __flags = regex_constants::match_default) { match_results __mc; bool __r = __e.__search(__s.data(), __s.data() + __s.size(), __mc, __flags); __m.__assign(__s.begin(), __s.end(), __mc, __flags & regex_constants::__no_update_pos); return __r; } #if _LIBCPP_STD_VER > 11 template bool regex_search(const basic_string<_Cp, _ST, _SA>&& __s, match_results::const_iterator, _Ap>&, const basic_regex<_Cp, _Tp>& __e, regex_constants::match_flag_type __flags = regex_constants::match_default) = delete; #endif // regex_match template bool regex_match(_BidirectionalIterator __first, _BidirectionalIterator __last, match_results<_BidirectionalIterator, _Allocator>& __m, const basic_regex<_CharT, _Traits>& __e, regex_constants::match_flag_type __flags = regex_constants::match_default) { bool __r = _VSTD::regex_search( __first, __last, __m, __e, __flags | regex_constants::match_continuous | regex_constants::__full_match); if (__r) { __r = !__m.suffix().matched; if (!__r) __m.__matches_.clear(); } return __r; } template inline _LIBCPP_INLINE_VISIBILITY bool regex_match(_BidirectionalIterator __first, _BidirectionalIterator __last, const basic_regex<_CharT, _Traits>& __e, regex_constants::match_flag_type __flags = regex_constants::match_default) { match_results<_BidirectionalIterator> __m; return _VSTD::regex_match(__first, __last, __m, __e, __flags); } template inline _LIBCPP_INLINE_VISIBILITY bool regex_match(const _CharT* __str, match_results& __m, const basic_regex<_CharT, _Traits>& __e, regex_constants::match_flag_type __flags = regex_constants::match_default) { return _VSTD::regex_match(__str, __str + _Traits::length(__str), __m, __e, __flags); } template inline _LIBCPP_INLINE_VISIBILITY bool regex_match(const basic_string<_CharT, _ST, _SA>& __s, match_results::const_iterator, _Allocator>& __m, const basic_regex<_CharT, _Traits>& __e, regex_constants::match_flag_type __flags = regex_constants::match_default) { return _VSTD::regex_match(__s.begin(), __s.end(), __m, __e, __flags); } #if _LIBCPP_STD_VER > 11 template inline _LIBCPP_INLINE_VISIBILITY bool regex_match(const basic_string<_CharT, _ST, _SA>&& __s, match_results::const_iterator, _Allocator>& __m, const basic_regex<_CharT, _Traits>& __e, regex_constants::match_flag_type __flags = regex_constants::match_default) = delete; #endif template inline _LIBCPP_INLINE_VISIBILITY bool regex_match(const _CharT* __str, const basic_regex<_CharT, _Traits>& __e, regex_constants::match_flag_type __flags = regex_constants::match_default) { return _VSTD::regex_match(__str, __str + _Traits::length(__str), __e, __flags); } template inline _LIBCPP_INLINE_VISIBILITY bool regex_match(const basic_string<_CharT, _ST, _SA>& __s, const basic_regex<_CharT, _Traits>& __e, regex_constants::match_flag_type __flags = regex_constants::match_default) { return _VSTD::regex_match(__s.begin(), __s.end(), __e, __flags); } // regex_iterator template ::value_type, class _Traits = regex_traits<_CharT> > class _LIBCPP_TEMPLATE_VIS regex_iterator { public: typedef basic_regex<_CharT, _Traits> regex_type; typedef match_results<_BidirectionalIterator> value_type; typedef ptrdiff_t difference_type; typedef const value_type* pointer; typedef const value_type& reference; typedef forward_iterator_tag iterator_category; private: _BidirectionalIterator __begin_; _BidirectionalIterator __end_; const regex_type* __pregex_; regex_constants::match_flag_type __flags_; value_type __match_; public: regex_iterator(); regex_iterator(_BidirectionalIterator __a, _BidirectionalIterator __b, const regex_type& __re, regex_constants::match_flag_type __m = regex_constants::match_default); #if _LIBCPP_STD_VER > 11 regex_iterator(_BidirectionalIterator __a, _BidirectionalIterator __b, const regex_type&& __re, regex_constants::match_flag_type __m = regex_constants::match_default) = delete; #endif bool operator==(const regex_iterator& __x) const; _LIBCPP_INLINE_VISIBILITY bool operator!=(const regex_iterator& __x) const {return !(*this == __x);} _LIBCPP_INLINE_VISIBILITY reference operator*() const {return __match_;} _LIBCPP_INLINE_VISIBILITY pointer operator->() const {return &__match_;} regex_iterator& operator++(); _LIBCPP_INLINE_VISIBILITY regex_iterator operator++(int) { regex_iterator __t(*this); ++(*this); return __t; } }; template regex_iterator<_BidirectionalIterator, _CharT, _Traits>::regex_iterator() : __begin_(), __end_(), __pregex_(nullptr), __flags_(), __match_() { } template regex_iterator<_BidirectionalIterator, _CharT, _Traits>:: regex_iterator(_BidirectionalIterator __a, _BidirectionalIterator __b, const regex_type& __re, regex_constants::match_flag_type __m) : __begin_(__a), __end_(__b), __pregex_(&__re), __flags_(__m) { _VSTD::regex_search(__begin_, __end_, __match_, *__pregex_, __flags_); } template bool regex_iterator<_BidirectionalIterator, _CharT, _Traits>:: operator==(const regex_iterator& __x) const { if (__match_.empty() && __x.__match_.empty()) return true; if (__match_.empty() || __x.__match_.empty()) return false; return __begin_ == __x.__begin_ && __end_ == __x.__end_ && __pregex_ == __x.__pregex_ && __flags_ == __x.__flags_ && __match_[0] == __x.__match_[0]; } template regex_iterator<_BidirectionalIterator, _CharT, _Traits>& regex_iterator<_BidirectionalIterator, _CharT, _Traits>::operator++() { __flags_ |= regex_constants::__no_update_pos; _BidirectionalIterator __start = __match_[0].second; - if (__match_.empty()) + if (__match_[0].first == __match_[0].second) { if (__start == __end_) { __match_ = value_type(); return *this; } else if (_VSTD::regex_search(__start, __end_, __match_, *__pregex_, __flags_ | regex_constants::match_not_null | regex_constants::match_continuous)) return *this; else ++__start; } __flags_ |= regex_constants::match_prev_avail; if (!_VSTD::regex_search(__start, __end_, __match_, *__pregex_, __flags_)) __match_ = value_type(); return *this; } typedef regex_iterator cregex_iterator; typedef regex_iterator wcregex_iterator; typedef regex_iterator sregex_iterator; typedef regex_iterator wsregex_iterator; // regex_token_iterator template ::value_type, class _Traits = regex_traits<_CharT> > class _LIBCPP_TEMPLATE_VIS regex_token_iterator { public: typedef basic_regex<_CharT, _Traits> regex_type; typedef sub_match<_BidirectionalIterator> value_type; typedef ptrdiff_t difference_type; typedef const value_type* pointer; typedef const value_type& reference; typedef forward_iterator_tag iterator_category; private: typedef regex_iterator<_BidirectionalIterator, _CharT, _Traits> _Position; _Position __position_; const value_type* __result_; value_type __suffix_; ptrdiff_t __n_; vector __subs_; public: regex_token_iterator(); regex_token_iterator(_BidirectionalIterator __a, _BidirectionalIterator __b, const regex_type& __re, int __submatch = 0, regex_constants::match_flag_type __m = regex_constants::match_default); #if _LIBCPP_STD_VER > 11 regex_token_iterator(_BidirectionalIterator __a, _BidirectionalIterator __b, const regex_type&& __re, int __submatch = 0, regex_constants::match_flag_type __m = regex_constants::match_default) = delete; #endif regex_token_iterator(_BidirectionalIterator __a, _BidirectionalIterator __b, const regex_type& __re, const vector& __submatches, regex_constants::match_flag_type __m = regex_constants::match_default); #if _LIBCPP_STD_VER > 11 regex_token_iterator(_BidirectionalIterator __a, _BidirectionalIterator __b, const regex_type&& __re, const vector& __submatches, regex_constants::match_flag_type __m = regex_constants::match_default) = delete; #endif #ifndef _LIBCPP_CXX03_LANG regex_token_iterator(_BidirectionalIterator __a, _BidirectionalIterator __b, const regex_type& __re, initializer_list __submatches, regex_constants::match_flag_type __m = regex_constants::match_default); #if _LIBCPP_STD_VER > 11 regex_token_iterator(_BidirectionalIterator __a, _BidirectionalIterator __b, const regex_type&& __re, initializer_list __submatches, regex_constants::match_flag_type __m = regex_constants::match_default) = delete; #endif #endif // _LIBCPP_CXX03_LANG template regex_token_iterator(_BidirectionalIterator __a, _BidirectionalIterator __b, const regex_type& __re, const int (&__submatches)[_Np], regex_constants::match_flag_type __m = regex_constants::match_default); #if _LIBCPP_STD_VER > 11 template regex_token_iterator(_BidirectionalIterator __a, _BidirectionalIterator __b, const regex_type&& __re, const int (&__submatches)[_Np], regex_constants::match_flag_type __m = regex_constants::match_default) = delete; #endif regex_token_iterator(const regex_token_iterator&); regex_token_iterator& operator=(const regex_token_iterator&); bool operator==(const regex_token_iterator& __x) const; _LIBCPP_INLINE_VISIBILITY bool operator!=(const regex_token_iterator& __x) const {return !(*this == __x);} _LIBCPP_INLINE_VISIBILITY const value_type& operator*() const {return *__result_;} _LIBCPP_INLINE_VISIBILITY const value_type* operator->() const {return __result_;} regex_token_iterator& operator++(); _LIBCPP_INLINE_VISIBILITY regex_token_iterator operator++(int) { regex_token_iterator __t(*this); ++(*this); return __t; } private: void __init(_BidirectionalIterator __a, _BidirectionalIterator __b); void __establish_result () { if (__subs_[__n_] == -1) __result_ = &__position_->prefix(); else __result_ = &(*__position_)[__subs_[__n_]]; } }; template regex_token_iterator<_BidirectionalIterator, _CharT, _Traits>:: regex_token_iterator() : __result_(nullptr), __suffix_(), __n_(0) { } template void regex_token_iterator<_BidirectionalIterator, _CharT, _Traits>:: __init(_BidirectionalIterator __a, _BidirectionalIterator __b) { if (__position_ != _Position()) __establish_result (); else if (__subs_[__n_] == -1) { __suffix_.matched = true; __suffix_.first = __a; __suffix_.second = __b; __result_ = &__suffix_; } else __result_ = nullptr; } template regex_token_iterator<_BidirectionalIterator, _CharT, _Traits>:: regex_token_iterator(_BidirectionalIterator __a, _BidirectionalIterator __b, const regex_type& __re, int __submatch, regex_constants::match_flag_type __m) : __position_(__a, __b, __re, __m), __n_(0), __subs_(1, __submatch) { __init(__a, __b); } template regex_token_iterator<_BidirectionalIterator, _CharT, _Traits>:: regex_token_iterator(_BidirectionalIterator __a, _BidirectionalIterator __b, const regex_type& __re, const vector& __submatches, regex_constants::match_flag_type __m) : __position_(__a, __b, __re, __m), __n_(0), __subs_(__submatches) { __init(__a, __b); } #ifndef _LIBCPP_CXX03_LANG template regex_token_iterator<_BidirectionalIterator, _CharT, _Traits>:: regex_token_iterator(_BidirectionalIterator __a, _BidirectionalIterator __b, const regex_type& __re, initializer_list __submatches, regex_constants::match_flag_type __m) : __position_(__a, __b, __re, __m), __n_(0), __subs_(__submatches) { __init(__a, __b); } #endif // _LIBCPP_CXX03_LANG template template regex_token_iterator<_BidirectionalIterator, _CharT, _Traits>:: regex_token_iterator(_BidirectionalIterator __a, _BidirectionalIterator __b, const regex_type& __re, const int (&__submatches)[_Np], regex_constants::match_flag_type __m) : __position_(__a, __b, __re, __m), __n_(0), __subs_(__submatches, __submatches + _Np) { __init(__a, __b); } template regex_token_iterator<_BidirectionalIterator, _CharT, _Traits>:: regex_token_iterator(const regex_token_iterator& __x) : __position_(__x.__position_), __result_(__x.__result_), __suffix_(__x.__suffix_), __n_(__x.__n_), __subs_(__x.__subs_) { if (__x.__result_ == &__x.__suffix_) __result_ = &__suffix_; else if ( __result_ != nullptr ) __establish_result (); } template regex_token_iterator<_BidirectionalIterator, _CharT, _Traits>& regex_token_iterator<_BidirectionalIterator, _CharT, _Traits>:: operator=(const regex_token_iterator& __x) { if (this != &__x) { __position_ = __x.__position_; if (__x.__result_ == &__x.__suffix_) __result_ = &__suffix_; else __result_ = __x.__result_; __suffix_ = __x.__suffix_; __n_ = __x.__n_; __subs_ = __x.__subs_; if ( __result_ != nullptr && __result_ != &__suffix_ ) __establish_result(); } return *this; } template bool regex_token_iterator<_BidirectionalIterator, _CharT, _Traits>:: operator==(const regex_token_iterator& __x) const { if (__result_ == nullptr && __x.__result_ == nullptr) return true; if (__result_ == &__suffix_ && __x.__result_ == &__x.__suffix_ && __suffix_ == __x.__suffix_) return true; if (__result_ == nullptr || __x.__result_ == nullptr) return false; if (__result_ == &__suffix_ || __x.__result_ == &__x.__suffix_) return false; return __position_ == __x.__position_ && __n_ == __x.__n_ && __subs_ == __x.__subs_; } template regex_token_iterator<_BidirectionalIterator, _CharT, _Traits>& regex_token_iterator<_BidirectionalIterator, _CharT, _Traits>::operator++() { _Position __prev = __position_; if (__result_ == &__suffix_) __result_ = nullptr; else if (static_cast(__n_ + 1) < __subs_.size()) { ++__n_; __establish_result(); } else { __n_ = 0; ++__position_; if (__position_ != _Position()) __establish_result(); else { if (_VSTD::find(__subs_.begin(), __subs_.end(), -1) != __subs_.end() && __prev->suffix().length() != 0) { __suffix_.matched = true; __suffix_.first = __prev->suffix().first; __suffix_.second = __prev->suffix().second; __result_ = &__suffix_; } else __result_ = nullptr; } } return *this; } typedef regex_token_iterator cregex_token_iterator; typedef regex_token_iterator wcregex_token_iterator; typedef regex_token_iterator sregex_token_iterator; typedef regex_token_iterator wsregex_token_iterator; // regex_replace template _OutputIterator regex_replace(_OutputIterator __output, _BidirectionalIterator __first, _BidirectionalIterator __last, const basic_regex<_CharT, _Traits>& __e, const _CharT* __fmt, regex_constants::match_flag_type __flags = regex_constants::match_default) { typedef regex_iterator<_BidirectionalIterator, _CharT, _Traits> _Iter; _Iter __i(__first, __last, __e, __flags); _Iter __eof; if (__i == __eof) { if (!(__flags & regex_constants::format_no_copy)) __output = _VSTD::copy(__first, __last, __output); } else { sub_match<_BidirectionalIterator> __lm; for (size_t __len = char_traits<_CharT>::length(__fmt); __i != __eof; ++__i) { if (!(__flags & regex_constants::format_no_copy)) __output = _VSTD::copy(__i->prefix().first, __i->prefix().second, __output); __output = __i->format(__output, __fmt, __fmt + __len, __flags); __lm = __i->suffix(); if (__flags & regex_constants::format_first_only) break; } if (!(__flags & regex_constants::format_no_copy)) __output = _VSTD::copy(__lm.first, __lm.second, __output); } return __output; } template inline _LIBCPP_INLINE_VISIBILITY _OutputIterator regex_replace(_OutputIterator __output, _BidirectionalIterator __first, _BidirectionalIterator __last, const basic_regex<_CharT, _Traits>& __e, const basic_string<_CharT, _ST, _SA>& __fmt, regex_constants::match_flag_type __flags = regex_constants::match_default) { return _VSTD::regex_replace(__output, __first, __last, __e, __fmt.c_str(), __flags); } template inline _LIBCPP_INLINE_VISIBILITY basic_string<_CharT, _ST, _SA> regex_replace(const basic_string<_CharT, _ST, _SA>& __s, const basic_regex<_CharT, _Traits>& __e, const basic_string<_CharT, _FST, _FSA>& __fmt, regex_constants::match_flag_type __flags = regex_constants::match_default) { basic_string<_CharT, _ST, _SA> __r; _VSTD::regex_replace(back_inserter(__r), __s.begin(), __s.end(), __e, __fmt.c_str(), __flags); return __r; } template inline _LIBCPP_INLINE_VISIBILITY basic_string<_CharT, _ST, _SA> regex_replace(const basic_string<_CharT, _ST, _SA>& __s, const basic_regex<_CharT, _Traits>& __e, const _CharT* __fmt, regex_constants::match_flag_type __flags = regex_constants::match_default) { basic_string<_CharT, _ST, _SA> __r; _VSTD::regex_replace(back_inserter(__r), __s.begin(), __s.end(), __e, __fmt, __flags); return __r; } template inline _LIBCPP_INLINE_VISIBILITY basic_string<_CharT> regex_replace(const _CharT* __s, const basic_regex<_CharT, _Traits>& __e, const basic_string<_CharT, _ST, _SA>& __fmt, regex_constants::match_flag_type __flags = regex_constants::match_default) { basic_string<_CharT> __r; _VSTD::regex_replace(back_inserter(__r), __s, __s + char_traits<_CharT>::length(__s), __e, __fmt.c_str(), __flags); return __r; } template inline _LIBCPP_INLINE_VISIBILITY basic_string<_CharT> regex_replace(const _CharT* __s, const basic_regex<_CharT, _Traits>& __e, const _CharT* __fmt, regex_constants::match_flag_type __flags = regex_constants::match_default) { basic_string<_CharT> __r; _VSTD::regex_replace(back_inserter(__r), __s, __s + char_traits<_CharT>::length(__s), __e, __fmt, __flags); return __r; } _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS #endif // _LIBCPP_REGEX diff --git a/include/string b/include/string index d1a3a1f8e6cc..010a4c7816ea 100644 --- a/include/string +++ b/include/string @@ -1,4048 +1,4048 @@ // -*- C++ -*- //===--------------------------- string -----------------------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef _LIBCPP_STRING #define _LIBCPP_STRING /* string synopsis namespace std { template class fpos { private: stateT st; public: fpos(streamoff = streamoff()); operator streamoff() const; stateT state() const; void state(stateT); fpos& operator+=(streamoff); fpos operator+ (streamoff) const; fpos& operator-=(streamoff); fpos operator- (streamoff) const; }; template streamoff operator-(const fpos& x, const fpos& y); template bool operator==(const fpos& x, const fpos& y); template bool operator!=(const fpos& x, const fpos& y); template struct char_traits { typedef charT char_type; typedef ... int_type; typedef streamoff off_type; typedef streampos pos_type; typedef mbstate_t state_type; static void assign(char_type& c1, const char_type& c2) noexcept; static constexpr bool eq(char_type c1, char_type c2) noexcept; static constexpr bool lt(char_type c1, char_type c2) noexcept; static int compare(const char_type* s1, const char_type* s2, size_t n); static size_t length(const char_type* s); static const char_type* find(const char_type* s, size_t n, const char_type& a); static char_type* move(char_type* s1, const char_type* s2, size_t n); static char_type* copy(char_type* s1, const char_type* s2, size_t n); static char_type* assign(char_type* s, size_t n, char_type a); static constexpr int_type not_eof(int_type c) noexcept; static constexpr char_type to_char_type(int_type c) noexcept; static constexpr int_type to_int_type(char_type c) noexcept; static constexpr bool eq_int_type(int_type c1, int_type c2) noexcept; static constexpr int_type eof() noexcept; }; template <> struct char_traits; template <> struct char_traits; template, class Allocator = allocator > class basic_string { public: // types: typedef traits traits_type; typedef typename traits_type::char_type value_type; typedef Allocator allocator_type; typedef typename allocator_type::size_type size_type; typedef typename allocator_type::difference_type difference_type; typedef typename allocator_type::reference reference; typedef typename allocator_type::const_reference const_reference; typedef typename allocator_type::pointer pointer; typedef typename allocator_type::const_pointer const_pointer; typedef implementation-defined iterator; typedef implementation-defined const_iterator; typedef std::reverse_iterator reverse_iterator; typedef std::reverse_iterator const_reverse_iterator; static const size_type npos = -1; basic_string() noexcept(is_nothrow_default_constructible::value); explicit basic_string(const allocator_type& a); basic_string(const basic_string& str); basic_string(basic_string&& str) noexcept(is_nothrow_move_constructible::value); basic_string(const basic_string& str, size_type pos, const allocator_type& a = allocator_type()); basic_string(const basic_string& str, size_type pos, size_type n, const Allocator& a = Allocator()); template basic_string(const T& t, size_type pos, size_type n, const Allocator& a = Allocator()); // C++17 explicit basic_string(const basic_string_view sv, const Allocator& a = Allocator()); basic_string(const value_type* s, const allocator_type& a = allocator_type()); basic_string(const value_type* s, size_type n, const allocator_type& a = allocator_type()); basic_string(size_type n, value_type c, const allocator_type& a = allocator_type()); template basic_string(InputIterator begin, InputIterator end, const allocator_type& a = allocator_type()); basic_string(initializer_list, const Allocator& = Allocator()); basic_string(const basic_string&, const Allocator&); basic_string(basic_string&&, const Allocator&); ~basic_string(); operator basic_string_view() const noexcept; basic_string& operator=(const basic_string& str); basic_string& operator=(basic_string_view sv); basic_string& operator=(basic_string&& str) noexcept( allocator_type::propagate_on_container_move_assignment::value || allocator_type::is_always_equal::value ); // C++17 basic_string& operator=(const value_type* s); basic_string& operator=(value_type c); basic_string& operator=(initializer_list); iterator begin() noexcept; const_iterator begin() const noexcept; iterator end() noexcept; const_iterator end() const noexcept; reverse_iterator rbegin() noexcept; const_reverse_iterator rbegin() const noexcept; reverse_iterator rend() noexcept; const_reverse_iterator rend() const noexcept; const_iterator cbegin() const noexcept; const_iterator cend() const noexcept; const_reverse_iterator crbegin() const noexcept; const_reverse_iterator crend() const noexcept; size_type size() const noexcept; size_type length() const noexcept; size_type max_size() const noexcept; size_type capacity() const noexcept; void resize(size_type n, value_type c); void resize(size_type n); void reserve(size_type res_arg = 0); void shrink_to_fit(); void clear() noexcept; bool empty() const noexcept; const_reference operator[](size_type pos) const; reference operator[](size_type pos); const_reference at(size_type n) const; reference at(size_type n); basic_string& operator+=(const basic_string& str); basic_string& operator+=(basic_string_view sv); basic_string& operator+=(const value_type* s); basic_string& operator+=(value_type c); basic_string& operator+=(initializer_list); basic_string& append(const basic_string& str); basic_string& append(basic_string_view sv); basic_string& append(const basic_string& str, size_type pos, size_type n=npos); //C++14 template basic_string& append(const T& t, size_type pos, size_type n=npos); // C++17 basic_string& append(const value_type* s, size_type n); basic_string& append(const value_type* s); basic_string& append(size_type n, value_type c); template basic_string& append(InputIterator first, InputIterator last); basic_string& append(initializer_list); void push_back(value_type c); void pop_back(); reference front(); const_reference front() const; reference back(); const_reference back() const; basic_string& assign(const basic_string& str); basic_string& assign(basic_string_view sv); basic_string& assign(basic_string&& str); basic_string& assign(const basic_string& str, size_type pos, size_type n=npos); // C++14 template basic_string& assign(const T& t, size_type pos, size_type n=npos); // C++17 basic_string& assign(const value_type* s, size_type n); basic_string& assign(const value_type* s); basic_string& assign(size_type n, value_type c); template basic_string& assign(InputIterator first, InputIterator last); basic_string& assign(initializer_list); basic_string& insert(size_type pos1, const basic_string& str); basic_string& insert(size_type pos1, basic_string_view sv); basic_string& insert(size_type pos1, const basic_string& str, size_type pos2, size_type n); template basic_string& insert(size_type pos1, const T& t, size_type pos2, size_type n); // C++17 basic_string& insert(size_type pos, const value_type* s, size_type n=npos); //C++14 basic_string& insert(size_type pos, const value_type* s); basic_string& insert(size_type pos, size_type n, value_type c); iterator insert(const_iterator p, value_type c); iterator insert(const_iterator p, size_type n, value_type c); template iterator insert(const_iterator p, InputIterator first, InputIterator last); iterator insert(const_iterator p, initializer_list); basic_string& erase(size_type pos = 0, size_type n = npos); iterator erase(const_iterator position); iterator erase(const_iterator first, const_iterator last); basic_string& replace(size_type pos1, size_type n1, const basic_string& str); basic_string& replace(size_type pos1, size_type n1, basic_string_view sv); basic_string& replace(size_type pos1, size_type n1, const basic_string& str, size_type pos2, size_type n2=npos); // C++14 template basic_string& replace(size_type pos1, size_type n1, const T& t, size_type pos2, size_type n); // C++17 basic_string& replace(size_type pos, size_type n1, const value_type* s, size_type n2); basic_string& replace(size_type pos, size_type n1, const value_type* s); basic_string& replace(size_type pos, size_type n1, size_type n2, value_type c); basic_string& replace(const_iterator i1, const_iterator i2, const basic_string& str); basic_string& replace(const_iterator i1, const_iterator i2, basic_string_view sv); basic_string& replace(const_iterator i1, const_iterator i2, const value_type* s, size_type n); basic_string& replace(const_iterator i1, const_iterator i2, const value_type* s); basic_string& replace(const_iterator i1, const_iterator i2, size_type n, value_type c); template basic_string& replace(const_iterator i1, const_iterator i2, InputIterator j1, InputIterator j2); basic_string& replace(const_iterator i1, const_iterator i2, initializer_list); size_type copy(value_type* s, size_type n, size_type pos = 0) const; basic_string substr(size_type pos = 0, size_type n = npos) const; void swap(basic_string& str) noexcept(allocator_traits::propagate_on_container_swap::value || allocator_traits::is_always_equal::value); // C++17 const value_type* c_str() const noexcept; const value_type* data() const noexcept; value_type* data() noexcept; // C++17 allocator_type get_allocator() const noexcept; size_type find(const basic_string& str, size_type pos = 0) const noexcept; size_type find(basic_string_view sv, size_type pos = 0) const noexcept; size_type find(const value_type* s, size_type pos, size_type n) const noexcept; size_type find(const value_type* s, size_type pos = 0) const noexcept; size_type find(value_type c, size_type pos = 0) const noexcept; size_type rfind(const basic_string& str, size_type pos = npos) const noexcept; size_type ffind(basic_string_view sv, size_type pos = 0) const noexcept; size_type rfind(const value_type* s, size_type pos, size_type n) const noexcept; size_type rfind(const value_type* s, size_type pos = npos) const noexcept; size_type rfind(value_type c, size_type pos = npos) const noexcept; size_type find_first_of(const basic_string& str, size_type pos = 0) const noexcept; size_type find_first_of(basic_string_view sv, size_type pos = 0) const noexcept; size_type find_first_of(const value_type* s, size_type pos, size_type n) const noexcept; size_type find_first_of(const value_type* s, size_type pos = 0) const noexcept; size_type find_first_of(value_type c, size_type pos = 0) const noexcept; size_type find_last_of(const basic_string& str, size_type pos = npos) const noexcept; size_type find_last_of(basic_string_view sv, size_type pos = 0) const noexcept; size_type find_last_of(const value_type* s, size_type pos, size_type n) const noexcept; size_type find_last_of(const value_type* s, size_type pos = npos) const noexcept; size_type find_last_of(value_type c, size_type pos = npos) const noexcept; size_type find_first_not_of(const basic_string& str, size_type pos = 0) const noexcept; size_type find_first_not_of(basic_string_view sv, size_type pos = 0) const noexcept; size_type find_first_not_of(const value_type* s, size_type pos, size_type n) const noexcept; size_type find_first_not_of(const value_type* s, size_type pos = 0) const noexcept; size_type find_first_not_of(value_type c, size_type pos = 0) const noexcept; size_type find_last_not_of(const basic_string& str, size_type pos = npos) const noexcept; size_type find_last_not_of(basic_string_view sv, size_type pos = 0) const noexcept; size_type find_last_not_of(const value_type* s, size_type pos, size_type n) const noexcept; size_type find_last_not_of(const value_type* s, size_type pos = npos) const noexcept; size_type find_last_not_of(value_type c, size_type pos = npos) const noexcept; int compare(const basic_string& str) const noexcept; int compare(basic_string_view sv) const noexcept; int compare(size_type pos1, size_type n1, const basic_string& str) const; int compare(size_type pos1, size_type n1, basic_string_view sv) const; int compare(size_type pos1, size_type n1, const basic_string& str, size_type pos2, size_type n2=npos) const; // C++14 template int compare(size_type pos1, size_type n1, const T& t, size_type pos2, size_type n2=npos) const; // C++17 int compare(const value_type* s) const noexcept; int compare(size_type pos1, size_type n1, const value_type* s) const; int compare(size_type pos1, size_type n1, const value_type* s, size_type n2) const; bool __invariants() const; }; template basic_string operator+(const basic_string& lhs, const basic_string& rhs); template basic_string operator+(const charT* lhs , const basic_string&rhs); template basic_string operator+(charT lhs, const basic_string& rhs); template basic_string operator+(const basic_string& lhs, const charT* rhs); template basic_string operator+(const basic_string& lhs, charT rhs); template bool operator==(const basic_string& lhs, const basic_string& rhs) noexcept; template bool operator==(const charT* lhs, const basic_string& rhs) noexcept; template bool operator==(const basic_string& lhs, const charT* rhs) noexcept; template bool operator!=(const basic_string& lhs, const basic_string& rhs) noexcept; template bool operator!=(const charT* lhs, const basic_string& rhs) noexcept; template bool operator!=(const basic_string& lhs, const charT* rhs) noexcept; template bool operator< (const basic_string& lhs, const basic_string& rhs) noexcept; template bool operator< (const basic_string& lhs, const charT* rhs) noexcept; template bool operator< (const charT* lhs, const basic_string& rhs) noexcept; template bool operator> (const basic_string& lhs, const basic_string& rhs) noexcept; template bool operator> (const basic_string& lhs, const charT* rhs) noexcept; template bool operator> (const charT* lhs, const basic_string& rhs) noexcept; template bool operator<=(const basic_string& lhs, const basic_string& rhs) noexcept; template bool operator<=(const basic_string& lhs, const charT* rhs) noexcept; template bool operator<=(const charT* lhs, const basic_string& rhs) noexcept; template bool operator>=(const basic_string& lhs, const basic_string& rhs) noexcept; template bool operator>=(const basic_string& lhs, const charT* rhs) noexcept; template bool operator>=(const charT* lhs, const basic_string& rhs) noexcept; template void swap(basic_string& lhs, basic_string& rhs) noexcept(noexcept(lhs.swap(rhs))); template basic_istream& operator>>(basic_istream& is, basic_string& str); template basic_ostream& operator<<(basic_ostream& os, const basic_string& str); template basic_istream& getline(basic_istream& is, basic_string& str, charT delim); template basic_istream& getline(basic_istream& is, basic_string& str); typedef basic_string string; typedef basic_string wstring; typedef basic_string u16string; typedef basic_string u32string; int stoi (const string& str, size_t* idx = 0, int base = 10); long stol (const string& str, size_t* idx = 0, int base = 10); unsigned long stoul (const string& str, size_t* idx = 0, int base = 10); long long stoll (const string& str, size_t* idx = 0, int base = 10); unsigned long long stoull(const string& str, size_t* idx = 0, int base = 10); float stof (const string& str, size_t* idx = 0); double stod (const string& str, size_t* idx = 0); long double stold(const string& str, size_t* idx = 0); string to_string(int val); string to_string(unsigned val); string to_string(long val); string to_string(unsigned long val); string to_string(long long val); string to_string(unsigned long long val); string to_string(float val); string to_string(double val); string to_string(long double val); int stoi (const wstring& str, size_t* idx = 0, int base = 10); long stol (const wstring& str, size_t* idx = 0, int base = 10); unsigned long stoul (const wstring& str, size_t* idx = 0, int base = 10); long long stoll (const wstring& str, size_t* idx = 0, int base = 10); unsigned long long stoull(const wstring& str, size_t* idx = 0, int base = 10); float stof (const wstring& str, size_t* idx = 0); double stod (const wstring& str, size_t* idx = 0); long double stold(const wstring& str, size_t* idx = 0); wstring to_wstring(int val); wstring to_wstring(unsigned val); wstring to_wstring(long val); wstring to_wstring(unsigned long val); wstring to_wstring(long long val); wstring to_wstring(unsigned long long val); wstring to_wstring(float val); wstring to_wstring(double val); wstring to_wstring(long double val); template <> struct hash; template <> struct hash; template <> struct hash; template <> struct hash; basic_string operator "" s( const char *str, size_t len ); // C++14 basic_string operator "" s( const wchar_t *str, size_t len ); // C++14 basic_string operator "" s( const char16_t *str, size_t len ); // C++14 basic_string operator "" s( const char32_t *str, size_t len ); // C++14 } // std */ #include <__config> #include #include #include #include // For EOF. #include #include #include #include #include #include #include #include #include <__functional_base> #ifndef _LIBCPP_HAS_NO_UNICODE_CHARS #include #endif #include <__debug> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header #endif _LIBCPP_PUSH_MACROS #include <__undef_macros> _LIBCPP_BEGIN_NAMESPACE_STD // fpos template class _LIBCPP_TEMPLATE_VIS fpos { private: _StateT __st_; streamoff __off_; public: _LIBCPP_INLINE_VISIBILITY fpos(streamoff __off = streamoff()) : __st_(), __off_(__off) {} _LIBCPP_INLINE_VISIBILITY operator streamoff() const {return __off_;} _LIBCPP_INLINE_VISIBILITY _StateT state() const {return __st_;} _LIBCPP_INLINE_VISIBILITY void state(_StateT __st) {__st_ = __st;} _LIBCPP_INLINE_VISIBILITY fpos& operator+=(streamoff __off) {__off_ += __off; return *this;} _LIBCPP_INLINE_VISIBILITY fpos operator+ (streamoff __off) const {fpos __t(*this); __t += __off; return __t;} _LIBCPP_INLINE_VISIBILITY fpos& operator-=(streamoff __off) {__off_ -= __off; return *this;} _LIBCPP_INLINE_VISIBILITY fpos operator- (streamoff __off) const {fpos __t(*this); __t -= __off; return __t;} }; template inline _LIBCPP_INLINE_VISIBILITY streamoff operator-(const fpos<_StateT>& __x, const fpos<_StateT>& __y) {return streamoff(__x) - streamoff(__y);} template inline _LIBCPP_INLINE_VISIBILITY bool operator==(const fpos<_StateT>& __x, const fpos<_StateT>& __y) {return streamoff(__x) == streamoff(__y);} template inline _LIBCPP_INLINE_VISIBILITY bool operator!=(const fpos<_StateT>& __x, const fpos<_StateT>& __y) {return streamoff(__x) != streamoff(__y);} // basic_string template basic_string<_CharT, _Traits, _Allocator> operator+(const basic_string<_CharT, _Traits, _Allocator>& __x, const basic_string<_CharT, _Traits, _Allocator>& __y); template basic_string<_CharT, _Traits, _Allocator> operator+(const _CharT* __x, const basic_string<_CharT,_Traits,_Allocator>& __y); template basic_string<_CharT, _Traits, _Allocator> operator+(_CharT __x, const basic_string<_CharT,_Traits,_Allocator>& __y); template basic_string<_CharT, _Traits, _Allocator> operator+(const basic_string<_CharT, _Traits, _Allocator>& __x, const _CharT* __y); template basic_string<_CharT, _Traits, _Allocator> operator+(const basic_string<_CharT, _Traits, _Allocator>& __x, _CharT __y); template class _LIBCPP_TEMPLATE_VIS __basic_string_common { protected: _LIBCPP_NORETURN void __throw_length_error() const; _LIBCPP_NORETURN void __throw_out_of_range() const; }; template void __basic_string_common<__b>::__throw_length_error() const { _VSTD::__throw_length_error("basic_string"); } template void __basic_string_common<__b>::__throw_out_of_range() const { _VSTD::__throw_out_of_range("basic_string"); } #ifdef _LIBCPP_MSVC #pragma warning( push ) #pragma warning( disable: 4231 ) #endif // _LIBCPP_MSVC _LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __basic_string_common) #ifdef _LIBCPP_MSVC #pragma warning( pop ) #endif // _LIBCPP_MSVC #ifdef _LIBCPP_NO_EXCEPTIONS template struct __libcpp_string_gets_noexcept_iterator_impl : public true_type {}; #elif defined(_LIBCPP_HAS_NO_NOEXCEPT) template struct __libcpp_string_gets_noexcept_iterator_impl : public false_type {}; #else template ::value> struct __libcpp_string_gets_noexcept_iterator_impl : public _LIBCPP_BOOL_CONSTANT(( noexcept(++(declval<_Iter&>())) && is_nothrow_assignable<_Iter&, _Iter>::value && noexcept(declval<_Iter>() == declval<_Iter>()) && noexcept(*declval<_Iter>()) )) {}; template struct __libcpp_string_gets_noexcept_iterator_impl<_Iter, false> : public false_type {}; #endif template struct __libcpp_string_gets_noexcept_iterator : public _LIBCPP_BOOL_CONSTANT(__libcpp_is_trivial_iterator<_Iter>::value || __libcpp_string_gets_noexcept_iterator_impl<_Iter>::value) {}; template struct __can_be_converted_to_string_view : public _LIBCPP_BOOL_CONSTANT( ( is_convertible >::value && !is_convertible::value)) {}; #ifdef _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT template struct __padding { unsigned char __xx[sizeof(_CharT)-1]; }; template struct __padding<_CharT, 1> { }; #endif // _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT template class _LIBCPP_TEMPLATE_VIS basic_string : private __basic_string_common { public: typedef basic_string __self; typedef basic_string_view<_CharT, _Traits> __self_view; typedef _Traits traits_type; typedef _CharT value_type; typedef _Allocator allocator_type; typedef allocator_traits __alloc_traits; typedef typename __alloc_traits::size_type size_type; typedef typename __alloc_traits::difference_type difference_type; typedef value_type& reference; typedef const value_type& const_reference; typedef typename __alloc_traits::pointer pointer; typedef typename __alloc_traits::const_pointer const_pointer; static_assert(is_pod::value, "Character type of basic_string must be a POD"); static_assert((is_same<_CharT, typename traits_type::char_type>::value), "traits_type::char_type must be the same type as CharT"); static_assert((is_same::value), "Allocator::value_type must be same type as value_type"); #if defined(_LIBCPP_RAW_ITERATORS) typedef pointer iterator; typedef const_pointer const_iterator; #else // defined(_LIBCPP_RAW_ITERATORS) typedef __wrap_iter iterator; typedef __wrap_iter const_iterator; #endif // defined(_LIBCPP_RAW_ITERATORS) typedef _VSTD::reverse_iterator reverse_iterator; typedef _VSTD::reverse_iterator const_reverse_iterator; private: #ifdef _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT struct __long { pointer __data_; size_type __size_; size_type __cap_; }; #if _LIBCPP_BIG_ENDIAN - enum {__short_mask = 0x01}; - enum {__long_mask = 0x1ul}; + static const size_type __short_mask = 0x01; + static const size_type __long_mask = 0x1ul; #else // _LIBCPP_BIG_ENDIAN - enum {__short_mask = 0x80}; - enum {__long_mask = ~(size_type(~0) >> 1)}; + static const size_type __short_mask = 0x80; + static const size_type __long_mask = ~(size_type(~0) >> 1); #endif // _LIBCPP_BIG_ENDIAN enum {__min_cap = (sizeof(__long) - 1)/sizeof(value_type) > 2 ? (sizeof(__long) - 1)/sizeof(value_type) : 2}; struct __short { value_type __data_[__min_cap]; struct : __padding { unsigned char __size_; }; }; #else struct __long { size_type __cap_; size_type __size_; pointer __data_; }; #if _LIBCPP_BIG_ENDIAN - enum {__short_mask = 0x80}; - enum {__long_mask = ~(size_type(~0) >> 1)}; + static const size_type __short_mask = 0x80; + static const size_type __long_mask = ~(size_type(~0) >> 1); #else // _LIBCPP_BIG_ENDIAN - enum {__short_mask = 0x01}; - enum {__long_mask = 0x1ul}; + static const size_type __short_mask = 0x01; + static const size_type __long_mask = 0x1ul; #endif // _LIBCPP_BIG_ENDIAN enum {__min_cap = (sizeof(__long) - 1)/sizeof(value_type) > 2 ? (sizeof(__long) - 1)/sizeof(value_type) : 2}; struct __short { union { unsigned char __size_; value_type __lx; }; value_type __data_[__min_cap]; }; #endif // _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT union __ulx{__long __lx; __short __lxx;}; enum {__n_words = sizeof(__ulx) / sizeof(size_type)}; struct __raw { size_type __words[__n_words]; }; struct __rep { union { __long __l; __short __s; __raw __r; }; }; __compressed_pair<__rep, allocator_type> __r_; public: static const size_type npos = -1; _LIBCPP_INLINE_VISIBILITY basic_string() _NOEXCEPT_(is_nothrow_default_constructible::value); _LIBCPP_INLINE_VISIBILITY explicit basic_string(const allocator_type& __a) #if _LIBCPP_STD_VER <= 14 _NOEXCEPT_(is_nothrow_copy_constructible::value); #else _NOEXCEPT; #endif basic_string(const basic_string& __str); basic_string(const basic_string& __str, const allocator_type& __a); #ifndef _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY basic_string(basic_string&& __str) #if _LIBCPP_STD_VER <= 14 _NOEXCEPT_(is_nothrow_move_constructible::value); #else _NOEXCEPT; #endif _LIBCPP_INLINE_VISIBILITY basic_string(basic_string&& __str, const allocator_type& __a); #endif // _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY basic_string(const _CharT* __s); _LIBCPP_INLINE_VISIBILITY basic_string(const _CharT* __s, const _Allocator& __a); _LIBCPP_INLINE_VISIBILITY basic_string(const _CharT* __s, size_type __n); _LIBCPP_INLINE_VISIBILITY basic_string(const _CharT* __s, size_type __n, const _Allocator& __a); _LIBCPP_INLINE_VISIBILITY basic_string(size_type __n, _CharT __c); _LIBCPP_INLINE_VISIBILITY basic_string(size_type __n, _CharT __c, const _Allocator& __a); basic_string(const basic_string& __str, size_type __pos, size_type __n, const _Allocator& __a = _Allocator()); _LIBCPP_INLINE_VISIBILITY basic_string(const basic_string& __str, size_type __pos, const _Allocator& __a = _Allocator()); template _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS basic_string(const _Tp& __t, size_type __pos, size_type __n, const allocator_type& __a = allocator_type(), typename enable_if<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, void>::type* = 0); _LIBCPP_INLINE_VISIBILITY explicit basic_string(__self_view __sv); _LIBCPP_INLINE_VISIBILITY basic_string(__self_view __sv, const _Allocator& __a); template _LIBCPP_INLINE_VISIBILITY basic_string(_InputIterator __first, _InputIterator __last); template _LIBCPP_INLINE_VISIBILITY basic_string(_InputIterator __first, _InputIterator __last, const allocator_type& __a); #ifndef _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY basic_string(initializer_list<_CharT> __il); _LIBCPP_INLINE_VISIBILITY basic_string(initializer_list<_CharT> __il, const _Allocator& __a); #endif // _LIBCPP_CXX03_LANG inline ~basic_string(); _LIBCPP_INLINE_VISIBILITY operator __self_view() const _NOEXCEPT { return __self_view(data(), size()); } basic_string& operator=(const basic_string& __str); #ifndef _LIBCPP_CXX03_LANG template #endif _LIBCPP_INLINE_VISIBILITY basic_string& operator=(__self_view __sv) {return assign(__sv);} #ifndef _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY basic_string& operator=(basic_string&& __str) _NOEXCEPT_((__noexcept_move_assign_container<_Allocator, __alloc_traits>::value)); _LIBCPP_INLINE_VISIBILITY basic_string& operator=(initializer_list __il) {return assign(__il.begin(), __il.size());} #endif _LIBCPP_INLINE_VISIBILITY basic_string& operator=(const value_type* __s) {return assign(__s);} basic_string& operator=(value_type __c); #if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_INLINE_VISIBILITY iterator begin() _NOEXCEPT {return iterator(this, __get_pointer());} _LIBCPP_INLINE_VISIBILITY const_iterator begin() const _NOEXCEPT {return const_iterator(this, __get_pointer());} _LIBCPP_INLINE_VISIBILITY iterator end() _NOEXCEPT {return iterator(this, __get_pointer() + size());} _LIBCPP_INLINE_VISIBILITY const_iterator end() const _NOEXCEPT {return const_iterator(this, __get_pointer() + size());} #else _LIBCPP_INLINE_VISIBILITY iterator begin() _NOEXCEPT {return iterator(__get_pointer());} _LIBCPP_INLINE_VISIBILITY const_iterator begin() const _NOEXCEPT {return const_iterator(__get_pointer());} _LIBCPP_INLINE_VISIBILITY iterator end() _NOEXCEPT {return iterator(__get_pointer() + size());} _LIBCPP_INLINE_VISIBILITY const_iterator end() const _NOEXCEPT {return const_iterator(__get_pointer() + size());} #endif // _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_INLINE_VISIBILITY reverse_iterator rbegin() _NOEXCEPT {return reverse_iterator(end());} _LIBCPP_INLINE_VISIBILITY const_reverse_iterator rbegin() const _NOEXCEPT {return const_reverse_iterator(end());} _LIBCPP_INLINE_VISIBILITY reverse_iterator rend() _NOEXCEPT {return reverse_iterator(begin());} _LIBCPP_INLINE_VISIBILITY const_reverse_iterator rend() const _NOEXCEPT {return const_reverse_iterator(begin());} _LIBCPP_INLINE_VISIBILITY const_iterator cbegin() const _NOEXCEPT {return begin();} _LIBCPP_INLINE_VISIBILITY const_iterator cend() const _NOEXCEPT {return end();} _LIBCPP_INLINE_VISIBILITY const_reverse_iterator crbegin() const _NOEXCEPT {return rbegin();} _LIBCPP_INLINE_VISIBILITY const_reverse_iterator crend() const _NOEXCEPT {return rend();} _LIBCPP_INLINE_VISIBILITY size_type size() const _NOEXCEPT {return __is_long() ? __get_long_size() : __get_short_size();} _LIBCPP_INLINE_VISIBILITY size_type length() const _NOEXCEPT {return size();} _LIBCPP_INLINE_VISIBILITY size_type max_size() const _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY size_type capacity() const _NOEXCEPT {return (__is_long() ? __get_long_cap() : static_cast(__min_cap)) - 1;} void resize(size_type __n, value_type __c); _LIBCPP_INLINE_VISIBILITY void resize(size_type __n) {resize(__n, value_type());} void reserve(size_type __res_arg = 0); _LIBCPP_INLINE_VISIBILITY void shrink_to_fit() _NOEXCEPT {reserve();} _LIBCPP_INLINE_VISIBILITY void clear() _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY bool empty() const _NOEXCEPT {return size() == 0;} _LIBCPP_INLINE_VISIBILITY const_reference operator[](size_type __pos) const _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY reference operator[](size_type __pos) _NOEXCEPT; const_reference at(size_type __n) const; reference at(size_type __n); _LIBCPP_INLINE_VISIBILITY basic_string& operator+=(const basic_string& __str) {return append(__str);} _LIBCPP_INLINE_VISIBILITY basic_string& operator+=(__self_view __sv) {return append(__sv);} _LIBCPP_INLINE_VISIBILITY basic_string& operator+=(const value_type* __s) {return append(__s);} _LIBCPP_INLINE_VISIBILITY basic_string& operator+=(value_type __c) {push_back(__c); return *this;} #ifndef _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY basic_string& operator+=(initializer_list __il) {return append(__il);} #endif // _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY basic_string& append(const basic_string& __str); _LIBCPP_INLINE_VISIBILITY basic_string& append(__self_view __sv) { return append(__sv.data(), __sv.size()); } basic_string& append(const basic_string& __str, size_type __pos, size_type __n=npos); template _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS typename enable_if < __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, basic_string& >::type append(const _Tp& __t, size_type __pos, size_type __n=npos); basic_string& append(const value_type* __s, size_type __n); basic_string& append(const value_type* __s); basic_string& append(size_type __n, value_type __c); template _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS basic_string& __append_forward_unsafe(_ForwardIterator, _ForwardIterator); template _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS typename enable_if < __is_exactly_input_iterator<_InputIterator>::value || !__libcpp_string_gets_noexcept_iterator<_InputIterator>::value, basic_string& >::type _LIBCPP_INLINE_VISIBILITY append(_InputIterator __first, _InputIterator __last) { const basic_string __temp (__first, __last, __alloc()); append(__temp.data(), __temp.size()); return *this; } template _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS typename enable_if < __is_forward_iterator<_ForwardIterator>::value && __libcpp_string_gets_noexcept_iterator<_ForwardIterator>::value, basic_string& >::type _LIBCPP_INLINE_VISIBILITY append(_ForwardIterator __first, _ForwardIterator __last) { return __append_forward_unsafe(__first, __last); } #ifndef _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY basic_string& append(initializer_list __il) {return append(__il.begin(), __il.size());} #endif // _LIBCPP_CXX03_LANG void push_back(value_type __c); _LIBCPP_INLINE_VISIBILITY void pop_back(); _LIBCPP_INLINE_VISIBILITY reference front(); _LIBCPP_INLINE_VISIBILITY const_reference front() const; _LIBCPP_INLINE_VISIBILITY reference back(); _LIBCPP_INLINE_VISIBILITY const_reference back() const; _LIBCPP_INLINE_VISIBILITY basic_string& assign(__self_view __sv) { return assign(__sv.data(), __sv.size()); } _LIBCPP_INLINE_VISIBILITY basic_string& assign(const basic_string& __str) { return *this = __str; } #ifndef _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY basic_string& assign(basic_string&& __str) _NOEXCEPT_((__noexcept_move_assign_container<_Allocator, __alloc_traits>::value)) {*this = _VSTD::move(__str); return *this;} #endif basic_string& assign(const basic_string& __str, size_type __pos, size_type __n=npos); template _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS typename enable_if < __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, basic_string& >::type assign(const _Tp & __t, size_type __pos, size_type __n=npos); basic_string& assign(const value_type* __s, size_type __n); basic_string& assign(const value_type* __s); basic_string& assign(size_type __n, value_type __c); template _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS typename enable_if < __is_exactly_input_iterator<_InputIterator>::value || !__libcpp_string_gets_noexcept_iterator<_InputIterator>::value, basic_string& >::type assign(_InputIterator __first, _InputIterator __last); template _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS typename enable_if < __is_forward_iterator<_ForwardIterator>::value && __libcpp_string_gets_noexcept_iterator<_ForwardIterator>::value, basic_string& >::type assign(_ForwardIterator __first, _ForwardIterator __last); #ifndef _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY basic_string& assign(initializer_list __il) {return assign(__il.begin(), __il.size());} #endif // _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY basic_string& insert(size_type __pos1, const basic_string& __str); _LIBCPP_INLINE_VISIBILITY basic_string& insert(size_type __pos1, __self_view __sv) { return insert(__pos1, __sv.data(), __sv.size()); } template _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS typename enable_if < __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, basic_string& >::type insert(size_type __pos1, const _Tp& __t, size_type __pos2, size_type __n=npos); basic_string& insert(size_type __pos1, const basic_string& __str, size_type __pos2, size_type __n=npos); basic_string& insert(size_type __pos, const value_type* __s, size_type __n); basic_string& insert(size_type __pos, const value_type* __s); basic_string& insert(size_type __pos, size_type __n, value_type __c); iterator insert(const_iterator __pos, value_type __c); _LIBCPP_INLINE_VISIBILITY iterator insert(const_iterator __pos, size_type __n, value_type __c); template _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS typename enable_if < __is_exactly_input_iterator<_InputIterator>::value || !__libcpp_string_gets_noexcept_iterator<_InputIterator>::value, iterator >::type insert(const_iterator __pos, _InputIterator __first, _InputIterator __last); template _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS typename enable_if < __is_forward_iterator<_ForwardIterator>::value && __libcpp_string_gets_noexcept_iterator<_ForwardIterator>::value, iterator >::type insert(const_iterator __pos, _ForwardIterator __first, _ForwardIterator __last); #ifndef _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY iterator insert(const_iterator __pos, initializer_list __il) {return insert(__pos, __il.begin(), __il.end());} #endif // _LIBCPP_CXX03_LANG basic_string& erase(size_type __pos = 0, size_type __n = npos); _LIBCPP_INLINE_VISIBILITY iterator erase(const_iterator __pos); _LIBCPP_INLINE_VISIBILITY iterator erase(const_iterator __first, const_iterator __last); _LIBCPP_INLINE_VISIBILITY basic_string& replace(size_type __pos1, size_type __n1, const basic_string& __str); _LIBCPP_INLINE_VISIBILITY basic_string& replace(size_type __pos1, size_type __n1, __self_view __sv) { return replace(__pos1, __n1, __sv.data(), __sv.size()); } basic_string& replace(size_type __pos1, size_type __n1, const basic_string& __str, size_type __pos2, size_type __n2=npos); template _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS typename enable_if < __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, basic_string& >::type replace(size_type __pos1, size_type __n1, const _Tp& __t, size_type __pos2, size_type __n2=npos); basic_string& replace(size_type __pos, size_type __n1, const value_type* __s, size_type __n2); basic_string& replace(size_type __pos, size_type __n1, const value_type* __s); basic_string& replace(size_type __pos, size_type __n1, size_type __n2, value_type __c); _LIBCPP_INLINE_VISIBILITY basic_string& replace(const_iterator __i1, const_iterator __i2, const basic_string& __str); _LIBCPP_INLINE_VISIBILITY basic_string& replace(const_iterator __i1, const_iterator __i2, __self_view __sv) { return replace(__i1 - begin(), __i2 - __i1, __sv); } _LIBCPP_INLINE_VISIBILITY basic_string& replace(const_iterator __i1, const_iterator __i2, const value_type* __s, size_type __n); _LIBCPP_INLINE_VISIBILITY basic_string& replace(const_iterator __i1, const_iterator __i2, const value_type* __s); _LIBCPP_INLINE_VISIBILITY basic_string& replace(const_iterator __i1, const_iterator __i2, size_type __n, value_type __c); template _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS typename enable_if < __is_input_iterator<_InputIterator>::value, basic_string& >::type replace(const_iterator __i1, const_iterator __i2, _InputIterator __j1, _InputIterator __j2); #ifndef _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY basic_string& replace(const_iterator __i1, const_iterator __i2, initializer_list __il) {return replace(__i1, __i2, __il.begin(), __il.end());} #endif // _LIBCPP_CXX03_LANG size_type copy(value_type* __s, size_type __n, size_type __pos = 0) const; _LIBCPP_INLINE_VISIBILITY basic_string substr(size_type __pos = 0, size_type __n = npos) const; _LIBCPP_INLINE_VISIBILITY void swap(basic_string& __str) #if _LIBCPP_STD_VER >= 14 _NOEXCEPT_DEBUG; #else _NOEXCEPT_DEBUG_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable::value); #endif _LIBCPP_INLINE_VISIBILITY const value_type* c_str() const _NOEXCEPT {return data();} _LIBCPP_INLINE_VISIBILITY const value_type* data() const _NOEXCEPT {return _VSTD::__to_raw_pointer(__get_pointer());} #if _LIBCPP_STD_VER > 14 _LIBCPP_INLINE_VISIBILITY value_type* data() _NOEXCEPT {return _VSTD::__to_raw_pointer(__get_pointer());} #endif _LIBCPP_INLINE_VISIBILITY allocator_type get_allocator() const _NOEXCEPT {return __alloc();} _LIBCPP_INLINE_VISIBILITY size_type find(const basic_string& __str, size_type __pos = 0) const _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY size_type find(__self_view __sv, size_type __pos = 0) const _NOEXCEPT; size_type find(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY size_type find(const value_type* __s, size_type __pos = 0) const _NOEXCEPT; size_type find(value_type __c, size_type __pos = 0) const _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY size_type rfind(const basic_string& __str, size_type __pos = npos) const _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY size_type rfind(__self_view __sv, size_type __pos = 0) const _NOEXCEPT; size_type rfind(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY size_type rfind(const value_type* __s, size_type __pos = npos) const _NOEXCEPT; size_type rfind(value_type __c, size_type __pos = npos) const _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY size_type find_first_of(const basic_string& __str, size_type __pos = 0) const _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY size_type find_first_of(__self_view __sv, size_type __pos = 0) const _NOEXCEPT; size_type find_first_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY size_type find_first_of(const value_type* __s, size_type __pos = 0) const _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY size_type find_first_of(value_type __c, size_type __pos = 0) const _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY size_type find_last_of(const basic_string& __str, size_type __pos = npos) const _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY size_type find_last_of(__self_view __sv, size_type __pos = 0) const _NOEXCEPT; size_type find_last_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY size_type find_last_of(const value_type* __s, size_type __pos = npos) const _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY size_type find_last_of(value_type __c, size_type __pos = npos) const _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY size_type find_first_not_of(const basic_string& __str, size_type __pos = 0) const _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY size_type find_first_not_of(__self_view __sv, size_type __pos = 0) const _NOEXCEPT; size_type find_first_not_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY size_type find_first_not_of(const value_type* __s, size_type __pos = 0) const _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY size_type find_first_not_of(value_type __c, size_type __pos = 0) const _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY size_type find_last_not_of(const basic_string& __str, size_type __pos = npos) const _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY size_type find_last_not_of(__self_view __sv, size_type __pos = 0) const _NOEXCEPT; size_type find_last_not_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY size_type find_last_not_of(const value_type* __s, size_type __pos = npos) const _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY size_type find_last_not_of(value_type __c, size_type __pos = npos) const _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY int compare(const basic_string& __str) const _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY int compare(__self_view __sv) const _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY int compare(size_type __pos1, size_type __n1, __self_view __sv) const; _LIBCPP_INLINE_VISIBILITY int compare(size_type __pos1, size_type __n1, const basic_string& __str) const; int compare(size_type __pos1, size_type __n1, const basic_string& __str, size_type __pos2, size_type __n2=npos) const; template inline _LIBCPP_INLINE_VISIBILITY typename enable_if < __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int >::type compare(size_type __pos1, size_type __n1, const _Tp& __t, size_type __pos2, size_type __n2=npos) const; int compare(const value_type* __s) const _NOEXCEPT; int compare(size_type __pos1, size_type __n1, const value_type* __s) const; int compare(size_type __pos1, size_type __n1, const value_type* __s, size_type __n2) const; _LIBCPP_INLINE_VISIBILITY bool __invariants() const; _LIBCPP_INLINE_VISIBILITY bool __is_long() const _NOEXCEPT {return bool(__r_.first().__s.__size_ & __short_mask);} #if _LIBCPP_DEBUG_LEVEL >= 2 bool __dereferenceable(const const_iterator* __i) const; bool __decrementable(const const_iterator* __i) const; bool __addable(const const_iterator* __i, ptrdiff_t __n) const; bool __subscriptable(const const_iterator* __i, ptrdiff_t __n) const; #endif // _LIBCPP_DEBUG_LEVEL >= 2 private: _LIBCPP_INLINE_VISIBILITY allocator_type& __alloc() _NOEXCEPT {return __r_.second();} _LIBCPP_INLINE_VISIBILITY const allocator_type& __alloc() const _NOEXCEPT {return __r_.second();} #ifdef _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT _LIBCPP_INLINE_VISIBILITY void __set_short_size(size_type __s) _NOEXCEPT # if _LIBCPP_BIG_ENDIAN {__r_.first().__s.__size_ = (unsigned char)(__s << 1);} # else {__r_.first().__s.__size_ = (unsigned char)(__s);} # endif _LIBCPP_INLINE_VISIBILITY size_type __get_short_size() const _NOEXCEPT # if _LIBCPP_BIG_ENDIAN {return __r_.first().__s.__size_ >> 1;} # else {return __r_.first().__s.__size_;} # endif #else // _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT _LIBCPP_INLINE_VISIBILITY void __set_short_size(size_type __s) _NOEXCEPT # if _LIBCPP_BIG_ENDIAN {__r_.first().__s.__size_ = (unsigned char)(__s);} # else {__r_.first().__s.__size_ = (unsigned char)(__s << 1);} # endif _LIBCPP_INLINE_VISIBILITY size_type __get_short_size() const _NOEXCEPT # if _LIBCPP_BIG_ENDIAN {return __r_.first().__s.__size_;} # else {return __r_.first().__s.__size_ >> 1;} # endif #endif // _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT _LIBCPP_INLINE_VISIBILITY void __set_long_size(size_type __s) _NOEXCEPT {__r_.first().__l.__size_ = __s;} _LIBCPP_INLINE_VISIBILITY size_type __get_long_size() const _NOEXCEPT {return __r_.first().__l.__size_;} _LIBCPP_INLINE_VISIBILITY void __set_size(size_type __s) _NOEXCEPT {if (__is_long()) __set_long_size(__s); else __set_short_size(__s);} _LIBCPP_INLINE_VISIBILITY void __set_long_cap(size_type __s) _NOEXCEPT {__r_.first().__l.__cap_ = __long_mask | __s;} _LIBCPP_INLINE_VISIBILITY size_type __get_long_cap() const _NOEXCEPT {return __r_.first().__l.__cap_ & size_type(~__long_mask);} _LIBCPP_INLINE_VISIBILITY void __set_long_pointer(pointer __p) _NOEXCEPT {__r_.first().__l.__data_ = __p;} _LIBCPP_INLINE_VISIBILITY pointer __get_long_pointer() _NOEXCEPT {return __r_.first().__l.__data_;} _LIBCPP_INLINE_VISIBILITY const_pointer __get_long_pointer() const _NOEXCEPT {return __r_.first().__l.__data_;} _LIBCPP_INLINE_VISIBILITY pointer __get_short_pointer() _NOEXCEPT {return pointer_traits::pointer_to(__r_.first().__s.__data_[0]);} _LIBCPP_INLINE_VISIBILITY const_pointer __get_short_pointer() const _NOEXCEPT {return pointer_traits::pointer_to(__r_.first().__s.__data_[0]);} _LIBCPP_INLINE_VISIBILITY pointer __get_pointer() _NOEXCEPT {return __is_long() ? __get_long_pointer() : __get_short_pointer();} _LIBCPP_INLINE_VISIBILITY const_pointer __get_pointer() const _NOEXCEPT {return __is_long() ? __get_long_pointer() : __get_short_pointer();} _LIBCPP_INLINE_VISIBILITY void __zero() _NOEXCEPT { size_type (&__a)[__n_words] = __r_.first().__r.__words; for (unsigned __i = 0; __i < __n_words; ++__i) __a[__i] = 0; } template static _LIBCPP_INLINE_VISIBILITY size_type __align_it(size_type __s) _NOEXCEPT {return (__s + (__a-1)) & ~(__a-1);} enum {__alignment = 16}; static _LIBCPP_INLINE_VISIBILITY size_type __recommend(size_type __s) _NOEXCEPT {return (__s < __min_cap ? static_cast(__min_cap) : __align_it (__s+1)) - 1;} inline void __init(const value_type* __s, size_type __sz, size_type __reserve); inline void __init(const value_type* __s, size_type __sz); inline void __init(size_type __n, value_type __c); template inline typename enable_if < __is_exactly_input_iterator<_InputIterator>::value, void >::type __init(_InputIterator __first, _InputIterator __last); template inline typename enable_if < __is_forward_iterator<_ForwardIterator>::value, void >::type __init(_ForwardIterator __first, _ForwardIterator __last); void __grow_by(size_type __old_cap, size_type __delta_cap, size_type __old_sz, size_type __n_copy, size_type __n_del, size_type __n_add = 0); void __grow_by_and_replace(size_type __old_cap, size_type __delta_cap, size_type __old_sz, size_type __n_copy, size_type __n_del, size_type __n_add, const value_type* __p_new_stuff); _LIBCPP_INLINE_VISIBILITY void __erase_to_end(size_type __pos); _LIBCPP_INLINE_VISIBILITY void __copy_assign_alloc(const basic_string& __str) {__copy_assign_alloc(__str, integral_constant());} _LIBCPP_INLINE_VISIBILITY void __copy_assign_alloc(const basic_string& __str, true_type) { if (__alloc() == __str.__alloc()) __alloc() = __str.__alloc(); else { if (!__str.__is_long()) { clear(); shrink_to_fit(); __alloc() = __str.__alloc(); } else { allocator_type __a = __str.__alloc(); pointer __p = __alloc_traits::allocate(__a, __str.__get_long_cap()); clear(); shrink_to_fit(); __alloc() = _VSTD::move(__a); __set_long_pointer(__p); __set_long_cap(__str.__get_long_cap()); __set_long_size(__str.size()); } } } _LIBCPP_INLINE_VISIBILITY void __copy_assign_alloc(const basic_string&, false_type) _NOEXCEPT {} #ifndef _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY void __move_assign(basic_string& __str, false_type) _NOEXCEPT_(__alloc_traits::is_always_equal::value); _LIBCPP_INLINE_VISIBILITY void __move_assign(basic_string& __str, true_type) #if _LIBCPP_STD_VER > 14 _NOEXCEPT; #else _NOEXCEPT_(is_nothrow_move_assignable::value); #endif #endif _LIBCPP_INLINE_VISIBILITY void __move_assign_alloc(basic_string& __str) _NOEXCEPT_( !__alloc_traits::propagate_on_container_move_assignment::value || is_nothrow_move_assignable::value) {__move_assign_alloc(__str, integral_constant());} _LIBCPP_INLINE_VISIBILITY void __move_assign_alloc(basic_string& __c, true_type) _NOEXCEPT_(is_nothrow_move_assignable::value) { __alloc() = _VSTD::move(__c.__alloc()); } _LIBCPP_INLINE_VISIBILITY void __move_assign_alloc(basic_string&, false_type) _NOEXCEPT {} _LIBCPP_INLINE_VISIBILITY void __invalidate_all_iterators(); _LIBCPP_INLINE_VISIBILITY void __invalidate_iterators_past(size_type); friend basic_string operator+<>(const basic_string&, const basic_string&); friend basic_string operator+<>(const value_type*, const basic_string&); friend basic_string operator+<>(value_type, const basic_string&); friend basic_string operator+<>(const basic_string&, const value_type*); friend basic_string operator+<>(const basic_string&, value_type); }; template inline _LIBCPP_INLINE_VISIBILITY void basic_string<_CharT, _Traits, _Allocator>::__invalidate_all_iterators() { #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__invalidate_all(this); #endif // _LIBCPP_DEBUG_LEVEL >= 2 } template inline _LIBCPP_INLINE_VISIBILITY void basic_string<_CharT, _Traits, _Allocator>::__invalidate_iterators_past(size_type #if _LIBCPP_DEBUG_LEVEL >= 2 __pos #endif ) { #if _LIBCPP_DEBUG_LEVEL >= 2 __c_node* __c = __get_db()->__find_c_and_lock(this); if (__c) { const_pointer __new_last = __get_pointer() + __pos; for (__i_node** __p = __c->end_; __p != __c->beg_; ) { --__p; const_iterator* __i = static_cast((*__p)->__i_); if (__i->base() > __new_last) { (*__p)->__c_ = nullptr; if (--__c->end_ != __p) memmove(__p, __p+1, (__c->end_ - __p)*sizeof(__i_node*)); } } __get_db()->unlock(); } #endif // _LIBCPP_DEBUG_LEVEL >= 2 } template inline _LIBCPP_INLINE_VISIBILITY basic_string<_CharT, _Traits, _Allocator>::basic_string() _NOEXCEPT_(is_nothrow_default_constructible::value) { #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); #endif __zero(); } template inline _LIBCPP_INLINE_VISIBILITY basic_string<_CharT, _Traits, _Allocator>::basic_string(const allocator_type& __a) #if _LIBCPP_STD_VER <= 14 _NOEXCEPT_(is_nothrow_copy_constructible::value) #else _NOEXCEPT #endif : __r_(__second_tag(), __a) { #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); #endif __zero(); } template void basic_string<_CharT, _Traits, _Allocator>::__init(const value_type* __s, size_type __sz, size_type __reserve) { if (__reserve > max_size()) this->__throw_length_error(); pointer __p; if (__reserve < __min_cap) { __set_short_size(__sz); __p = __get_short_pointer(); } else { size_type __cap = __recommend(__reserve); __p = __alloc_traits::allocate(__alloc(), __cap+1); __set_long_pointer(__p); __set_long_cap(__cap+1); __set_long_size(__sz); } traits_type::copy(_VSTD::__to_raw_pointer(__p), __s, __sz); traits_type::assign(__p[__sz], value_type()); } template void basic_string<_CharT, _Traits, _Allocator>::__init(const value_type* __s, size_type __sz) { if (__sz > max_size()) this->__throw_length_error(); pointer __p; if (__sz < __min_cap) { __set_short_size(__sz); __p = __get_short_pointer(); } else { size_type __cap = __recommend(__sz); __p = __alloc_traits::allocate(__alloc(), __cap+1); __set_long_pointer(__p); __set_long_cap(__cap+1); __set_long_size(__sz); } traits_type::copy(_VSTD::__to_raw_pointer(__p), __s, __sz); traits_type::assign(__p[__sz], value_type()); } template inline _LIBCPP_INLINE_VISIBILITY basic_string<_CharT, _Traits, _Allocator>::basic_string(const _CharT* __s) { _LIBCPP_ASSERT(__s != nullptr, "basic_string(const char*) detected nullptr"); __init(__s, traits_type::length(__s)); #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); #endif } template inline _LIBCPP_INLINE_VISIBILITY basic_string<_CharT, _Traits, _Allocator>::basic_string(const _CharT* __s, const _Allocator& __a) : __r_(__second_tag(), __a) { _LIBCPP_ASSERT(__s != nullptr, "basic_string(const char*, allocator) detected nullptr"); __init(__s, traits_type::length(__s)); #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); #endif } template inline _LIBCPP_INLINE_VISIBILITY basic_string<_CharT, _Traits, _Allocator>::basic_string(const _CharT* __s, size_type __n) { _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "basic_string(const char*, n) detected nullptr"); __init(__s, __n); #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); #endif } template inline _LIBCPP_INLINE_VISIBILITY basic_string<_CharT, _Traits, _Allocator>::basic_string(const _CharT* __s, size_type __n, const _Allocator& __a) : __r_(__second_tag(), __a) { _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "basic_string(const char*, n, allocator) detected nullptr"); __init(__s, __n); #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); #endif } template basic_string<_CharT, _Traits, _Allocator>::basic_string(const basic_string& __str) : __r_(__second_tag(), __alloc_traits::select_on_container_copy_construction(__str.__alloc())) { if (!__str.__is_long()) __r_.first().__r = __str.__r_.first().__r; else __init(_VSTD::__to_raw_pointer(__str.__get_long_pointer()), __str.__get_long_size()); #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); #endif } template basic_string<_CharT, _Traits, _Allocator>::basic_string( const basic_string& __str, const allocator_type& __a) : __r_(__second_tag(), __a) { if (!__str.__is_long()) __r_.first().__r = __str.__r_.first().__r; else __init(_VSTD::__to_raw_pointer(__str.__get_long_pointer()), __str.__get_long_size()); #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); #endif } #ifndef _LIBCPP_CXX03_LANG template inline _LIBCPP_INLINE_VISIBILITY basic_string<_CharT, _Traits, _Allocator>::basic_string(basic_string&& __str) #if _LIBCPP_STD_VER <= 14 _NOEXCEPT_(is_nothrow_move_constructible::value) #else _NOEXCEPT #endif : __r_(_VSTD::move(__str.__r_)) { __str.__zero(); #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); if (__is_long()) __get_db()->swap(this, &__str); #endif } template inline _LIBCPP_INLINE_VISIBILITY basic_string<_CharT, _Traits, _Allocator>::basic_string(basic_string&& __str, const allocator_type& __a) : __r_(__second_tag(), __a) { if (__str.__is_long() && __a != __str.__alloc()) // copy, not move __init(_VSTD::__to_raw_pointer(__str.__get_long_pointer()), __str.__get_long_size()); else { __r_.first().__r = __str.__r_.first().__r; __str.__zero(); } #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); if (__is_long()) __get_db()->swap(this, &__str); #endif } #endif // _LIBCPP_CXX03_LANG template void basic_string<_CharT, _Traits, _Allocator>::__init(size_type __n, value_type __c) { if (__n > max_size()) this->__throw_length_error(); pointer __p; if (__n < __min_cap) { __set_short_size(__n); __p = __get_short_pointer(); } else { size_type __cap = __recommend(__n); __p = __alloc_traits::allocate(__alloc(), __cap+1); __set_long_pointer(__p); __set_long_cap(__cap+1); __set_long_size(__n); } traits_type::assign(_VSTD::__to_raw_pointer(__p), __n, __c); traits_type::assign(__p[__n], value_type()); } template inline _LIBCPP_INLINE_VISIBILITY basic_string<_CharT, _Traits, _Allocator>::basic_string(size_type __n, _CharT __c) { __init(__n, __c); #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); #endif } template inline _LIBCPP_INLINE_VISIBILITY basic_string<_CharT, _Traits, _Allocator>::basic_string(size_type __n, _CharT __c, const _Allocator& __a) : __r_(__second_tag(), __a) { __init(__n, __c); #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); #endif } template basic_string<_CharT, _Traits, _Allocator>::basic_string(const basic_string& __str, size_type __pos, size_type __n, const _Allocator& __a) : __r_(__second_tag(), __a) { size_type __str_sz = __str.size(); if (__pos > __str_sz) this->__throw_out_of_range(); __init(__str.data() + __pos, _VSTD::min(__n, __str_sz - __pos)); #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); #endif } template inline _LIBCPP_INLINE_VISIBILITY basic_string<_CharT, _Traits, _Allocator>::basic_string(const basic_string& __str, size_type __pos, const _Allocator& __a) : __r_(__second_tag(), __a) { size_type __str_sz = __str.size(); if (__pos > __str_sz) this->__throw_out_of_range(); __init(__str.data() + __pos, __str_sz - __pos); #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); #endif } template template basic_string<_CharT, _Traits, _Allocator>::basic_string( const _Tp& __t, size_type __pos, size_type __n, const allocator_type& __a, typename enable_if<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, void>::type *) : __r_(__second_tag(), __a) { __self_view __sv = __self_view(__t).substr(__pos, __n); __init(__sv.data(), __sv.size()); #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); #endif } template inline _LIBCPP_INLINE_VISIBILITY basic_string<_CharT, _Traits, _Allocator>::basic_string(__self_view __sv) { __init(__sv.data(), __sv.size()); #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); #endif } template inline _LIBCPP_INLINE_VISIBILITY basic_string<_CharT, _Traits, _Allocator>::basic_string(__self_view __sv, const _Allocator& __a) : __r_(__second_tag(), __a) { __init(__sv.data(), __sv.size()); #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); #endif } template template typename enable_if < __is_exactly_input_iterator<_InputIterator>::value, void >::type basic_string<_CharT, _Traits, _Allocator>::__init(_InputIterator __first, _InputIterator __last) { __zero(); #ifndef _LIBCPP_NO_EXCEPTIONS try { #endif // _LIBCPP_NO_EXCEPTIONS for (; __first != __last; ++__first) push_back(*__first); #ifndef _LIBCPP_NO_EXCEPTIONS } catch (...) { if (__is_long()) __alloc_traits::deallocate(__alloc(), __get_long_pointer(), __get_long_cap()); throw; } #endif // _LIBCPP_NO_EXCEPTIONS } template template typename enable_if < __is_forward_iterator<_ForwardIterator>::value, void >::type basic_string<_CharT, _Traits, _Allocator>::__init(_ForwardIterator __first, _ForwardIterator __last) { size_type __sz = static_cast(_VSTD::distance(__first, __last)); if (__sz > max_size()) this->__throw_length_error(); pointer __p; if (__sz < __min_cap) { __set_short_size(__sz); __p = __get_short_pointer(); } else { size_type __cap = __recommend(__sz); __p = __alloc_traits::allocate(__alloc(), __cap+1); __set_long_pointer(__p); __set_long_cap(__cap+1); __set_long_size(__sz); } for (; __first != __last; ++__first, (void) ++__p) traits_type::assign(*__p, *__first); traits_type::assign(*__p, value_type()); } template template inline _LIBCPP_INLINE_VISIBILITY basic_string<_CharT, _Traits, _Allocator>::basic_string(_InputIterator __first, _InputIterator __last) { __init(__first, __last); #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); #endif } template template inline _LIBCPP_INLINE_VISIBILITY basic_string<_CharT, _Traits, _Allocator>::basic_string(_InputIterator __first, _InputIterator __last, const allocator_type& __a) : __r_(__second_tag(), __a) { __init(__first, __last); #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); #endif } #ifndef _LIBCPP_CXX03_LANG template inline _LIBCPP_INLINE_VISIBILITY basic_string<_CharT, _Traits, _Allocator>::basic_string( initializer_list<_CharT> __il) { __init(__il.begin(), __il.end()); #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); #endif } template inline _LIBCPP_INLINE_VISIBILITY basic_string<_CharT, _Traits, _Allocator>::basic_string( initializer_list<_CharT> __il, const _Allocator& __a) : __r_(__second_tag(), __a) { __init(__il.begin(), __il.end()); #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); #endif } #endif // _LIBCPP_CXX03_LANG template basic_string<_CharT, _Traits, _Allocator>::~basic_string() { #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__erase_c(this); #endif if (__is_long()) __alloc_traits::deallocate(__alloc(), __get_long_pointer(), __get_long_cap()); } template void basic_string<_CharT, _Traits, _Allocator>::__grow_by_and_replace (size_type __old_cap, size_type __delta_cap, size_type __old_sz, size_type __n_copy, size_type __n_del, size_type __n_add, const value_type* __p_new_stuff) { size_type __ms = max_size(); if (__delta_cap > __ms - __old_cap - 1) this->__throw_length_error(); pointer __old_p = __get_pointer(); size_type __cap = __old_cap < __ms / 2 - __alignment ? __recommend(_VSTD::max(__old_cap + __delta_cap, 2 * __old_cap)) : __ms - 1; pointer __p = __alloc_traits::allocate(__alloc(), __cap+1); __invalidate_all_iterators(); if (__n_copy != 0) traits_type::copy(_VSTD::__to_raw_pointer(__p), _VSTD::__to_raw_pointer(__old_p), __n_copy); if (__n_add != 0) traits_type::copy(_VSTD::__to_raw_pointer(__p) + __n_copy, __p_new_stuff, __n_add); size_type __sec_cp_sz = __old_sz - __n_del - __n_copy; if (__sec_cp_sz != 0) traits_type::copy(_VSTD::__to_raw_pointer(__p) + __n_copy + __n_add, _VSTD::__to_raw_pointer(__old_p) + __n_copy + __n_del, __sec_cp_sz); if (__old_cap+1 != __min_cap) __alloc_traits::deallocate(__alloc(), __old_p, __old_cap+1); __set_long_pointer(__p); __set_long_cap(__cap+1); __old_sz = __n_copy + __n_add + __sec_cp_sz; __set_long_size(__old_sz); traits_type::assign(__p[__old_sz], value_type()); } template void basic_string<_CharT, _Traits, _Allocator>::__grow_by(size_type __old_cap, size_type __delta_cap, size_type __old_sz, size_type __n_copy, size_type __n_del, size_type __n_add) { size_type __ms = max_size(); if (__delta_cap > __ms - __old_cap) this->__throw_length_error(); pointer __old_p = __get_pointer(); size_type __cap = __old_cap < __ms / 2 - __alignment ? __recommend(_VSTD::max(__old_cap + __delta_cap, 2 * __old_cap)) : __ms - 1; pointer __p = __alloc_traits::allocate(__alloc(), __cap+1); __invalidate_all_iterators(); if (__n_copy != 0) traits_type::copy(_VSTD::__to_raw_pointer(__p), _VSTD::__to_raw_pointer(__old_p), __n_copy); size_type __sec_cp_sz = __old_sz - __n_del - __n_copy; if (__sec_cp_sz != 0) traits_type::copy(_VSTD::__to_raw_pointer(__p) + __n_copy + __n_add, _VSTD::__to_raw_pointer(__old_p) + __n_copy + __n_del, __sec_cp_sz); if (__old_cap+1 != __min_cap) __alloc_traits::deallocate(__alloc(), __old_p, __old_cap+1); __set_long_pointer(__p); __set_long_cap(__cap+1); } // assign template basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::assign(const value_type* __s, size_type __n) { _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string::assign received nullptr"); size_type __cap = capacity(); if (__cap >= __n) { value_type* __p = _VSTD::__to_raw_pointer(__get_pointer()); traits_type::move(__p, __s, __n); traits_type::assign(__p[__n], value_type()); __set_size(__n); __invalidate_iterators_past(__n); } else { size_type __sz = size(); __grow_by_and_replace(__cap, __n - __cap, __sz, 0, __sz, __n, __s); } return *this; } template basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::assign(size_type __n, value_type __c) { size_type __cap = capacity(); if (__cap < __n) { size_type __sz = size(); __grow_by(__cap, __n - __cap, __sz, 0, __sz); } else __invalidate_iterators_past(__n); value_type* __p = _VSTD::__to_raw_pointer(__get_pointer()); traits_type::assign(__p, __n, __c); traits_type::assign(__p[__n], value_type()); __set_size(__n); return *this; } template basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::operator=(value_type __c) { pointer __p; if (__is_long()) { __p = __get_long_pointer(); __set_long_size(1); } else { __p = __get_short_pointer(); __set_short_size(1); } traits_type::assign(*__p, __c); traits_type::assign(*++__p, value_type()); __invalidate_iterators_past(1); return *this; } template basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::operator=(const basic_string& __str) { if (this != &__str) { __copy_assign_alloc(__str); assign(__str.data(), __str.size()); } return *this; } #ifndef _LIBCPP_CXX03_LANG template inline _LIBCPP_INLINE_VISIBILITY void basic_string<_CharT, _Traits, _Allocator>::__move_assign(basic_string& __str, false_type) _NOEXCEPT_(__alloc_traits::is_always_equal::value) { if (__alloc() != __str.__alloc()) assign(__str); else __move_assign(__str, true_type()); } template inline _LIBCPP_INLINE_VISIBILITY void basic_string<_CharT, _Traits, _Allocator>::__move_assign(basic_string& __str, true_type) #if _LIBCPP_STD_VER > 14 _NOEXCEPT #else _NOEXCEPT_(is_nothrow_move_assignable::value) #endif { clear(); shrink_to_fit(); __r_.first() = __str.__r_.first(); __move_assign_alloc(__str); __str.__zero(); } template inline _LIBCPP_INLINE_VISIBILITY basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::operator=(basic_string&& __str) _NOEXCEPT_((__noexcept_move_assign_container<_Allocator, __alloc_traits>::value)) { __move_assign(__str, integral_constant()); return *this; } #endif template template typename enable_if < __is_exactly_input_iterator <_InputIterator>::value || !__libcpp_string_gets_noexcept_iterator<_InputIterator>::value, basic_string<_CharT, _Traits, _Allocator>& >::type basic_string<_CharT, _Traits, _Allocator>::assign(_InputIterator __first, _InputIterator __last) { const basic_string __temp(__first, __last, __alloc()); assign(__temp.data(), __temp.size()); return *this; } template template typename enable_if < __is_forward_iterator<_ForwardIterator>::value && __libcpp_string_gets_noexcept_iterator<_ForwardIterator>::value, basic_string<_CharT, _Traits, _Allocator>& >::type basic_string<_CharT, _Traits, _Allocator>::assign(_ForwardIterator __first, _ForwardIterator __last) { size_type __n = static_cast(_VSTD::distance(__first, __last)); size_type __cap = capacity(); if (__cap < __n) { size_type __sz = size(); __grow_by(__cap, __n - __cap, __sz, 0, __sz); } else __invalidate_iterators_past(__n); pointer __p = __get_pointer(); for (; __first != __last; ++__first, ++__p) traits_type::assign(*__p, *__first); traits_type::assign(*__p, value_type()); __set_size(__n); return *this; } template basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::assign(const basic_string& __str, size_type __pos, size_type __n) { size_type __sz = __str.size(); if (__pos > __sz) this->__throw_out_of_range(); return assign(__str.data() + __pos, _VSTD::min(__n, __sz - __pos)); } template template typename enable_if < __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, basic_string<_CharT, _Traits, _Allocator>& >::type basic_string<_CharT, _Traits, _Allocator>::assign(const _Tp & __t, size_type __pos, size_type __n) { __self_view __sv = __t; size_type __sz = __sv.size(); if (__pos > __sz) this->__throw_out_of_range(); return assign(__sv.data() + __pos, _VSTD::min(__n, __sz - __pos)); } template basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::assign(const value_type* __s) { _LIBCPP_ASSERT(__s != nullptr, "string::assign received nullptr"); return assign(__s, traits_type::length(__s)); } // append template basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::append(const value_type* __s, size_type __n) { _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string::append received nullptr"); size_type __cap = capacity(); size_type __sz = size(); if (__cap - __sz >= __n) { if (__n) { value_type* __p = _VSTD::__to_raw_pointer(__get_pointer()); traits_type::copy(__p + __sz, __s, __n); __sz += __n; __set_size(__sz); traits_type::assign(__p[__sz], value_type()); } } else __grow_by_and_replace(__cap, __sz + __n - __cap, __sz, __sz, 0, __n, __s); return *this; } template basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::append(size_type __n, value_type __c) { if (__n) { size_type __cap = capacity(); size_type __sz = size(); if (__cap - __sz < __n) __grow_by(__cap, __sz + __n - __cap, __sz, __sz, 0); pointer __p = __get_pointer(); traits_type::assign(_VSTD::__to_raw_pointer(__p) + __sz, __n, __c); __sz += __n; __set_size(__sz); traits_type::assign(__p[__sz], value_type()); } return *this; } template void basic_string<_CharT, _Traits, _Allocator>::push_back(value_type __c) { bool __is_short = !__is_long(); size_type __cap; size_type __sz; if (__is_short) { __cap = __min_cap - 1; __sz = __get_short_size(); } else { __cap = __get_long_cap() - 1; __sz = __get_long_size(); } if (__sz == __cap) { __grow_by(__cap, 1, __sz, __sz, 0); __is_short = !__is_long(); } pointer __p; if (__is_short) { __p = __get_short_pointer() + __sz; __set_short_size(__sz+1); } else { __p = __get_long_pointer() + __sz; __set_long_size(__sz+1); } traits_type::assign(*__p, __c); traits_type::assign(*++__p, value_type()); } template bool __ptr_in_range (const _Tp* __p, const _Tp* __first, const _Tp* __last) { return __first <= __p && __p < __last; } template bool __ptr_in_range (const _Tp1*, const _Tp2*, const _Tp2*) { return false; } template template basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::__append_forward_unsafe( _ForwardIterator __first, _ForwardIterator __last) { static_assert(__is_forward_iterator<_ForwardIterator>::value, "function requires a ForwardIterator"); size_type __sz = size(); size_type __cap = capacity(); size_type __n = static_cast(_VSTD::distance(__first, __last)); if (__n) { typedef typename iterator_traits<_ForwardIterator>::reference _CharRef; _CharRef __tmp_ref = *__first; if (__ptr_in_range(_VSTD::addressof(__tmp_ref), data(), data() + size())) { const basic_string __temp (__first, __last, __alloc()); append(__temp.data(), __temp.size()); } else { if (__cap - __sz < __n) __grow_by(__cap, __sz + __n - __cap, __sz, __sz, 0); pointer __p = __get_pointer() + __sz; for (; __first != __last; ++__p, ++__first) traits_type::assign(*__p, *__first); traits_type::assign(*__p, value_type()); __set_size(__sz + __n); } } return *this; } template inline _LIBCPP_INLINE_VISIBILITY basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::append(const basic_string& __str) { return append(__str.data(), __str.size()); } template basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::append(const basic_string& __str, size_type __pos, size_type __n) { size_type __sz = __str.size(); if (__pos > __sz) this->__throw_out_of_range(); return append(__str.data() + __pos, _VSTD::min(__n, __sz - __pos)); } template template typename enable_if < __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, basic_string<_CharT, _Traits, _Allocator>& >::type basic_string<_CharT, _Traits, _Allocator>::append(const _Tp & __t, size_type __pos, size_type __n) { __self_view __sv = __t; size_type __sz = __sv.size(); if (__pos > __sz) this->__throw_out_of_range(); return append(__sv.data() + __pos, _VSTD::min(__n, __sz - __pos)); } template basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::append(const value_type* __s) { _LIBCPP_ASSERT(__s != nullptr, "string::append received nullptr"); return append(__s, traits_type::length(__s)); } // insert template basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::insert(size_type __pos, const value_type* __s, size_type __n) { _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string::insert received nullptr"); size_type __sz = size(); if (__pos > __sz) this->__throw_out_of_range(); size_type __cap = capacity(); if (__cap - __sz >= __n) { if (__n) { value_type* __p = _VSTD::__to_raw_pointer(__get_pointer()); size_type __n_move = __sz - __pos; if (__n_move != 0) { if (__p + __pos <= __s && __s < __p + __sz) __s += __n; traits_type::move(__p + __pos + __n, __p + __pos, __n_move); } traits_type::move(__p + __pos, __s, __n); __sz += __n; __set_size(__sz); traits_type::assign(__p[__sz], value_type()); } } else __grow_by_and_replace(__cap, __sz + __n - __cap, __sz, __pos, 0, __n, __s); return *this; } template basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::insert(size_type __pos, size_type __n, value_type __c) { size_type __sz = size(); if (__pos > __sz) this->__throw_out_of_range(); if (__n) { size_type __cap = capacity(); value_type* __p; if (__cap - __sz >= __n) { __p = _VSTD::__to_raw_pointer(__get_pointer()); size_type __n_move = __sz - __pos; if (__n_move != 0) traits_type::move(__p + __pos + __n, __p + __pos, __n_move); } else { __grow_by(__cap, __sz + __n - __cap, __sz, __pos, 0, __n); __p = _VSTD::__to_raw_pointer(__get_long_pointer()); } traits_type::assign(__p + __pos, __n, __c); __sz += __n; __set_size(__sz); traits_type::assign(__p[__sz], value_type()); } return *this; } template template typename enable_if < __is_exactly_input_iterator<_InputIterator>::value || !__libcpp_string_gets_noexcept_iterator<_InputIterator>::value, typename basic_string<_CharT, _Traits, _Allocator>::iterator >::type basic_string<_CharT, _Traits, _Allocator>::insert(const_iterator __pos, _InputIterator __first, _InputIterator __last) { #if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__pos) == this, "string::insert(iterator, range) called with an iterator not" " referring to this string"); #endif const basic_string __temp(__first, __last, __alloc()); return insert(__pos, __temp.data(), __temp.data() + __temp.size()); } template template typename enable_if < __is_forward_iterator<_ForwardIterator>::value && __libcpp_string_gets_noexcept_iterator<_ForwardIterator>::value, typename basic_string<_CharT, _Traits, _Allocator>::iterator >::type basic_string<_CharT, _Traits, _Allocator>::insert(const_iterator __pos, _ForwardIterator __first, _ForwardIterator __last) { #if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__pos) == this, "string::insert(iterator, range) called with an iterator not" " referring to this string"); #endif size_type __ip = static_cast(__pos - begin()); size_type __n = static_cast(_VSTD::distance(__first, __last)); if (__n) { typedef typename iterator_traits<_ForwardIterator>::reference _CharRef; _CharRef __tmp_char = *__first; if (__ptr_in_range(_VSTD::addressof(__tmp_char), data(), data() + size())) { const basic_string __temp(__first, __last, __alloc()); return insert(__pos, __temp.data(), __temp.data() + __temp.size()); } size_type __sz = size(); size_type __cap = capacity(); value_type* __p; if (__cap - __sz >= __n) { __p = _VSTD::__to_raw_pointer(__get_pointer()); size_type __n_move = __sz - __ip; if (__n_move != 0) traits_type::move(__p + __ip + __n, __p + __ip, __n_move); } else { __grow_by(__cap, __sz + __n - __cap, __sz, __ip, 0, __n); __p = _VSTD::__to_raw_pointer(__get_long_pointer()); } __sz += __n; __set_size(__sz); traits_type::assign(__p[__sz], value_type()); for (__p += __ip; __first != __last; ++__p, ++__first) traits_type::assign(*__p, *__first); } return begin() + __ip; } template inline _LIBCPP_INLINE_VISIBILITY basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::insert(size_type __pos1, const basic_string& __str) { return insert(__pos1, __str.data(), __str.size()); } template basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::insert(size_type __pos1, const basic_string& __str, size_type __pos2, size_type __n) { size_type __str_sz = __str.size(); if (__pos2 > __str_sz) this->__throw_out_of_range(); return insert(__pos1, __str.data() + __pos2, _VSTD::min(__n, __str_sz - __pos2)); } template template typename enable_if < __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, basic_string<_CharT, _Traits, _Allocator>& >::type basic_string<_CharT, _Traits, _Allocator>::insert(size_type __pos1, const _Tp& __t, size_type __pos2, size_type __n) { __self_view __sv = __t; size_type __str_sz = __sv.size(); if (__pos2 > __str_sz) this->__throw_out_of_range(); return insert(__pos1, __sv.data() + __pos2, _VSTD::min(__n, __str_sz - __pos2)); } template basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::insert(size_type __pos, const value_type* __s) { _LIBCPP_ASSERT(__s != nullptr, "string::insert received nullptr"); return insert(__pos, __s, traits_type::length(__s)); } template typename basic_string<_CharT, _Traits, _Allocator>::iterator basic_string<_CharT, _Traits, _Allocator>::insert(const_iterator __pos, value_type __c) { size_type __ip = static_cast(__pos - begin()); size_type __sz = size(); size_type __cap = capacity(); value_type* __p; if (__cap == __sz) { __grow_by(__cap, 1, __sz, __ip, 0, 1); __p = _VSTD::__to_raw_pointer(__get_long_pointer()); } else { __p = _VSTD::__to_raw_pointer(__get_pointer()); size_type __n_move = __sz - __ip; if (__n_move != 0) traits_type::move(__p + __ip + 1, __p + __ip, __n_move); } traits_type::assign(__p[__ip], __c); traits_type::assign(__p[++__sz], value_type()); __set_size(__sz); return begin() + static_cast(__ip); } template inline _LIBCPP_INLINE_VISIBILITY typename basic_string<_CharT, _Traits, _Allocator>::iterator basic_string<_CharT, _Traits, _Allocator>::insert(const_iterator __pos, size_type __n, value_type __c) { #if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__pos) == this, "string::insert(iterator, n, value) called with an iterator not" " referring to this string"); #endif difference_type __p = __pos - begin(); insert(static_cast(__p), __n, __c); return begin() + __p; } // replace template basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::replace(size_type __pos, size_type __n1, const value_type* __s, size_type __n2) _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK { _LIBCPP_ASSERT(__n2 == 0 || __s != nullptr, "string::replace received nullptr"); size_type __sz = size(); if (__pos > __sz) this->__throw_out_of_range(); __n1 = _VSTD::min(__n1, __sz - __pos); size_type __cap = capacity(); if (__cap - __sz + __n1 >= __n2) { value_type* __p = _VSTD::__to_raw_pointer(__get_pointer()); if (__n1 != __n2) { size_type __n_move = __sz - __pos - __n1; if (__n_move != 0) { if (__n1 > __n2) { traits_type::move(__p + __pos, __s, __n2); traits_type::move(__p + __pos + __n2, __p + __pos + __n1, __n_move); goto __finish; } if (__p + __pos < __s && __s < __p + __sz) { if (__p + __pos + __n1 <= __s) __s += __n2 - __n1; else // __p + __pos < __s < __p + __pos + __n1 { traits_type::move(__p + __pos, __s, __n1); __pos += __n1; __s += __n2; __n2 -= __n1; __n1 = 0; } } traits_type::move(__p + __pos + __n2, __p + __pos + __n1, __n_move); } } traits_type::move(__p + __pos, __s, __n2); __finish: // __sz += __n2 - __n1; in this and the below function below can cause unsigned integer overflow, // but this is a safe operation, so we disable the check. __sz += __n2 - __n1; __set_size(__sz); __invalidate_iterators_past(__sz); traits_type::assign(__p[__sz], value_type()); } else __grow_by_and_replace(__cap, __sz - __n1 + __n2 - __cap, __sz, __pos, __n1, __n2, __s); return *this; } template basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::replace(size_type __pos, size_type __n1, size_type __n2, value_type __c) _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK { size_type __sz = size(); if (__pos > __sz) this->__throw_out_of_range(); __n1 = _VSTD::min(__n1, __sz - __pos); size_type __cap = capacity(); value_type* __p; if (__cap - __sz + __n1 >= __n2) { __p = _VSTD::__to_raw_pointer(__get_pointer()); if (__n1 != __n2) { size_type __n_move = __sz - __pos - __n1; if (__n_move != 0) traits_type::move(__p + __pos + __n2, __p + __pos + __n1, __n_move); } } else { __grow_by(__cap, __sz - __n1 + __n2 - __cap, __sz, __pos, __n1, __n2); __p = _VSTD::__to_raw_pointer(__get_long_pointer()); } traits_type::assign(__p + __pos, __n2, __c); __sz += __n2 - __n1; __set_size(__sz); __invalidate_iterators_past(__sz); traits_type::assign(__p[__sz], value_type()); return *this; } template template typename enable_if < __is_input_iterator<_InputIterator>::value, basic_string<_CharT, _Traits, _Allocator>& >::type basic_string<_CharT, _Traits, _Allocator>::replace(const_iterator __i1, const_iterator __i2, _InputIterator __j1, _InputIterator __j2) { const basic_string __temp(__j1, __j2, __alloc()); return this->replace(__i1, __i2, __temp); } template inline _LIBCPP_INLINE_VISIBILITY basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::replace(size_type __pos1, size_type __n1, const basic_string& __str) { return replace(__pos1, __n1, __str.data(), __str.size()); } template basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::replace(size_type __pos1, size_type __n1, const basic_string& __str, size_type __pos2, size_type __n2) { size_type __str_sz = __str.size(); if (__pos2 > __str_sz) this->__throw_out_of_range(); return replace(__pos1, __n1, __str.data() + __pos2, _VSTD::min(__n2, __str_sz - __pos2)); } template template typename enable_if < __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, basic_string<_CharT, _Traits, _Allocator>& >::type basic_string<_CharT, _Traits, _Allocator>::replace(size_type __pos1, size_type __n1, const _Tp& __t, size_type __pos2, size_type __n2) { __self_view __sv = __t; size_type __str_sz = __sv.size(); if (__pos2 > __str_sz) this->__throw_out_of_range(); return replace(__pos1, __n1, __sv.data() + __pos2, _VSTD::min(__n2, __str_sz - __pos2)); } template basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::replace(size_type __pos, size_type __n1, const value_type* __s) { _LIBCPP_ASSERT(__s != nullptr, "string::replace received nullptr"); return replace(__pos, __n1, __s, traits_type::length(__s)); } template inline _LIBCPP_INLINE_VISIBILITY basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::replace(const_iterator __i1, const_iterator __i2, const basic_string& __str) { return replace(static_cast(__i1 - begin()), static_cast(__i2 - __i1), __str.data(), __str.size()); } template inline _LIBCPP_INLINE_VISIBILITY basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::replace(const_iterator __i1, const_iterator __i2, const value_type* __s, size_type __n) { return replace(static_cast(__i1 - begin()), static_cast(__i2 - __i1), __s, __n); } template inline _LIBCPP_INLINE_VISIBILITY basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::replace(const_iterator __i1, const_iterator __i2, const value_type* __s) { return replace(static_cast(__i1 - begin()), static_cast(__i2 - __i1), __s); } template inline _LIBCPP_INLINE_VISIBILITY basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::replace(const_iterator __i1, const_iterator __i2, size_type __n, value_type __c) { return replace(static_cast(__i1 - begin()), static_cast(__i2 - __i1), __n, __c); } // erase template basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::erase(size_type __pos, size_type __n) { size_type __sz = size(); if (__pos > __sz) this->__throw_out_of_range(); if (__n) { value_type* __p = _VSTD::__to_raw_pointer(__get_pointer()); __n = _VSTD::min(__n, __sz - __pos); size_type __n_move = __sz - __pos - __n; if (__n_move != 0) traits_type::move(__p + __pos, __p + __pos + __n, __n_move); __sz -= __n; __set_size(__sz); __invalidate_iterators_past(__sz); traits_type::assign(__p[__sz], value_type()); } return *this; } template inline _LIBCPP_INLINE_VISIBILITY typename basic_string<_CharT, _Traits, _Allocator>::iterator basic_string<_CharT, _Traits, _Allocator>::erase(const_iterator __pos) { #if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__pos) == this, "string::erase(iterator) called with an iterator not" " referring to this string"); #endif _LIBCPP_ASSERT(__pos != end(), "string::erase(iterator) called with a non-dereferenceable iterator"); iterator __b = begin(); size_type __r = static_cast(__pos - __b); erase(__r, 1); return __b + static_cast(__r); } template inline _LIBCPP_INLINE_VISIBILITY typename basic_string<_CharT, _Traits, _Allocator>::iterator basic_string<_CharT, _Traits, _Allocator>::erase(const_iterator __first, const_iterator __last) { #if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__first) == this, "string::erase(iterator, iterator) called with an iterator not" " referring to this string"); #endif _LIBCPP_ASSERT(__first <= __last, "string::erase(first, last) called with invalid range"); iterator __b = begin(); size_type __r = static_cast(__first - __b); erase(__r, static_cast(__last - __first)); return __b + static_cast(__r); } template inline _LIBCPP_INLINE_VISIBILITY void basic_string<_CharT, _Traits, _Allocator>::pop_back() { _LIBCPP_ASSERT(!empty(), "string::pop_back(): string is already empty"); size_type __sz; if (__is_long()) { __sz = __get_long_size() - 1; __set_long_size(__sz); traits_type::assign(*(__get_long_pointer() + __sz), value_type()); } else { __sz = __get_short_size() - 1; __set_short_size(__sz); traits_type::assign(*(__get_short_pointer() + __sz), value_type()); } __invalidate_iterators_past(__sz); } template inline _LIBCPP_INLINE_VISIBILITY void basic_string<_CharT, _Traits, _Allocator>::clear() _NOEXCEPT { __invalidate_all_iterators(); if (__is_long()) { traits_type::assign(*__get_long_pointer(), value_type()); __set_long_size(0); } else { traits_type::assign(*__get_short_pointer(), value_type()); __set_short_size(0); } } template inline _LIBCPP_INLINE_VISIBILITY void basic_string<_CharT, _Traits, _Allocator>::__erase_to_end(size_type __pos) { if (__is_long()) { traits_type::assign(*(__get_long_pointer() + __pos), value_type()); __set_long_size(__pos); } else { traits_type::assign(*(__get_short_pointer() + __pos), value_type()); __set_short_size(__pos); } __invalidate_iterators_past(__pos); } template void basic_string<_CharT, _Traits, _Allocator>::resize(size_type __n, value_type __c) { size_type __sz = size(); if (__n > __sz) append(__n - __sz, __c); else __erase_to_end(__n); } template inline _LIBCPP_INLINE_VISIBILITY typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::max_size() const _NOEXCEPT { size_type __m = __alloc_traits::max_size(__alloc()); #if _LIBCPP_BIG_ENDIAN return (__m <= ~__long_mask ? __m : __m/2) - __alignment; #else return __m - __alignment; #endif } template void basic_string<_CharT, _Traits, _Allocator>::reserve(size_type __res_arg) { if (__res_arg > max_size()) this->__throw_length_error(); size_type __cap = capacity(); size_type __sz = size(); __res_arg = _VSTD::max(__res_arg, __sz); __res_arg = __recommend(__res_arg); if (__res_arg != __cap) { pointer __new_data, __p; bool __was_long, __now_long; if (__res_arg == __min_cap - 1) { __was_long = true; __now_long = false; __new_data = __get_short_pointer(); __p = __get_long_pointer(); } else { if (__res_arg > __cap) __new_data = __alloc_traits::allocate(__alloc(), __res_arg+1); else { #ifndef _LIBCPP_NO_EXCEPTIONS try { #endif // _LIBCPP_NO_EXCEPTIONS __new_data = __alloc_traits::allocate(__alloc(), __res_arg+1); #ifndef _LIBCPP_NO_EXCEPTIONS } catch (...) { return; } #else // _LIBCPP_NO_EXCEPTIONS if (__new_data == nullptr) return; #endif // _LIBCPP_NO_EXCEPTIONS } __now_long = true; __was_long = __is_long(); __p = __get_pointer(); } traits_type::copy(_VSTD::__to_raw_pointer(__new_data), _VSTD::__to_raw_pointer(__p), size()+1); if (__was_long) __alloc_traits::deallocate(__alloc(), __p, __cap+1); if (__now_long) { __set_long_cap(__res_arg+1); __set_long_size(__sz); __set_long_pointer(__new_data); } else __set_short_size(__sz); __invalidate_all_iterators(); } } template inline _LIBCPP_INLINE_VISIBILITY typename basic_string<_CharT, _Traits, _Allocator>::const_reference basic_string<_CharT, _Traits, _Allocator>::operator[](size_type __pos) const _NOEXCEPT { _LIBCPP_ASSERT(__pos <= size(), "string index out of bounds"); return *(data() + __pos); } template inline _LIBCPP_INLINE_VISIBILITY typename basic_string<_CharT, _Traits, _Allocator>::reference basic_string<_CharT, _Traits, _Allocator>::operator[](size_type __pos) _NOEXCEPT { _LIBCPP_ASSERT(__pos <= size(), "string index out of bounds"); return *(__get_pointer() + __pos); } template typename basic_string<_CharT, _Traits, _Allocator>::const_reference basic_string<_CharT, _Traits, _Allocator>::at(size_type __n) const { if (__n >= size()) this->__throw_out_of_range(); return (*this)[__n]; } template typename basic_string<_CharT, _Traits, _Allocator>::reference basic_string<_CharT, _Traits, _Allocator>::at(size_type __n) { if (__n >= size()) this->__throw_out_of_range(); return (*this)[__n]; } template inline _LIBCPP_INLINE_VISIBILITY typename basic_string<_CharT, _Traits, _Allocator>::reference basic_string<_CharT, _Traits, _Allocator>::front() { _LIBCPP_ASSERT(!empty(), "string::front(): string is empty"); return *__get_pointer(); } template inline _LIBCPP_INLINE_VISIBILITY typename basic_string<_CharT, _Traits, _Allocator>::const_reference basic_string<_CharT, _Traits, _Allocator>::front() const { _LIBCPP_ASSERT(!empty(), "string::front(): string is empty"); return *data(); } template inline _LIBCPP_INLINE_VISIBILITY typename basic_string<_CharT, _Traits, _Allocator>::reference basic_string<_CharT, _Traits, _Allocator>::back() { _LIBCPP_ASSERT(!empty(), "string::back(): string is empty"); return *(__get_pointer() + size() - 1); } template inline _LIBCPP_INLINE_VISIBILITY typename basic_string<_CharT, _Traits, _Allocator>::const_reference basic_string<_CharT, _Traits, _Allocator>::back() const { _LIBCPP_ASSERT(!empty(), "string::back(): string is empty"); return *(data() + size() - 1); } template typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::copy(value_type* __s, size_type __n, size_type __pos) const { size_type __sz = size(); if (__pos > __sz) this->__throw_out_of_range(); size_type __rlen = _VSTD::min(__n, __sz - __pos); traits_type::copy(__s, data() + __pos, __rlen); return __rlen; } template inline _LIBCPP_INLINE_VISIBILITY basic_string<_CharT, _Traits, _Allocator> basic_string<_CharT, _Traits, _Allocator>::substr(size_type __pos, size_type __n) const { return basic_string(*this, __pos, __n, __alloc()); } template inline _LIBCPP_INLINE_VISIBILITY void basic_string<_CharT, _Traits, _Allocator>::swap(basic_string& __str) #if _LIBCPP_STD_VER >= 14 _NOEXCEPT_DEBUG #else _NOEXCEPT_DEBUG_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable::value) #endif { #if _LIBCPP_DEBUG_LEVEL >= 2 if (!__is_long()) __get_db()->__invalidate_all(this); if (!__str.__is_long()) __get_db()->__invalidate_all(&__str); __get_db()->swap(this, &__str); #endif _LIBCPP_ASSERT( __alloc_traits::propagate_on_container_swap::value || __alloc_traits::is_always_equal::value || __alloc() == __str.__alloc(), "swapping non-equal allocators"); _VSTD::swap(__r_.first(), __str.__r_.first()); __swap_allocator(__alloc(), __str.__alloc()); } // find template struct _LIBCPP_HIDDEN __traits_eq { typedef typename _Traits::char_type char_type; _LIBCPP_INLINE_VISIBILITY bool operator()(const char_type& __x, const char_type& __y) _NOEXCEPT {return _Traits::eq(__x, __y);} }; template typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT { _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string::find(): received nullptr"); return __str_find (data(), size(), __s, __pos, __n); } template inline _LIBCPP_INLINE_VISIBILITY typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find(const basic_string& __str, size_type __pos) const _NOEXCEPT { return __str_find (data(), size(), __str.data(), __pos, __str.size()); } template inline _LIBCPP_INLINE_VISIBILITY typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find(__self_view __sv, size_type __pos) const _NOEXCEPT { return __str_find (data(), size(), __sv.data(), __pos, __sv.size()); } template inline _LIBCPP_INLINE_VISIBILITY typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find(const value_type* __s, size_type __pos) const _NOEXCEPT { _LIBCPP_ASSERT(__s != nullptr, "string::find(): received nullptr"); return __str_find (data(), size(), __s, __pos, traits_type::length(__s)); } template typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find(value_type __c, size_type __pos) const _NOEXCEPT { return __str_find (data(), size(), __c, __pos); } // rfind template typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::rfind(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT { _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string::rfind(): received nullptr"); return __str_rfind (data(), size(), __s, __pos, __n); } template inline _LIBCPP_INLINE_VISIBILITY typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::rfind(const basic_string& __str, size_type __pos) const _NOEXCEPT { return __str_rfind (data(), size(), __str.data(), __pos, __str.size()); } template inline _LIBCPP_INLINE_VISIBILITY typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::rfind(__self_view __sv, size_type __pos) const _NOEXCEPT { return __str_rfind (data(), size(), __sv.data(), __pos, __sv.size()); } template inline _LIBCPP_INLINE_VISIBILITY typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::rfind(const value_type* __s, size_type __pos) const _NOEXCEPT { _LIBCPP_ASSERT(__s != nullptr, "string::rfind(): received nullptr"); return __str_rfind (data(), size(), __s, __pos, traits_type::length(__s)); } template typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::rfind(value_type __c, size_type __pos) const _NOEXCEPT { return __str_rfind (data(), size(), __c, __pos); } // find_first_of template typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_first_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT { _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string::find_first_of(): received nullptr"); return __str_find_first_of (data(), size(), __s, __pos, __n); } template inline _LIBCPP_INLINE_VISIBILITY typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_first_of(const basic_string& __str, size_type __pos) const _NOEXCEPT { return __str_find_first_of (data(), size(), __str.data(), __pos, __str.size()); } template inline _LIBCPP_INLINE_VISIBILITY typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_first_of(__self_view __sv, size_type __pos) const _NOEXCEPT { return __str_find_first_of (data(), size(), __sv.data(), __pos, __sv.size()); } template inline _LIBCPP_INLINE_VISIBILITY typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_first_of(const value_type* __s, size_type __pos) const _NOEXCEPT { _LIBCPP_ASSERT(__s != nullptr, "string::find_first_of(): received nullptr"); return __str_find_first_of (data(), size(), __s, __pos, traits_type::length(__s)); } template inline _LIBCPP_INLINE_VISIBILITY typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_first_of(value_type __c, size_type __pos) const _NOEXCEPT { return find(__c, __pos); } // find_last_of template typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_last_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT { _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string::find_last_of(): received nullptr"); return __str_find_last_of (data(), size(), __s, __pos, __n); } template inline _LIBCPP_INLINE_VISIBILITY typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_last_of(const basic_string& __str, size_type __pos) const _NOEXCEPT { return __str_find_last_of (data(), size(), __str.data(), __pos, __str.size()); } template inline _LIBCPP_INLINE_VISIBILITY typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_last_of(__self_view __sv, size_type __pos) const _NOEXCEPT { return __str_find_last_of (data(), size(), __sv.data(), __pos, __sv.size()); } template inline _LIBCPP_INLINE_VISIBILITY typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_last_of(const value_type* __s, size_type __pos) const _NOEXCEPT { _LIBCPP_ASSERT(__s != nullptr, "string::find_last_of(): received nullptr"); return __str_find_last_of (data(), size(), __s, __pos, traits_type::length(__s)); } template inline _LIBCPP_INLINE_VISIBILITY typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_last_of(value_type __c, size_type __pos) const _NOEXCEPT { return rfind(__c, __pos); } // find_first_not_of template typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_first_not_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT { _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string::find_first_not_of(): received nullptr"); return __str_find_first_not_of (data(), size(), __s, __pos, __n); } template inline _LIBCPP_INLINE_VISIBILITY typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_first_not_of(const basic_string& __str, size_type __pos) const _NOEXCEPT { return __str_find_first_not_of (data(), size(), __str.data(), __pos, __str.size()); } template inline _LIBCPP_INLINE_VISIBILITY typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_first_not_of(__self_view __sv, size_type __pos) const _NOEXCEPT { return __str_find_first_not_of (data(), size(), __sv.data(), __pos, __sv.size()); } template inline _LIBCPP_INLINE_VISIBILITY typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_first_not_of(const value_type* __s, size_type __pos) const _NOEXCEPT { _LIBCPP_ASSERT(__s != nullptr, "string::find_first_not_of(): received nullptr"); return __str_find_first_not_of (data(), size(), __s, __pos, traits_type::length(__s)); } template inline _LIBCPP_INLINE_VISIBILITY typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_first_not_of(value_type __c, size_type __pos) const _NOEXCEPT { return __str_find_first_not_of (data(), size(), __c, __pos); } // find_last_not_of template typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_last_not_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT { _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string::find_last_not_of(): received nullptr"); return __str_find_last_not_of (data(), size(), __s, __pos, __n); } template inline _LIBCPP_INLINE_VISIBILITY typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_last_not_of(const basic_string& __str, size_type __pos) const _NOEXCEPT { return __str_find_last_not_of (data(), size(), __str.data(), __pos, __str.size()); } template inline _LIBCPP_INLINE_VISIBILITY typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_last_not_of(__self_view __sv, size_type __pos) const _NOEXCEPT { return __str_find_last_not_of (data(), size(), __sv.data(), __pos, __sv.size()); } template inline _LIBCPP_INLINE_VISIBILITY typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_last_not_of(const value_type* __s, size_type __pos) const _NOEXCEPT { _LIBCPP_ASSERT(__s != nullptr, "string::find_last_not_of(): received nullptr"); return __str_find_last_not_of (data(), size(), __s, __pos, traits_type::length(__s)); } template inline _LIBCPP_INLINE_VISIBILITY typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_last_not_of(value_type __c, size_type __pos) const _NOEXCEPT { return __str_find_last_not_of (data(), size(), __c, __pos); } // compare template inline _LIBCPP_INLINE_VISIBILITY int basic_string<_CharT, _Traits, _Allocator>::compare(__self_view __sv) const _NOEXCEPT { size_t __lhs_sz = size(); size_t __rhs_sz = __sv.size(); int __result = traits_type::compare(data(), __sv.data(), _VSTD::min(__lhs_sz, __rhs_sz)); if (__result != 0) return __result; if (__lhs_sz < __rhs_sz) return -1; if (__lhs_sz > __rhs_sz) return 1; return 0; } template inline _LIBCPP_INLINE_VISIBILITY int basic_string<_CharT, _Traits, _Allocator>::compare(const basic_string& __str) const _NOEXCEPT { return compare(__self_view(__str)); } template int basic_string<_CharT, _Traits, _Allocator>::compare(size_type __pos1, size_type __n1, const value_type* __s, size_type __n2) const { _LIBCPP_ASSERT(__n2 == 0 || __s != nullptr, "string::compare(): received nullptr"); size_type __sz = size(); if (__pos1 > __sz || __n2 == npos) this->__throw_out_of_range(); size_type __rlen = _VSTD::min(__n1, __sz - __pos1); int __r = traits_type::compare(data() + __pos1, __s, _VSTD::min(__rlen, __n2)); if (__r == 0) { if (__rlen < __n2) __r = -1; else if (__rlen > __n2) __r = 1; } return __r; } template inline _LIBCPP_INLINE_VISIBILITY int basic_string<_CharT, _Traits, _Allocator>::compare(size_type __pos1, size_type __n1, __self_view __sv) const { return compare(__pos1, __n1, __sv.data(), __sv.size()); } template inline _LIBCPP_INLINE_VISIBILITY int basic_string<_CharT, _Traits, _Allocator>::compare(size_type __pos1, size_type __n1, const basic_string& __str) const { return compare(__pos1, __n1, __str.data(), __str.size()); } template template typename enable_if < __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int >::type basic_string<_CharT, _Traits, _Allocator>::compare(size_type __pos1, size_type __n1, const _Tp& __t, size_type __pos2, size_type __n2) const { __self_view __sv = __t; return __self_view(*this).substr(__pos1, __n1).compare(__sv.substr(__pos2, __n2)); } template int basic_string<_CharT, _Traits, _Allocator>::compare(size_type __pos1, size_type __n1, const basic_string& __str, size_type __pos2, size_type __n2) const { return compare(__pos1, __n1, __self_view(__str), __pos2, __n2); } template int basic_string<_CharT, _Traits, _Allocator>::compare(const value_type* __s) const _NOEXCEPT { _LIBCPP_ASSERT(__s != nullptr, "string::compare(): received nullptr"); return compare(0, npos, __s, traits_type::length(__s)); } template int basic_string<_CharT, _Traits, _Allocator>::compare(size_type __pos1, size_type __n1, const value_type* __s) const { _LIBCPP_ASSERT(__s != nullptr, "string::compare(): received nullptr"); return compare(__pos1, __n1, __s, traits_type::length(__s)); } // __invariants template inline _LIBCPP_INLINE_VISIBILITY bool basic_string<_CharT, _Traits, _Allocator>::__invariants() const { if (size() > capacity()) return false; if (capacity() < __min_cap - 1) return false; if (data() == 0) return false; if (data()[size()] != value_type(0)) return false; return true; } // operator== template inline _LIBCPP_INLINE_VISIBILITY bool operator==(const basic_string<_CharT, _Traits, _Allocator>& __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT { size_t __lhs_sz = __lhs.size(); return __lhs_sz == __rhs.size() && _Traits::compare(__lhs.data(), __rhs.data(), __lhs_sz) == 0; } template inline _LIBCPP_INLINE_VISIBILITY bool operator==(const basic_string, _Allocator>& __lhs, const basic_string, _Allocator>& __rhs) _NOEXCEPT { size_t __lhs_sz = __lhs.size(); if (__lhs_sz != __rhs.size()) return false; const char* __lp = __lhs.data(); const char* __rp = __rhs.data(); if (__lhs.__is_long()) return char_traits::compare(__lp, __rp, __lhs_sz) == 0; for (; __lhs_sz != 0; --__lhs_sz, ++__lp, ++__rp) if (*__lp != *__rp) return false; return true; } template inline _LIBCPP_INLINE_VISIBILITY bool operator==(const _CharT* __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT { typedef basic_string<_CharT, _Traits, _Allocator> _String; _LIBCPP_ASSERT(__lhs != nullptr, "operator==(char*, basic_string): received nullptr"); size_t __lhs_len = _Traits::length(__lhs); if (__lhs_len != __rhs.size()) return false; return __rhs.compare(0, _String::npos, __lhs, __lhs_len) == 0; } template inline _LIBCPP_INLINE_VISIBILITY bool operator==(const basic_string<_CharT,_Traits,_Allocator>& __lhs, const _CharT* __rhs) _NOEXCEPT { typedef basic_string<_CharT, _Traits, _Allocator> _String; _LIBCPP_ASSERT(__rhs != nullptr, "operator==(basic_string, char*): received nullptr"); size_t __rhs_len = _Traits::length(__rhs); if (__rhs_len != __lhs.size()) return false; return __lhs.compare(0, _String::npos, __rhs, __rhs_len) == 0; } template inline _LIBCPP_INLINE_VISIBILITY bool operator!=(const basic_string<_CharT,_Traits,_Allocator>& __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT { return !(__lhs == __rhs); } template inline _LIBCPP_INLINE_VISIBILITY bool operator!=(const _CharT* __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT { return !(__lhs == __rhs); } template inline _LIBCPP_INLINE_VISIBILITY bool operator!=(const basic_string<_CharT, _Traits, _Allocator>& __lhs, const _CharT* __rhs) _NOEXCEPT { return !(__lhs == __rhs); } // operator< template inline _LIBCPP_INLINE_VISIBILITY bool operator< (const basic_string<_CharT, _Traits, _Allocator>& __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT { return __lhs.compare(__rhs) < 0; } template inline _LIBCPP_INLINE_VISIBILITY bool operator< (const basic_string<_CharT, _Traits, _Allocator>& __lhs, const _CharT* __rhs) _NOEXCEPT { return __lhs.compare(__rhs) < 0; } template inline _LIBCPP_INLINE_VISIBILITY bool operator< (const _CharT* __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT { return __rhs.compare(__lhs) > 0; } // operator> template inline _LIBCPP_INLINE_VISIBILITY bool operator> (const basic_string<_CharT, _Traits, _Allocator>& __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT { return __rhs < __lhs; } template inline _LIBCPP_INLINE_VISIBILITY bool operator> (const basic_string<_CharT, _Traits, _Allocator>& __lhs, const _CharT* __rhs) _NOEXCEPT { return __rhs < __lhs; } template inline _LIBCPP_INLINE_VISIBILITY bool operator> (const _CharT* __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT { return __rhs < __lhs; } // operator<= template inline _LIBCPP_INLINE_VISIBILITY bool operator<=(const basic_string<_CharT, _Traits, _Allocator>& __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT { return !(__rhs < __lhs); } template inline _LIBCPP_INLINE_VISIBILITY bool operator<=(const basic_string<_CharT, _Traits, _Allocator>& __lhs, const _CharT* __rhs) _NOEXCEPT { return !(__rhs < __lhs); } template inline _LIBCPP_INLINE_VISIBILITY bool operator<=(const _CharT* __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT { return !(__rhs < __lhs); } // operator>= template inline _LIBCPP_INLINE_VISIBILITY bool operator>=(const basic_string<_CharT, _Traits, _Allocator>& __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT { return !(__lhs < __rhs); } template inline _LIBCPP_INLINE_VISIBILITY bool operator>=(const basic_string<_CharT, _Traits, _Allocator>& __lhs, const _CharT* __rhs) _NOEXCEPT { return !(__lhs < __rhs); } template inline _LIBCPP_INLINE_VISIBILITY bool operator>=(const _CharT* __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT { return !(__lhs < __rhs); } // operator + template basic_string<_CharT, _Traits, _Allocator> operator+(const basic_string<_CharT, _Traits, _Allocator>& __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs) { basic_string<_CharT, _Traits, _Allocator> __r(__lhs.get_allocator()); typename basic_string<_CharT, _Traits, _Allocator>::size_type __lhs_sz = __lhs.size(); typename basic_string<_CharT, _Traits, _Allocator>::size_type __rhs_sz = __rhs.size(); __r.__init(__lhs.data(), __lhs_sz, __lhs_sz + __rhs_sz); __r.append(__rhs.data(), __rhs_sz); return __r; } template basic_string<_CharT, _Traits, _Allocator> operator+(const _CharT* __lhs , const basic_string<_CharT,_Traits,_Allocator>& __rhs) { basic_string<_CharT, _Traits, _Allocator> __r(__rhs.get_allocator()); typename basic_string<_CharT, _Traits, _Allocator>::size_type __lhs_sz = _Traits::length(__lhs); typename basic_string<_CharT, _Traits, _Allocator>::size_type __rhs_sz = __rhs.size(); __r.__init(__lhs, __lhs_sz, __lhs_sz + __rhs_sz); __r.append(__rhs.data(), __rhs_sz); return __r; } template basic_string<_CharT, _Traits, _Allocator> operator+(_CharT __lhs, const basic_string<_CharT,_Traits,_Allocator>& __rhs) { basic_string<_CharT, _Traits, _Allocator> __r(__rhs.get_allocator()); typename basic_string<_CharT, _Traits, _Allocator>::size_type __rhs_sz = __rhs.size(); __r.__init(&__lhs, 1, 1 + __rhs_sz); __r.append(__rhs.data(), __rhs_sz); return __r; } template basic_string<_CharT, _Traits, _Allocator> operator+(const basic_string<_CharT, _Traits, _Allocator>& __lhs, const _CharT* __rhs) { basic_string<_CharT, _Traits, _Allocator> __r(__lhs.get_allocator()); typename basic_string<_CharT, _Traits, _Allocator>::size_type __lhs_sz = __lhs.size(); typename basic_string<_CharT, _Traits, _Allocator>::size_type __rhs_sz = _Traits::length(__rhs); __r.__init(__lhs.data(), __lhs_sz, __lhs_sz + __rhs_sz); __r.append(__rhs, __rhs_sz); return __r; } template basic_string<_CharT, _Traits, _Allocator> operator+(const basic_string<_CharT, _Traits, _Allocator>& __lhs, _CharT __rhs) { basic_string<_CharT, _Traits, _Allocator> __r(__lhs.get_allocator()); typename basic_string<_CharT, _Traits, _Allocator>::size_type __lhs_sz = __lhs.size(); __r.__init(__lhs.data(), __lhs_sz, __lhs_sz + 1); __r.push_back(__rhs); return __r; } #ifndef _LIBCPP_CXX03_LANG template inline _LIBCPP_INLINE_VISIBILITY basic_string<_CharT, _Traits, _Allocator> operator+(basic_string<_CharT, _Traits, _Allocator>&& __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs) { return _VSTD::move(__lhs.append(__rhs)); } template inline _LIBCPP_INLINE_VISIBILITY basic_string<_CharT, _Traits, _Allocator> operator+(const basic_string<_CharT, _Traits, _Allocator>& __lhs, basic_string<_CharT, _Traits, _Allocator>&& __rhs) { return _VSTD::move(__rhs.insert(0, __lhs)); } template inline _LIBCPP_INLINE_VISIBILITY basic_string<_CharT, _Traits, _Allocator> operator+(basic_string<_CharT, _Traits, _Allocator>&& __lhs, basic_string<_CharT, _Traits, _Allocator>&& __rhs) { return _VSTD::move(__lhs.append(__rhs)); } template inline _LIBCPP_INLINE_VISIBILITY basic_string<_CharT, _Traits, _Allocator> operator+(const _CharT* __lhs , basic_string<_CharT,_Traits,_Allocator>&& __rhs) { return _VSTD::move(__rhs.insert(0, __lhs)); } template inline _LIBCPP_INLINE_VISIBILITY basic_string<_CharT, _Traits, _Allocator> operator+(_CharT __lhs, basic_string<_CharT,_Traits,_Allocator>&& __rhs) { __rhs.insert(__rhs.begin(), __lhs); return _VSTD::move(__rhs); } template inline _LIBCPP_INLINE_VISIBILITY basic_string<_CharT, _Traits, _Allocator> operator+(basic_string<_CharT, _Traits, _Allocator>&& __lhs, const _CharT* __rhs) { return _VSTD::move(__lhs.append(__rhs)); } template inline _LIBCPP_INLINE_VISIBILITY basic_string<_CharT, _Traits, _Allocator> operator+(basic_string<_CharT, _Traits, _Allocator>&& __lhs, _CharT __rhs) { __lhs.push_back(__rhs); return _VSTD::move(__lhs); } #endif // _LIBCPP_CXX03_LANG // swap template inline _LIBCPP_INLINE_VISIBILITY void swap(basic_string<_CharT, _Traits, _Allocator>& __lhs, basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT_(_NOEXCEPT_(__lhs.swap(__rhs))) { __lhs.swap(__rhs); } #ifndef _LIBCPP_HAS_NO_UNICODE_CHARS typedef basic_string u16string; typedef basic_string u32string; #endif // _LIBCPP_HAS_NO_UNICODE_CHARS _LIBCPP_FUNC_VIS int stoi (const string& __str, size_t* __idx = 0, int __base = 10); _LIBCPP_FUNC_VIS long stol (const string& __str, size_t* __idx = 0, int __base = 10); _LIBCPP_FUNC_VIS unsigned long stoul (const string& __str, size_t* __idx = 0, int __base = 10); _LIBCPP_FUNC_VIS long long stoll (const string& __str, size_t* __idx = 0, int __base = 10); _LIBCPP_FUNC_VIS unsigned long long stoull(const string& __str, size_t* __idx = 0, int __base = 10); _LIBCPP_FUNC_VIS float stof (const string& __str, size_t* __idx = 0); _LIBCPP_FUNC_VIS double stod (const string& __str, size_t* __idx = 0); _LIBCPP_FUNC_VIS long double stold(const string& __str, size_t* __idx = 0); _LIBCPP_FUNC_VIS string to_string(int __val); _LIBCPP_FUNC_VIS string to_string(unsigned __val); _LIBCPP_FUNC_VIS string to_string(long __val); _LIBCPP_FUNC_VIS string to_string(unsigned long __val); _LIBCPP_FUNC_VIS string to_string(long long __val); _LIBCPP_FUNC_VIS string to_string(unsigned long long __val); _LIBCPP_FUNC_VIS string to_string(float __val); _LIBCPP_FUNC_VIS string to_string(double __val); _LIBCPP_FUNC_VIS string to_string(long double __val); _LIBCPP_FUNC_VIS int stoi (const wstring& __str, size_t* __idx = 0, int __base = 10); _LIBCPP_FUNC_VIS long stol (const wstring& __str, size_t* __idx = 0, int __base = 10); _LIBCPP_FUNC_VIS unsigned long stoul (const wstring& __str, size_t* __idx = 0, int __base = 10); _LIBCPP_FUNC_VIS long long stoll (const wstring& __str, size_t* __idx = 0, int __base = 10); _LIBCPP_FUNC_VIS unsigned long long stoull(const wstring& __str, size_t* __idx = 0, int __base = 10); _LIBCPP_FUNC_VIS float stof (const wstring& __str, size_t* __idx = 0); _LIBCPP_FUNC_VIS double stod (const wstring& __str, size_t* __idx = 0); _LIBCPP_FUNC_VIS long double stold(const wstring& __str, size_t* __idx = 0); _LIBCPP_FUNC_VIS wstring to_wstring(int __val); _LIBCPP_FUNC_VIS wstring to_wstring(unsigned __val); _LIBCPP_FUNC_VIS wstring to_wstring(long __val); _LIBCPP_FUNC_VIS wstring to_wstring(unsigned long __val); _LIBCPP_FUNC_VIS wstring to_wstring(long long __val); _LIBCPP_FUNC_VIS wstring to_wstring(unsigned long long __val); _LIBCPP_FUNC_VIS wstring to_wstring(float __val); _LIBCPP_FUNC_VIS wstring to_wstring(double __val); _LIBCPP_FUNC_VIS wstring to_wstring(long double __val); template const typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::npos; template struct _LIBCPP_TEMPLATE_VIS hash > : public unary_function, size_t> { size_t operator()(const basic_string<_CharT, _Traits, _Allocator>& __val) const _NOEXCEPT; }; template size_t hash >::operator()( const basic_string<_CharT, _Traits, _Allocator>& __val) const _NOEXCEPT { return __do_string_hash(__val.data(), __val.data() + __val.size()); } template basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& __os, const basic_string<_CharT, _Traits, _Allocator>& __str); template basic_istream<_CharT, _Traits>& operator>>(basic_istream<_CharT, _Traits>& __is, basic_string<_CharT, _Traits, _Allocator>& __str); template basic_istream<_CharT, _Traits>& getline(basic_istream<_CharT, _Traits>& __is, basic_string<_CharT, _Traits, _Allocator>& __str, _CharT __dlm); template inline _LIBCPP_INLINE_VISIBILITY basic_istream<_CharT, _Traits>& getline(basic_istream<_CharT, _Traits>& __is, basic_string<_CharT, _Traits, _Allocator>& __str); #ifndef _LIBCPP_CXX03_LANG template inline _LIBCPP_INLINE_VISIBILITY basic_istream<_CharT, _Traits>& getline(basic_istream<_CharT, _Traits>&& __is, basic_string<_CharT, _Traits, _Allocator>& __str, _CharT __dlm); template inline _LIBCPP_INLINE_VISIBILITY basic_istream<_CharT, _Traits>& getline(basic_istream<_CharT, _Traits>&& __is, basic_string<_CharT, _Traits, _Allocator>& __str); #endif // _LIBCPP_CXX03_LANG #if _LIBCPP_DEBUG_LEVEL >= 2 template bool basic_string<_CharT, _Traits, _Allocator>::__dereferenceable(const const_iterator* __i) const { return this->data() <= _VSTD::__to_raw_pointer(__i->base()) && _VSTD::__to_raw_pointer(__i->base()) < this->data() + this->size(); } template bool basic_string<_CharT, _Traits, _Allocator>::__decrementable(const const_iterator* __i) const { return this->data() < _VSTD::__to_raw_pointer(__i->base()) && _VSTD::__to_raw_pointer(__i->base()) <= this->data() + this->size(); } template bool basic_string<_CharT, _Traits, _Allocator>::__addable(const const_iterator* __i, ptrdiff_t __n) const { const value_type* __p = _VSTD::__to_raw_pointer(__i->base()) + __n; return this->data() <= __p && __p <= this->data() + this->size(); } template bool basic_string<_CharT, _Traits, _Allocator>::__subscriptable(const const_iterator* __i, ptrdiff_t __n) const { const value_type* __p = _VSTD::__to_raw_pointer(__i->base()) + __n; return this->data() <= __p && __p < this->data() + this->size(); } #endif // _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS basic_string) _LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS basic_string) _LIBCPP_EXTERN_TEMPLATE(string operator+, allocator >(char const*, string const&)) #if _LIBCPP_STD_VER > 11 // Literal suffixes for basic_string [basic.string.literals] inline namespace literals { inline namespace string_literals { inline _LIBCPP_INLINE_VISIBILITY basic_string operator "" s( const char *__str, size_t __len ) { return basic_string (__str, __len); } inline _LIBCPP_INLINE_VISIBILITY basic_string operator "" s( const wchar_t *__str, size_t __len ) { return basic_string (__str, __len); } inline _LIBCPP_INLINE_VISIBILITY basic_string operator "" s( const char16_t *__str, size_t __len ) { return basic_string (__str, __len); } inline _LIBCPP_INLINE_VISIBILITY basic_string operator "" s( const char32_t *__str, size_t __len ) { return basic_string (__str, __len); } } } #endif _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS #endif // _LIBCPP_STRING diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index f04ef82a83d6..9fc0d1394336 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -1,391 +1,391 @@ set(LIBCXX_LIB_CMAKEFILES_DIR "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}" PARENT_SCOPE) # Get sources # FIXME: Don't use glob here file(GLOB LIBCXX_SOURCES ../src/*.cpp) if(WIN32) file(GLOB LIBCXX_WIN32_SOURCES ../src/support/win32/*.cpp) list(APPEND LIBCXX_SOURCES ${LIBCXX_WIN32_SOURCES}) elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "SunOS") file(GLOB LIBCXX_SOLARIS_SOURCES ../src/support/solaris/*.cpp) list(APPEND LIBCXX_SOURCES ${LIBCXX_SOLARIS_SOURCES}) endif() # Add all the headers to the project for IDEs. if (LIBCXX_CONFIGURE_IDE) file(GLOB_RECURSE LIBCXX_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/../include/*) if(WIN32) file( GLOB LIBCXX_WIN32_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/../include/support/win32/*.h) list(APPEND LIBCXX_HEADERS ${LIBCXX_WIN32_HEADERS}) endif() # Force them all into the headers dir on MSVC, otherwise they end up at # project scope because they don't have extensions. if (MSVC_IDE) source_group("Header Files" FILES ${LIBCXX_HEADERS}) endif() endif() if(NOT LIBCXX_INSTALL_LIBRARY) set(exclude_from_all EXCLUDE_FROM_ALL) endif() # If LIBCXX_CXX_ABI_LIBRARY_PATH is defined we want to add it to the search path. add_link_flags_if(LIBCXX_CXX_ABI_LIBRARY_PATH "${CMAKE_LIBRARY_PATH_FLAG}${LIBCXX_CXX_ABI_LIBRARY_PATH}") if (LIBCXX_GENERATE_COVERAGE AND NOT LIBCXX_COVERAGE_LIBRARY) find_compiler_rt_library(profile LIBCXX_COVERAGE_LIBRARY) endif() add_library_flags_if(LIBCXX_COVERAGE_LIBRARY "${LIBCXX_COVERAGE_LIBRARY}") if (APPLE AND (LIBCXX_CXX_ABI_LIBNAME STREQUAL "libcxxabi" OR LIBCXX_CXX_ABI_LIBNAME STREQUAL "default")) set(LIBCXX_OSX_REEXPORT_SYSTEM_ABI_LIBRARY ON) endif() if (LIBCXX_ENABLE_STATIC_ABI_LIBRARY) add_library_flags("-Wl,--whole-archive" "-Wl,-Bstatic") add_library_flags("${LIBCXX_CXX_ABI_LIBRARY}") add_library_flags("-Wl,-Bdynamic" "-Wl,--no-whole-archive") elseif (LIBCXX_OSX_REEXPORT_SYSTEM_ABI_LIBRARY) add_library_flags("${LIBCXX_CXX_ABI_LIBRARY}") else () add_interface_library("${LIBCXX_CXX_ABI_LIBRARY}") endif() if (APPLE AND LLVM_USE_SANITIZER) if (("${LLVM_USE_SANITIZER}" STREQUAL "Address") OR ("${LLVM_USE_SANITIZER}" STREQUAL "Address;Undefined") OR ("${LLVM_USE_SANITIZER}" STREQUAL "Undefined;Address")) set(LIBFILE "libclang_rt.asan_osx_dynamic.dylib") elseif("${LLVM_USE_SANITIZER}" STREQUAL "Undefined") set(LIBFILE "libclang_rt.ubsan_osx_dynamic.dylib") elseif("${LLVM_USE_SANITIZER}" STREQUAL "Thread") set(LIBFILE "libclang_rt.tsan_osx_dynamic.dylib") else() message(WARNING "LLVM_USE_SANITIZER=${LLVM_USE_SANITIZER} is not supported on OS X") endif() if (LIBFILE) find_compiler_rt_dir(LIBDIR) if (NOT IS_DIRECTORY "${LIBDIR}") message(FATAL_ERROR "Cannot find compiler-rt directory on OS X required for LLVM_USE_SANITIZER") endif() set(LIBCXX_SANITIZER_LIBRARY "${LIBDIR}/${LIBFILE}") set(LIBCXX_SANITIZER_LIBRARY "${LIBCXX_SANITIZER_LIBRARY}" PARENT_SCOPE) message(STATUS "Manually linking compiler-rt library: ${LIBCXX_SANITIZER_LIBRARY}") add_library_flags("${LIBCXX_SANITIZER_LIBRARY}") add_link_flags("-Wl,-rpath,${LIBDIR}") endif() endif() # Generate private library list. add_library_flags_if(LIBCXX_HAS_PTHREAD_LIB pthread) add_library_flags_if(LIBCXX_HAS_C_LIB c) add_library_flags_if(LIBCXX_HAS_M_LIB m) add_library_flags_if(LIBCXX_HAS_RT_LIB rt) if (LIBCXX_USE_COMPILER_RT) find_compiler_rt_library(builtins LIBCXX_BUILTINS_LIBRARY) add_library_flags_if(LIBCXX_BUILTINS_LIBRARY "${LIBCXX_BUILTINS_LIBRARY}") else() add_library_flags_if(LIBCXX_HAS_GCC_S_LIB gcc_s) endif() add_library_flags_if(LIBCXX_HAVE_CXX_ATOMICS_WITH_LIB atomic) # Add the unwinder library. if (LIBCXXABI_USE_LLVM_UNWINDER) if (NOT LIBCXXABI_ENABLE_STATIC_UNWINDER AND (TARGET unwind_shared OR HAVE_LIBUNWIND)) add_interface_library(unwind_shared) elseif (LIBCXXABI_ENABLE_STATIC_UNWINDER AND (TARGET unwind_static OR HAVE_LIBUNWIND)) add_interface_library(unwind_static) else() add_interface_library(unwind) endif() endif() # Setup flags. if (NOT WIN32) add_flags_if_supported(-fPIC) endif() add_link_flags_if_supported(-nodefaultlibs) if (LIBCXX_TARGETING_MSVC) if (LIBCXX_DEBUG_BUILD) set(LIB_SUFFIX "d") else() set(LIB_SUFFIX "") endif() add_compile_flags(/Zl) add_link_flags(/nodefaultlib) add_library_flags(ucrt${LIB_SUFFIX}) # Universal C runtime add_library_flags(vcruntime${LIB_SUFFIX}) # C++ runtime add_library_flags(msvcrt${LIB_SUFFIX}) # C runtime startup files add_library_flags(msvcprt${LIB_SUFFIX}) # C++ standard library. Required for exception_ptr internals. # Required for standards-complaint wide character formatting functions # (e.g. `printfw`/`scanfw`) add_library_flags(iso_stdio_wide_specifiers) endif() if (LIBCXX_OSX_REEXPORT_SYSTEM_ABI_LIBRARY) if (NOT DEFINED LIBCXX_LIBCPPABI_VERSION) set(LIBCXX_LIBCPPABI_VERSION "2") # Default value execute_process( COMMAND xcrun --show-sdk-version OUTPUT_VARIABLE sdk_ver RESULT_VARIABLE res OUTPUT_STRIP_TRAILING_WHITESPACE) if (res EQUAL 0) message(STATUS "Found SDK version ${sdk_ver}") string(REPLACE "10." "" sdk_ver "${sdk_ver}") if (sdk_ver LESS 9) set(LIBCXX_LIBCPPABI_VERSION "") else() set(LIBCXX_LIBCPPABI_VERSION "2") endif() endif() endif() if ( CMAKE_OSX_DEPLOYMENT_TARGET STREQUAL "10.6" ) add_definitions(-D__STRICT_ANSI__) add_link_flags( "-compatibility_version 1" "-current_version 1" "-install_name /usr/lib/libc++.1.dylib" "-Wl,-reexport_library,/usr/lib/libc++abi.dylib" "-Wl,-unexported_symbols_list,${CMAKE_CURRENT_SOURCE_DIR}/libc++unexp.exp" "/usr/lib/libSystem.B.dylib") else() if (DEFINED CMAKE_OSX_SYSROOT AND NOT CMAKE_OSX_SYSROOT STREQUAL "") list(FIND CMAKE_OSX_ARCHITECTURES "armv7" OSX_HAS_ARMV7) if (NOT OSX_HAS_ARMV7 EQUAL -1) set(OSX_RE_EXPORT_LINE "${CMAKE_OSX_SYSROOT}/usr/lib/libc++abi.dylib" "-Wl,-reexported_symbols_list,${CMAKE_CURRENT_SOURCE_DIR}/libc++sjlj-abi.exp") else() set(OSX_RE_EXPORT_LINE "-Wl,-reexport_library,${CMAKE_OSX_SYSROOT}/usr/lib/libc++abi.dylib") endif() else() set(OSX_RE_EXPORT_LINE "/usr/lib/libc++abi.dylib -Wl,-reexported_symbols_list,${CMAKE_CURRENT_SOURCE_DIR}/libc++abi${LIBCXX_LIBCPPABI_VERSION}.exp") if (NOT LIBCXX_ENABLE_NEW_DELETE_DEFINITIONS) add_link_flags("/usr/lib/libc++abi.dylib -Wl,-reexported_symbols_list,${CMAKE_CURRENT_SOURCE_DIR}/libc++abi-new-delete.exp") endif() endif() add_link_flags( "-compatibility_version 1" "-install_name /usr/lib/libc++.1.dylib" "-Wl,-unexported_symbols_list,${CMAKE_CURRENT_SOURCE_DIR}/libc++unexp.exp" "${OSX_RE_EXPORT_LINE}" "-Wl,-force_symbols_not_weak_list,${CMAKE_CURRENT_SOURCE_DIR}/notweak.exp" "-Wl,-force_symbols_weak_list,${CMAKE_CURRENT_SOURCE_DIR}/weak.exp") endif() endif() split_list(LIBCXX_COMPILE_FLAGS) split_list(LIBCXX_LINK_FLAGS) # Add an object library that contains the compiled source files. add_library(cxx_objects OBJECT ${exclude_from_all} ${LIBCXX_SOURCES} ${LIBCXX_HEADERS}) if(WIN32 AND NOT MINGW) target_compile_definitions(cxx_objects PRIVATE # Ignore the -MSC_VER mismatch, as we may build # with a different compatibility version. _ALLOW_MSC_VER_MISMATCH # Don't check the msvcprt iterator debug levels # as we will define the iterator types; libc++ # uses a different macro to identify the debug # level. _ALLOW_ITERATOR_DEBUG_LEVEL_MISMATCH # We are building the c++ runtime, don't pull in # msvcprt. _CRTBLD # Don't warn on the use of "deprecated" # "insecure" functions which are standards # specified. _CRT_SECURE_NO_WARNINGS # Use the ISO conforming behaviour for conversion # in printf, scanf. _CRT_STDIO_ISO_WIDE_SPECIFIERS) endif() set_target_properties(cxx_objects PROPERTIES COMPILE_FLAGS "${LIBCXX_COMPILE_FLAGS}" ) set(LIBCXX_TARGETS) # Build the shared library. if (LIBCXX_ENABLE_SHARED) add_library(cxx_shared SHARED $) target_link_libraries(cxx_shared ${LIBCXX_LIBRARIES}) set_target_properties(cxx_shared PROPERTIES LINK_FLAGS "${LIBCXX_LINK_FLAGS}" OUTPUT_NAME "c++" VERSION "${LIBCXX_ABI_VERSION}.0" SOVERSION "${LIBCXX_ABI_VERSION}" ) list(APPEND LIBCXX_TARGETS "cxx_shared") if(WIN32 AND NOT MINGW AND NOT "${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Windows") # Since we most likely do not have a mt.exe replacement, disable the # manifest bundling. This allows a normal cmake invocation to pass which # will attempt to use the manifest tool to generate the bundled manifest set_target_properties(cxx_shared PROPERTIES APPEND_STRING PROPERTY LINK_FLAGS " /MANIFEST:NO") endif() endif() # Build the static library. if (LIBCXX_ENABLE_STATIC) add_library(cxx_static STATIC $) target_link_libraries(cxx_static ${LIBCXX_LIBRARIES}) set(CMAKE_STATIC_LIBRARY_PREFIX "lib") set_target_properties(cxx_static PROPERTIES LINK_FLAGS "${LIBCXX_LINK_FLAGS}" OUTPUT_NAME "c++" ) list(APPEND LIBCXX_TARGETS "cxx_static") # Attempt to merge the libc++.a archive and the ABI library archive into one. if (LIBCXX_ENABLE_STATIC_ABI_LIBRARY) set(MERGE_ARCHIVES_SEARCH_PATHS "") if (LIBCXX_CXX_ABI_LIBRARY_PATH) set(MERGE_ARCHIVES_SEARCH_PATHS "-L${LIBCXX_CXX_ABI_LIBRARY_PATH}") endif() if ((TARGET ${LIBCXX_CXX_ABI_LIBRARY}) OR (${LIBCXX_CXX_ABI_LIBRARY} STREQUAL "cxxabi(_static|_shared)?" AND HAVE_LIBCXXABI)) set(MERGE_ARCHIVES_ABI_TARGET "$") else() set(MERGE_ARCHIVES_ABI_TARGET "${CMAKE_STATIC_LIBRARY_PREFIX}${LIBCXX_CXX_ABI_LIBRARY}${CMAKE_STATIC_LIBRARY_SUFFIX}") endif() add_custom_command(TARGET cxx_static POST_BUILD COMMAND ${PYTHON_EXECUTABLE} ${LIBCXX_SOURCE_DIR}/utils/merge_archives.py ARGS -o $ "$" "${MERGE_ARCHIVES_ABI_TARGET}" "${MERGE_ARCHIVES_SEARCH_PATHS}" WORKING_DIRECTORY ${LIBCXX_BUILD_DIR} ) endif() endif() # Add a meta-target for both libraries. add_custom_target(cxx DEPENDS ${LIBCXX_TARGETS}) if (LIBCXX_ENABLE_EXPERIMENTAL_LIBRARY) file(GLOB LIBCXX_EXPERIMENTAL_SOURCES ../src/experimental/*.cpp) if (LIBCXX_ENABLE_FILESYSTEM) file(GLOB LIBCXX_FILESYSTEM_SOURCES ../src/experimental/filesystem/*.cpp) endif() add_library(cxx_experimental STATIC ${LIBCXX_EXPERIMENTAL_SOURCES} ${LIBCXX_FILESYSTEM_SOURCES}) if (LIBCXX_ENABLE_SHARED) target_link_libraries(cxx_experimental cxx_shared) else() target_link_libraries(cxx_experimental cxx_static) endif() set(experimental_flags "${LIBCXX_COMPILE_FLAGS}") check_flag_supported(-std=c++14) if (NOT MSVC AND LIBCXX_SUPPORTS_STD_EQ_CXX14_FLAG) string(REPLACE "-std=c++11" "-std=c++14" experimental_flags "${LIBCXX_COMPILE_FLAGS}") endif() set_target_properties(cxx_experimental PROPERTIES COMPILE_FLAGS "${experimental_flags}" OUTPUT_NAME "c++experimental" ) endif() if (LIBCXX_BUILD_EXTERNAL_THREAD_LIBRARY) file(GLOB LIBCXX_EXTERNAL_THREADING_SUPPORT_SOURCES ../test/support/external_threads.cpp) if (LIBCXX_ENABLE_SHARED) add_library(cxx_external_threads SHARED ${LIBCXX_EXTERNAL_THREADING_SUPPORT_SOURCES}) else() add_library(cxx_external_threads STATIC ${LIBCXX_EXTERNAL_THREADING_SUPPORT_SOURCES}) endif() set_target_properties(cxx_external_threads PROPERTIES LINK_FLAGS "${LIBCXX_LINK_FLAGS}" COMPILE_FLAGS "${LIBCXX_COMPILE_FLAGS}" OUTPUT_NAME "c++external_threads" ) endif() # Generate a linker script inplace of a libc++.so symlink. Rerun this command # after cxx builds. if (LIBCXX_ENABLE_SHARED AND LIBCXX_ENABLE_ABI_LINKER_SCRIPT) # Get the name of the ABI library and handle the case where CXXABI_LIBNAME # is a target name and not a library. Ex cxxabi_shared. set(LIBCXX_INTERFACE_LIBRARY_NAMES) foreach(lib ${LIBCXX_INTERFACE_LIBRARIES}) # FIXME: Handle cxxabi_static and unwind_static. if (TARGET ${lib} OR (${lib} MATCHES "cxxabi(_static|_shared)?" AND HAVE_LIBCXXABI) OR (${lib} MATCHES "unwind(_static|_shared)?" AND HAVE_LIBUNWIND)) list(APPEND LIBCXX_INTERFACE_LIBRARY_NAMES "$") else() list(APPEND LIBCXX_INTERFACE_LIBRARY_NAMES "${lib}") endif() endforeach() #split_list(LIBCXX_INTERFACE_LIBRARY_NAMES) # Generate a linker script inplace of a libc++.so symlink. Rerun this command # after cxx builds. add_custom_command(TARGET cxx_shared POST_BUILD COMMAND ${PYTHON_EXECUTABLE} ${LIBCXX_SOURCE_DIR}/utils/gen_link_script.py ARGS "$" ${LIBCXX_INTERFACE_LIBRARY_NAMES} WORKING_DIRECTORY ${LIBCXX_BUILD_DIR} ) endif() if (LIBCXX_INSTALL_LIBRARY) if (LIBCXX_INSTALL_EXPERIMENTAL_LIBRARY) set(experimental_lib cxx_experimental) endif() install(TARGETS ${LIBCXX_TARGETS} ${experimental_lib} - LIBRARY DESTINATION lib${LIBCXX_LIBDIR_SUFFIX} COMPONENT cxx - ARCHIVE DESTINATION lib${LIBCXX_LIBDIR_SUFFIX} COMPONENT cxx + LIBRARY DESTINATION ${LIBCXX_INSTALL_PREFIX}lib${LIBCXX_LIBDIR_SUFFIX} COMPONENT cxx + ARCHIVE DESTINATION ${LIBCXX_INSTALL_PREFIX}lib${LIBCXX_LIBDIR_SUFFIX} COMPONENT cxx ) # NOTE: This install command must go after the cxx install command otherwise # it will not be executed after the library symlinks are installed. if (LIBCXX_ENABLE_SHARED AND LIBCXX_ENABLE_ABI_LINKER_SCRIPT) # Replace the libc++ filename with $ # after we required CMake 3.0. install(FILES "${LIBCXX_LIBRARY_DIR}/libc++${CMAKE_SHARED_LIBRARY_SUFFIX}" - DESTINATION lib${LIBCXX_LIBDIR_SUFFIX} + DESTINATION ${LIBCXX_INSTALL_PREFIX}lib${LIBCXX_LIBDIR_SUFFIX} COMPONENT libcxx) endif() endif() if (NOT CMAKE_CONFIGURATION_TYPES AND (LIBCXX_INSTALL_LIBRARY OR LIBCXX_INSTALL_HEADERS)) if(LIBCXX_INSTALL_LIBRARY) set(lib_install_target cxx) endif() if (LIBCXX_INSTALL_EXPERIMENTAL_LIBRARY) set(experimental_lib_install_target cxx_experimental) endif() if(LIBCXX_INSTALL_HEADERS) set(header_install_target install-cxx-headers) endif() add_custom_target(install-cxx DEPENDS ${lib_install_target} ${experimental_lib_install_target} ${header_install_target} COMMAND "${CMAKE_COMMAND}" -DCMAKE_INSTALL_COMPONENT=cxx -P "${LIBCXX_BINARY_DIR}/cmake_install.cmake") add_custom_target(install-libcxx DEPENDS install-cxx) endif() diff --git a/src/experimental/filesystem/filesystem_time_helper.h b/src/experimental/filesystem/filesystem_time_helper.h new file mode 100644 index 000000000000..a60fdef5f0d9 --- /dev/null +++ b/src/experimental/filesystem/filesystem_time_helper.h @@ -0,0 +1,173 @@ +//===----------------------------------------------------------------------===//// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===//// + +#ifndef FILESYSTEM_TIME_HELPER_H +#define FILESYSTEM_TIME_HELPER_H + +#include "experimental/__config" +#include "chrono" +#include "cstdlib" +#include "climits" + +#include +#include +#if !defined(UTIME_OMIT) +#include // for ::utimes as used in __last_write_time +#endif + +_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_FILESYSTEM + +namespace time_detail { namespace { + +using namespace chrono; + +template ::value> +struct fs_time_util_base { + static constexpr auto max_seconds = + duration_cast(FileTimeT::duration::max()).count(); + + static constexpr auto max_nsec = + duration_cast(FileTimeT::duration::max() - + seconds(max_seconds)) + .count(); + + static constexpr auto min_seconds = + duration_cast(FileTimeT::duration::min()).count(); + + static constexpr auto min_nsec_timespec = + duration_cast( + (FileTimeT::duration::min() - seconds(min_seconds)) + seconds(1)) + .count(); + + // Static assert that these values properly round trip. + static_assert((seconds(min_seconds) + + duration_cast(nanoseconds(min_nsec_timespec))) - + duration_cast(seconds(1)) == + FileTimeT::duration::min(), + ""); +}; + +template +struct fs_time_util_base { + static const long long max_seconds; + static const long long max_nsec; + static const long long min_seconds; + static const long long min_nsec_timespec; +}; + +template +const long long fs_time_util_base::max_seconds = + duration_cast(FileTimeT::duration::max()).count(); + +template +const long long fs_time_util_base::max_nsec = + duration_cast(FileTimeT::duration::max() - + seconds(max_seconds)) + .count(); + +template +const long long fs_time_util_base::min_seconds = + duration_cast(FileTimeT::duration::min()).count(); + +template +const long long fs_time_util_base::min_nsec_timespec = + duration_cast((FileTimeT::duration::min() - + seconds(min_seconds)) + + seconds(1)) + .count(); + +template +struct fs_time_util : fs_time_util_base { + using Base = fs_time_util_base; + using Base::max_nsec; + using Base::max_seconds; + using Base::min_nsec_timespec; + using Base::min_seconds; + +public: + template + static bool checked_set(CType* out, ChronoType time) { + using Lim = numeric_limits; + if (time > Lim::max() || time < Lim::min()) + return false; + *out = static_cast(time); + return true; + } + + static _LIBCPP_CONSTEXPR_AFTER_CXX11 bool is_representable(TimeSpecT tm) { + if (tm.tv_sec >= 0) { + return (tm.tv_sec < max_seconds) || + (tm.tv_sec == max_seconds && tm.tv_nsec <= max_nsec); + } else if (tm.tv_sec == (min_seconds - 1)) { + return tm.tv_nsec >= min_nsec_timespec; + } else { + return (tm.tv_sec >= min_seconds); + } + } + + static _LIBCPP_CONSTEXPR_AFTER_CXX11 bool is_representable(FileTimeT tm) { + auto secs = duration_cast(tm.time_since_epoch()); + auto nsecs = duration_cast(tm.time_since_epoch() - secs); + if (nsecs.count() < 0) { + secs = secs + seconds(1); + nsecs = nsecs + seconds(1); + } + using TLim = numeric_limits; + if (secs.count() >= 0) + return secs.count() <= TLim::max(); + return secs.count() >= TLim::min(); + } + + static _LIBCPP_CONSTEXPR_AFTER_CXX11 FileTimeT + convert_timespec(TimeSpecT tm) { + auto adj_msec = duration_cast(nanoseconds(tm.tv_nsec)); + if (tm.tv_sec >= 0) { + auto Dur = seconds(tm.tv_sec) + microseconds(adj_msec); + return FileTimeT(Dur); + } else if (duration_cast(nanoseconds(tm.tv_nsec)).count() == + 0) { + return FileTimeT(seconds(tm.tv_sec)); + } else { // tm.tv_sec < 0 + auto adj_subsec = + duration_cast(seconds(1) - nanoseconds(tm.tv_nsec)); + auto Dur = seconds(tm.tv_sec + 1) - adj_subsec; + return FileTimeT(Dur); + } + } + + template + static bool set_times_checked(TimeT* sec_out, SubSecT* subsec_out, + FileTimeT tp) { + using namespace chrono; + auto dur = tp.time_since_epoch(); + auto sec_dur = duration_cast(dur); + auto subsec_dur = duration_cast(dur - sec_dur); + // The tv_nsec and tv_usec fields must not be negative so adjust accordingly + if (subsec_dur.count() < 0) { + if (sec_dur.count() > min_seconds) { + sec_dur -= seconds(1); + subsec_dur += seconds(1); + } else { + subsec_dur = SubSecDurT::zero(); + } + } + return checked_set(sec_out, sec_dur.count()) && + checked_set(subsec_out, subsec_dur.count()); + } +}; + +} // end namespace +} // end namespace time_detail + +using time_detail::fs_time_util; + +_LIBCPP_END_NAMESPACE_EXPERIMENTAL_FILESYSTEM + +#endif // FILESYSTEM_TIME_HELPER_H diff --git a/src/experimental/filesystem/operations.cpp b/src/experimental/filesystem/operations.cpp index e9bc0eb6e30e..641a3c53636d 100644 --- a/src/experimental/filesystem/operations.cpp +++ b/src/experimental/filesystem/operations.cpp @@ -1,940 +1,807 @@ //===--------------------- filesystem/ops.cpp -----------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "experimental/filesystem" #include "iterator" #include "fstream" #include "type_traits" #include "random" /* for unique_path */ #include "cstdlib" #include "climits" +#include "filesystem_time_helper.h" + #include #include #include #include /* values for fchmodat */ #if !defined(UTIME_OMIT) #include // for ::utimes as used in __last_write_time #endif _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_FILESYSTEM filesystem_error::~filesystem_error() {} // POSIX HELPERS namespace detail { namespace { using value_type = path::value_type; using string_type = path::string_type; inline std::error_code capture_errno() { _LIBCPP_ASSERT(errno, "Expected errno to be non-zero"); return std::error_code(errno, std::generic_category()); } void set_or_throw(std::error_code const& m_ec, std::error_code* ec, const char* msg, path const& p = {}, path const& p2 = {}) { if (ec) { *ec = m_ec; } else { string msg_s("std::experimental::filesystem::"); msg_s += msg; __throw_filesystem_error(msg_s, p, p2, m_ec); } } void set_or_throw(std::error_code* ec, const char* msg, path const& p = {}, path const& p2 = {}) { return set_or_throw(capture_errno(), ec, msg, p, p2); } perms posix_get_perms(const struct ::stat & st) noexcept { return static_cast(st.st_mode) & perms::mask; } ::mode_t posix_convert_perms(perms prms) { return static_cast< ::mode_t>(prms & perms::mask); } file_status create_file_status(std::error_code& m_ec, path const& p, struct ::stat& path_stat, std::error_code* ec) { if (ec) *ec = m_ec; if (m_ec && (m_ec.value() == ENOENT || m_ec.value() == ENOTDIR)) { return file_status(file_type::not_found); } else if (m_ec) { set_or_throw(m_ec, ec, "posix_stat", p); return file_status(file_type::none); } // else file_status fs_tmp; auto const mode = path_stat.st_mode; if (S_ISLNK(mode)) fs_tmp.type(file_type::symlink); else if (S_ISREG(mode)) fs_tmp.type(file_type::regular); else if (S_ISDIR(mode)) fs_tmp.type(file_type::directory); else if (S_ISBLK(mode)) fs_tmp.type(file_type::block); else if (S_ISCHR(mode)) fs_tmp.type(file_type::character); else if (S_ISFIFO(mode)) fs_tmp.type(file_type::fifo); else if (S_ISSOCK(mode)) fs_tmp.type(file_type::socket); else fs_tmp.type(file_type::unknown); fs_tmp.permissions(detail::posix_get_perms(path_stat)); return fs_tmp; } file_status posix_stat(path const & p, struct ::stat& path_stat, std::error_code* ec) { std::error_code m_ec; if (::stat(p.c_str(), &path_stat) == -1) m_ec = detail::capture_errno(); return create_file_status(m_ec, p, path_stat, ec); } file_status posix_stat(path const & p, std::error_code* ec) { struct ::stat path_stat; return posix_stat(p, path_stat, ec); } file_status posix_lstat(path const & p, struct ::stat & path_stat, std::error_code* ec) { std::error_code m_ec; if (::lstat(p.c_str(), &path_stat) == -1) m_ec = detail::capture_errno(); return create_file_status(m_ec, p, path_stat, ec); } file_status posix_lstat(path const & p, std::error_code* ec) { struct ::stat path_stat; return posix_lstat(p, path_stat, ec); } bool stat_equivalent(struct ::stat& st1, struct ::stat& st2) { return (st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino); } // DETAIL::MISC bool copy_file_impl(const path& from, const path& to, perms from_perms, std::error_code *ec) { std::ifstream in(from.c_str(), std::ios::binary); std::ofstream out(to.c_str(), std::ios::binary); if (in.good() && out.good()) { using InIt = std::istreambuf_iterator; using OutIt = std::ostreambuf_iterator; InIt bin(in); InIt ein; OutIt bout(out); std::copy(bin, ein, bout); } if (out.fail() || in.fail()) { set_or_throw(make_error_code(errc::operation_not_permitted), ec, "copy_file", from, to); return false; } __permissions(to, from_perms, ec); // TODO what if permissions fails? return true; } }} // end namespace detail using detail::set_or_throw; path __canonical(path const & orig_p, const path& base, std::error_code *ec) { path p = absolute(orig_p, base); char buff[PATH_MAX + 1]; char *ret; if ((ret = ::realpath(p.c_str(), buff)) == nullptr) { set_or_throw(ec, "canonical", orig_p, base); return {}; } if (ec) ec->clear(); return {ret}; } void __copy(const path& from, const path& to, copy_options options, std::error_code *ec) { const bool sym_status = bool(options & (copy_options::create_symlinks | copy_options::skip_symlinks)); const bool sym_status2 = bool(options & copy_options::copy_symlinks); std::error_code m_ec; struct ::stat f_st = {}; const file_status f = sym_status || sym_status2 ? detail::posix_lstat(from, f_st, &m_ec) : detail::posix_stat(from, f_st, &m_ec); if (m_ec) return set_or_throw(m_ec, ec, "copy", from, to); struct ::stat t_st = {}; const file_status t = sym_status ? detail::posix_lstat(to, t_st, &m_ec) : detail::posix_stat(to, t_st, &m_ec); if (not status_known(t)) return set_or_throw(m_ec, ec, "copy", from, to); if (!exists(f) || is_other(f) || is_other(t) || (is_directory(f) && is_regular_file(t)) || detail::stat_equivalent(f_st, t_st)) { return set_or_throw(make_error_code(errc::function_not_supported), ec, "copy", from, to); } if (ec) ec->clear(); if (is_symlink(f)) { if (bool(copy_options::skip_symlinks & options)) { // do nothing } else if (not exists(t)) { __copy_symlink(from, to, ec); } else { set_or_throw(make_error_code(errc::file_exists), ec, "copy", from, to); } return; } else if (is_regular_file(f)) { if (bool(copy_options::directories_only & options)) { // do nothing } else if (bool(copy_options::create_symlinks & options)) { __create_symlink(from, to, ec); } else if (bool(copy_options::create_hard_links & options)) { __create_hard_link(from, to, ec); } else if (is_directory(t)) { __copy_file(from, to / from.filename(), options, ec); } else { __copy_file(from, to, options, ec); } return; } else if (is_directory(f) && bool(copy_options::create_symlinks & options)) { return set_or_throw(make_error_code(errc::is_a_directory), ec, "copy"); } else if (is_directory(f) && (bool(copy_options::recursive & options) || copy_options::none == options)) { if (!exists(t)) { // create directory to with attributes from 'from'. __create_directory(to, from, ec); if (ec && *ec) { return; } } directory_iterator it = ec ? directory_iterator(from, *ec) : directory_iterator(from); if (ec && *ec) { return; } std::error_code m_ec; for (; it != directory_iterator(); it.increment(m_ec)) { if (m_ec) return set_or_throw(m_ec, ec, "copy", from, to); __copy(it->path(), to / it->path().filename(), options | copy_options::__in_recursive_copy, ec); if (ec && *ec) { return; } } } } bool __copy_file(const path& from, const path& to, copy_options options, std::error_code *ec) { if (ec) ec->clear(); std::error_code m_ec; auto from_st = detail::posix_stat(from, &m_ec); if (not is_regular_file(from_st)) { if (not m_ec) m_ec = make_error_code(errc::not_supported); set_or_throw(m_ec, ec, "copy_file", from, to); return false; } auto to_st = detail::posix_stat(to, &m_ec); if (!status_known(to_st)) { set_or_throw(m_ec, ec, "copy_file", from, to); return false; } const bool to_exists = exists(to_st); if (to_exists && !is_regular_file(to_st)) { set_or_throw(make_error_code(errc::not_supported), ec, "copy_file", from, to); return false; } if (to_exists && bool(copy_options::skip_existing & options)) { return false; } else if (to_exists && bool(copy_options::update_existing & options)) { auto from_time = __last_write_time(from, ec); if (ec && *ec) { return false; } auto to_time = __last_write_time(to, ec); if (ec && *ec) { return false; } if (from_time <= to_time) { return false; } return detail::copy_file_impl(from, to, from_st.permissions(), ec); } else if (!to_exists || bool(copy_options::overwrite_existing & options)) { return detail::copy_file_impl(from, to, from_st.permissions(), ec); } else { set_or_throw(make_error_code(errc::file_exists), ec, "copy", from, to); return false; } _LIBCPP_UNREACHABLE(); } void __copy_symlink(const path& existing_symlink, const path& new_symlink, std::error_code *ec) { const path real_path(__read_symlink(existing_symlink, ec)); if (ec && *ec) { return; } // NOTE: proposal says you should detect if you should call // create_symlink or create_directory_symlink. I don't think this // is needed with POSIX __create_symlink(real_path, new_symlink, ec); } bool __create_directories(const path& p, std::error_code *ec) { std::error_code m_ec; auto const st = detail::posix_stat(p, &m_ec); if (!status_known(st)) { set_or_throw(m_ec, ec, "create_directories", p); return false; } else if (is_directory(st)) { if (ec) ec->clear(); return false; } else if (exists(st)) { set_or_throw(make_error_code(errc::file_exists), ec, "create_directories", p); return false; } const path parent = p.parent_path(); if (!parent.empty()) { const file_status parent_st = status(parent, m_ec); if (not status_known(parent_st)) { set_or_throw(m_ec, ec, "create_directories", p); return false; } if (not exists(parent_st)) { __create_directories(parent, ec); if (ec && *ec) { return false; } } } return __create_directory(p, ec); } bool __create_directory(const path& p, std::error_code *ec) { if (ec) ec->clear(); if (::mkdir(p.c_str(), static_cast(perms::all)) == 0) return true; if (errno != EEXIST || !is_directory(p)) set_or_throw(ec, "create_directory", p); return false; } bool __create_directory(path const & p, path const & attributes, std::error_code *ec) { struct ::stat attr_stat; std::error_code mec; auto st = detail::posix_stat(attributes, attr_stat, &mec); if (!status_known(st)) { set_or_throw(mec, ec, "create_directory", p, attributes); return false; } if (ec) ec->clear(); if (::mkdir(p.c_str(), attr_stat.st_mode) == 0) return true; if (errno != EEXIST || !is_directory(p)) set_or_throw(ec, "create_directory", p, attributes); return false; } void __create_directory_symlink(path const & from, path const & to, std::error_code *ec){ if (::symlink(from.c_str(), to.c_str()) != 0) set_or_throw(ec, "create_directory_symlink", from, to); else if (ec) ec->clear(); } void __create_hard_link(const path& from, const path& to, std::error_code *ec){ if (::link(from.c_str(), to.c_str()) == -1) set_or_throw(ec, "create_hard_link", from, to); else if (ec) ec->clear(); } void __create_symlink(path const & from, path const & to, std::error_code *ec) { if (::symlink(from.c_str(), to.c_str()) == -1) set_or_throw(ec, "create_symlink", from, to); else if (ec) ec->clear(); } path __current_path(std::error_code *ec) { auto size = ::pathconf(".", _PC_PATH_MAX); _LIBCPP_ASSERT(size >= 0, "pathconf returned a 0 as max size"); auto buff = std::unique_ptr(new char[size + 1]); char* ret; if ((ret = ::getcwd(buff.get(), static_cast(size))) == nullptr) { set_or_throw(ec, "current_path"); return {}; } if (ec) ec->clear(); return {buff.get()}; } void __current_path(const path& p, std::error_code *ec) { if (::chdir(p.c_str()) == -1) set_or_throw(ec, "current_path", p); else if (ec) ec->clear(); } bool __equivalent(const path& p1, const path& p2, std::error_code *ec) { + auto make_unsupported_error = [&]() { + set_or_throw(make_error_code(errc::not_supported), ec, + "equivalent", p1, p2); + return false; + }; std::error_code ec1, ec2; struct ::stat st1 = {}; struct ::stat st2 = {}; auto s1 = detail::posix_stat(p1.native(), st1, &ec1); + if (!exists(s1)) + return make_unsupported_error(); auto s2 = detail::posix_stat(p2.native(), st2, &ec2); - - if ((!exists(s1) && !exists(s2)) || (is_other(s1) && is_other(s2))) { - set_or_throw(make_error_code(errc::not_supported), ec, - "equivalent", p1, p2); - return false; - } + if (!exists(s2)) + return make_unsupported_error(); if (ec) ec->clear(); return (st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino); } std::uintmax_t __file_size(const path& p, std::error_code *ec) { std::error_code m_ec; struct ::stat st; file_status fst = detail::posix_stat(p, st, &m_ec); if (!exists(fst) || !is_regular_file(fst)) { if (!m_ec) m_ec = make_error_code(errc::not_supported); set_or_throw(m_ec, ec, "file_size", p); return static_cast(-1); } // is_regular_file(p) == true if (ec) ec->clear(); return static_cast(st.st_size); } std::uintmax_t __hard_link_count(const path& p, std::error_code *ec) { std::error_code m_ec; struct ::stat st; detail::posix_stat(p, st, &m_ec); if (m_ec) { set_or_throw(m_ec, ec, "hard_link_count", p); return static_cast(-1); } if (ec) ec->clear(); return static_cast(st.st_nlink); } bool __fs_is_empty(const path& p, std::error_code *ec) { if (ec) ec->clear(); std::error_code m_ec; struct ::stat pst; auto st = detail::posix_stat(p, pst, &m_ec); if (m_ec) { set_or_throw(m_ec, ec, "is_empty", p); return false; } else if (!is_directory(st) && !is_regular_file(st)) { m_ec = make_error_code(errc::not_supported); set_or_throw(m_ec, ec, "is_empty"); return false; } else if (is_directory(st)) { auto it = ec ? directory_iterator(p, *ec) : directory_iterator(p); if (ec && *ec) return false; return it == directory_iterator{}; } else if (is_regular_file(st)) return static_cast(pst.st_size) == 0; _LIBCPP_UNREACHABLE(); } namespace detail { namespace { -using namespace std::chrono; - -template -bool checked_set(CType* out, ChronoType time) { - using Lim = numeric_limits; - if (time > Lim::max() || time < Lim::min()) - return false; - *out = static_cast(time); - return true; -} - using TimeSpec = struct timespec; using StatT = struct stat; #if defined(__APPLE__) TimeSpec extract_mtime(StatT const& st) { return st.st_mtimespec; } TimeSpec extract_atime(StatT const& st) { return st.st_atimespec; } #else TimeSpec extract_mtime(StatT const& st) { return st.st_mtim; } __attribute__((unused)) // Suppress warning TimeSpec extract_atime(StatT const& st) { return st.st_atim; } #endif -constexpr auto max_seconds = duration_cast( - file_time_type::duration::max()).count(); - -constexpr auto max_nsec = duration_cast( - file_time_type::duration::max() - seconds(max_seconds)).count(); - -constexpr auto min_seconds = duration_cast( - file_time_type::duration::min()).count(); - -constexpr auto min_nsec_timespec = duration_cast( - (file_time_type::duration::min() - seconds(min_seconds)) + seconds(1)).count(); - -// Static assert that these values properly round trip. -static_assert((seconds(min_seconds) + duration_cast(nanoseconds(min_nsec_timespec))) - - duration_cast(seconds(1)) - == file_time_type::duration::min(), ""); - -constexpr auto max_time_t = numeric_limits::max(); -constexpr auto min_time_t = numeric_limits::min(); - -#if !defined(__LP64__) && defined(__clang__) -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wtautological-constant-out-of-range-compare" -#endif - -_LIBCPP_CONSTEXPR_AFTER_CXX11 -bool is_representable(TimeSpec const& tm) { - if (tm.tv_sec >= 0) { - return (tm.tv_sec < max_seconds) || - (tm.tv_sec == max_seconds && tm.tv_nsec <= max_nsec); - } else if (tm.tv_sec == (min_seconds - 1)) { - return tm.tv_nsec >= min_nsec_timespec; - } else { - return (tm.tv_sec >= min_seconds); - } -} -#ifndef _LIBCPP_HAS_NO_CXX14_CONSTEXPR -#if defined(__LP64__) -static_assert(is_representable({max_seconds, max_nsec}), ""); -static_assert(!is_representable({max_seconds + 1, 0}), ""); -static_assert(!is_representable({max_seconds, max_nsec + 1}), ""); -static_assert(!is_representable({max_time_t, 0}), ""); -static_assert(is_representable({min_seconds, 0}), ""); -static_assert(is_representable({min_seconds - 1, min_nsec_timespec}), ""); -static_assert(is_representable({min_seconds - 1, min_nsec_timespec + 1}), ""); -static_assert(!is_representable({min_seconds - 1, min_nsec_timespec - 1}), ""); -static_assert(!is_representable({min_time_t, 999999999}), ""); -#else -static_assert(is_representable({max_time_t, 999999999}), ""); -static_assert(is_representable({max_time_t, 1000000000}), ""); -static_assert(is_representable({min_time_t, 0}), ""); -#endif -#endif - -_LIBCPP_CONSTEXPR_AFTER_CXX11 -bool is_representable(file_time_type const& tm) { - auto secs = duration_cast(tm.time_since_epoch()); - auto nsecs = duration_cast(tm.time_since_epoch() - secs); - if (nsecs.count() < 0) { - secs = secs + seconds(1); - nsecs = nsecs + seconds(1); - } - using TLim = numeric_limits; - if (secs.count() >= 0) - return secs.count() <= TLim::max(); - return secs.count() >= TLim::min(); -} -#ifndef _LIBCPP_HAS_NO_CXX14_CONSTEXPR -#if defined(__LP64__) -static_assert(is_representable(file_time_type::max()), ""); -static_assert(is_representable(file_time_type::min()), ""); -#else -static_assert(!is_representable(file_time_type::max()), ""); -static_assert(!is_representable(file_time_type::min()), ""); -static_assert(is_representable(file_time_type(seconds(max_time_t))), ""); -static_assert(is_representable(file_time_type(seconds(min_time_t))), ""); -#endif -#endif - -_LIBCPP_CONSTEXPR_AFTER_CXX11 -file_time_type convert_timespec(TimeSpec const& tm) { - auto adj_msec = duration_cast(nanoseconds(tm.tv_nsec)); - if (tm.tv_sec >= 0) { - auto Dur = seconds(tm.tv_sec) + microseconds(adj_msec); - return file_time_type(Dur); - } else if (duration_cast(nanoseconds(tm.tv_nsec)).count() == 0) { - return file_time_type(seconds(tm.tv_sec)); - } else { // tm.tv_sec < 0 - auto adj_subsec = duration_cast(seconds(1) - nanoseconds(tm.tv_nsec)); - auto Dur = seconds(tm.tv_sec + 1) - adj_subsec; - return file_time_type(Dur); - } -} -#ifndef _LIBCPP_HAS_NO_CXX14_CONSTEXPR -#if defined(__LP64__) -static_assert(convert_timespec({max_seconds, max_nsec}) == file_time_type::max(), ""); -static_assert(convert_timespec({max_seconds, max_nsec - 1}) < file_time_type::max(), ""); -static_assert(convert_timespec({max_seconds - 1, 999999999}) < file_time_type::max(), ""); -static_assert(convert_timespec({min_seconds - 1, min_nsec_timespec}) == file_time_type::min(), ""); -static_assert(convert_timespec({min_seconds - 1, min_nsec_timespec + 1}) > file_time_type::min(), ""); -static_assert(convert_timespec({min_seconds , 0}) > file_time_type::min(), ""); -#else -// FIXME add tests for 32 bit builds -#endif -#endif - -#if !defined(__LP64__) && defined(__clang__) -#pragma clang diagnostic pop -#endif - -template -bool set_times_checked(time_t* sec_out, SubSecT* subsec_out, file_time_type tp) { - using namespace chrono; - auto dur = tp.time_since_epoch(); - auto sec_dur = duration_cast(dur); - auto subsec_dur = duration_cast(dur - sec_dur); - // The tv_nsec and tv_usec fields must not be negative so adjust accordingly - if (subsec_dur.count() < 0) { - if (sec_dur.count() > min_seconds) { - sec_dur -= seconds(1); - subsec_dur += seconds(1); - } else { - subsec_dur = SubSecDurT::zero(); - } - } - return checked_set(sec_out, sec_dur.count()) - && checked_set(subsec_out, subsec_dur.count()); -} - }} // end namespace detail +using FSTime = fs_time_util; + file_time_type __last_write_time(const path& p, std::error_code *ec) { using namespace ::std::chrono; std::error_code m_ec; struct ::stat st; detail::posix_stat(p, st, &m_ec); if (m_ec) { set_or_throw(m_ec, ec, "last_write_time", p); return file_time_type::min(); } if (ec) ec->clear(); auto ts = detail::extract_mtime(st); - if (!detail::is_representable(ts)) { + if (!FSTime::is_representable(ts)) { set_or_throw(error_code(EOVERFLOW, generic_category()), ec, "last_write_time", p); return file_time_type::min(); } - return detail::convert_timespec(ts); + return FSTime::convert_timespec(ts); } void __last_write_time(const path& p, file_time_type new_time, std::error_code *ec) { using namespace std::chrono; std::error_code m_ec; // We can use the presence of UTIME_OMIT to detect platforms that do not // provide utimensat. #if !defined(UTIME_OMIT) // This implementation has a race condition between determining the // last access time and attempting to set it to the same value using // ::utimes struct ::stat st; file_status fst = detail::posix_stat(p, st, &m_ec); if (m_ec && !status_known(fst)) { set_or_throw(m_ec, ec, "last_write_time", p); return; } auto atime = detail::extract_atime(st); struct ::timeval tbuf[2]; tbuf[0].tv_sec = atime.tv_sec; tbuf[0].tv_usec = duration_cast(nanoseconds(atime.tv_nsec)).count(); - const bool overflowed = !detail::set_times_checked( + const bool overflowed = !FSTime::set_times_checked( &tbuf[1].tv_sec, &tbuf[1].tv_usec, new_time); if (overflowed) { set_or_throw(make_error_code(errc::invalid_argument), ec, "last_write_time", p); return; } if (::utimes(p.c_str(), tbuf) == -1) { m_ec = detail::capture_errno(); } #else struct ::timespec tbuf[2]; tbuf[0].tv_sec = 0; tbuf[0].tv_nsec = UTIME_OMIT; - const bool overflowed = !detail::set_times_checked( + const bool overflowed = !FSTime::set_times_checked( &tbuf[1].tv_sec, &tbuf[1].tv_nsec, new_time); if (overflowed) { set_or_throw(make_error_code(errc::invalid_argument), ec, "last_write_time", p); return; } if (::utimensat(AT_FDCWD, p.c_str(), tbuf, 0) == -1) { m_ec = detail::capture_errno(); } #endif if (m_ec) set_or_throw(m_ec, ec, "last_write_time", p); else if (ec) ec->clear(); } void __permissions(const path& p, perms prms, std::error_code *ec) { const bool resolve_symlinks = !bool(perms::symlink_nofollow & prms); const bool add_perms = bool(perms::add_perms & prms); const bool remove_perms = bool(perms::remove_perms & prms); _LIBCPP_ASSERT(!(add_perms && remove_perms), "Both add_perms and remove_perms are set"); bool set_sym_perms = false; prms &= perms::mask; if (!resolve_symlinks || (add_perms || remove_perms)) { std::error_code m_ec; file_status st = resolve_symlinks ? detail::posix_stat(p, &m_ec) : detail::posix_lstat(p, &m_ec); set_sym_perms = is_symlink(st); if (m_ec) return set_or_throw(m_ec, ec, "permissions", p); _LIBCPP_ASSERT(st.permissions() != perms::unknown, "Permissions unexpectedly unknown"); if (add_perms) prms |= st.permissions(); else if (remove_perms) prms = st.permissions() & ~prms; } const auto real_perms = detail::posix_convert_perms(prms); # if defined(AT_SYMLINK_NOFOLLOW) && defined(AT_FDCWD) const int flags = set_sym_perms ? AT_SYMLINK_NOFOLLOW : 0; if (::fchmodat(AT_FDCWD, p.c_str(), real_perms, flags) == -1) { return set_or_throw(ec, "permissions", p); } # else if (set_sym_perms) return set_or_throw(make_error_code(errc::operation_not_supported), ec, "permissions", p); if (::chmod(p.c_str(), real_perms) == -1) { return set_or_throw(ec, "permissions", p); } # endif if (ec) ec->clear(); } path __read_symlink(const path& p, std::error_code *ec) { char buff[PATH_MAX + 1]; std::error_code m_ec; ::ssize_t ret; if ((ret = ::readlink(p.c_str(), buff, PATH_MAX)) == -1) { set_or_throw(ec, "read_symlink", p); return {}; } _LIBCPP_ASSERT(ret <= PATH_MAX, "TODO"); _LIBCPP_ASSERT(ret > 0, "TODO"); if (ec) ec->clear(); buff[ret] = 0; return {buff}; } bool __remove(const path& p, std::error_code *ec) { if (ec) ec->clear(); if (::remove(p.c_str()) == -1) { set_or_throw(ec, "remove", p); return false; } return true; } namespace { std::uintmax_t remove_all_impl(path const & p, std::error_code& ec) { const auto npos = static_cast(-1); const file_status st = __symlink_status(p, &ec); if (ec) return npos; std::uintmax_t count = 1; if (is_directory(st)) { for (directory_iterator it(p, ec); !ec && it != directory_iterator(); it.increment(ec)) { auto other_count = remove_all_impl(it->path(), ec); if (ec) return npos; count += other_count; } if (ec) return npos; } if (!__remove(p, &ec)) return npos; return count; } } // end namespace std::uintmax_t __remove_all(const path& p, std::error_code *ec) { std::error_code mec; auto count = remove_all_impl(p, mec); if (mec) { set_or_throw(mec, ec, "remove_all", p); return static_cast(-1); } if (ec) ec->clear(); return count; } void __rename(const path& from, const path& to, std::error_code *ec) { if (::rename(from.c_str(), to.c_str()) == -1) set_or_throw(ec, "rename", from, to); else if (ec) ec->clear(); } void __resize_file(const path& p, std::uintmax_t size, std::error_code *ec) { if (::truncate(p.c_str(), static_cast<::off_t>(size)) == -1) set_or_throw(ec, "resize_file", p); else if (ec) ec->clear(); } space_info __space(const path& p, std::error_code *ec) { space_info si; struct statvfs m_svfs = {}; if (::statvfs(p.c_str(), &m_svfs) == -1) { set_or_throw(ec, "space", p); si.capacity = si.free = si.available = static_cast(-1); return si; } if (ec) ec->clear(); // Multiply with overflow checking. auto do_mult = [&](std::uintmax_t& out, std::uintmax_t other) { out = other * m_svfs.f_frsize; if (other == 0 || out / other != m_svfs.f_frsize) out = static_cast(-1); }; do_mult(si.capacity, m_svfs.f_blocks); do_mult(si.free, m_svfs.f_bfree); do_mult(si.available, m_svfs.f_bavail); return si; } file_status __status(const path& p, std::error_code *ec) { return detail::posix_stat(p, ec); } file_status __symlink_status(const path& p, std::error_code *ec) { return detail::posix_lstat(p, ec); } path __system_complete(const path& p, std::error_code *ec) { if (ec) ec->clear(); return absolute(p, current_path()); } path __temp_directory_path(std::error_code* ec) { const char* env_paths[] = {"TMPDIR", "TMP", "TEMP", "TEMPDIR"}; const char* ret = nullptr; for (auto& ep : env_paths) if ((ret = std::getenv(ep))) break; if (ret == nullptr) ret = "/tmp"; path p(ret); std::error_code m_ec; if (!exists(p, m_ec) || !is_directory(p, m_ec)) { if (!m_ec || m_ec == make_error_code(errc::no_such_file_or_directory)) m_ec = make_error_code(errc::not_a_directory); set_or_throw(m_ec, ec, "temp_directory_path"); return {}; } if (ec) ec->clear(); return p; } // An absolute path is composed according to the table in [fs.op.absolute]. path absolute(const path& p, const path& base) { auto root_name = p.root_name(); auto root_dir = p.root_directory(); if (!root_name.empty() && !root_dir.empty()) return p; auto abs_base = base.is_absolute() ? base : absolute(base); /* !has_root_name && !has_root_dir */ if (root_name.empty() && root_dir.empty()) { return abs_base / p; } else if (!root_name.empty()) /* has_root_name && !has_root_dir */ { return root_name / abs_base.root_directory() / abs_base.relative_path() / p.relative_path(); } else /* !has_root_name && has_root_dir */ { if (abs_base.has_root_name()) return abs_base.root_name() / p; // else p is absolute, return outside of block } return p; } _LIBCPP_END_NAMESPACE_EXPERIMENTAL_FILESYSTEM diff --git a/include/__refstring b/src/include/refstring.h similarity index 97% rename from include/__refstring rename to src/include/refstring.h index 7f417a03c491..f0d5b4456da5 100644 --- a/include/__refstring +++ b/src/include/refstring.h @@ -1,127 +1,127 @@ //===------------------------ __refstring ---------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -#ifndef _LIBCPP___REFSTRING -#define _LIBCPP___REFSTRING +#ifndef _LIBCPP_REFSTRING_H +#define _LIBCPP_REFSTRING_H #include <__config> #include #include #include #ifdef __APPLE__ #include #include #endif _LIBCPP_BEGIN_NAMESPACE_STD namespace __refstring_imp { namespace { typedef int count_t; struct _Rep_base { std::size_t len; std::size_t cap; count_t count; }; inline _Rep_base* rep_from_data(const char *data_) noexcept { char *data = const_cast(data_); return reinterpret_cast<_Rep_base *>(data - sizeof(_Rep_base)); } inline char * data_from_rep(_Rep_base *rep) noexcept { char *data = reinterpret_cast(rep); return data + sizeof(*rep); } #if defined(__APPLE__) inline const char* compute_gcc_empty_string_storage() _NOEXCEPT { void* handle = dlopen("/usr/lib/libstdc++.6.dylib", RTLD_NOLOAD); if (handle == nullptr) return nullptr; void* sym = dlsym(handle, "_ZNSs4_Rep20_S_empty_rep_storageE"); if (sym == nullptr) return nullptr; return data_from_rep(reinterpret_cast<_Rep_base *>(sym)); } inline const char* get_gcc_empty_string_storage() _NOEXCEPT { static const char* p = compute_gcc_empty_string_storage(); return p; } #endif }} // namespace __refstring_imp using namespace __refstring_imp; inline __libcpp_refstring::__libcpp_refstring(const char* msg) { std::size_t len = strlen(msg); _Rep_base* rep = static_cast<_Rep_base *>(::operator new(sizeof(*rep) + len + 1)); rep->len = len; rep->cap = len; rep->count = 0; char *data = data_from_rep(rep); std::memcpy(data, msg, len + 1); __imp_ = data; } inline __libcpp_refstring::__libcpp_refstring(const __libcpp_refstring &s) _NOEXCEPT : __imp_(s.__imp_) { if (__uses_refcount()) __sync_add_and_fetch(&rep_from_data(__imp_)->count, 1); } inline __libcpp_refstring& __libcpp_refstring::operator=(__libcpp_refstring const& s) _NOEXCEPT { bool adjust_old_count = __uses_refcount(); struct _Rep_base *old_rep = rep_from_data(__imp_); __imp_ = s.__imp_; if (__uses_refcount()) __sync_add_and_fetch(&rep_from_data(__imp_)->count, 1); if (adjust_old_count) { if (__sync_add_and_fetch(&old_rep->count, count_t(-1)) < 0) { ::operator delete(old_rep); } } return *this; } inline __libcpp_refstring::~__libcpp_refstring() { if (__uses_refcount()) { _Rep_base* rep = rep_from_data(__imp_); if (__sync_add_and_fetch(&rep->count, count_t(-1)) < 0) { ::operator delete(rep); } } } inline bool __libcpp_refstring::__uses_refcount() const { #ifdef __APPLE__ return __imp_ != get_gcc_empty_string_storage(); #else return true; #endif } _LIBCPP_END_NAMESPACE_STD -#endif //_LIBCPP___REFSTRING +#endif //_LIBCPP_REFSTRING_H diff --git a/src/stdexcept.cpp b/src/stdexcept.cpp index 3f333309dd8f..5e06e521e404 100644 --- a/src/stdexcept.cpp +++ b/src/stdexcept.cpp @@ -1,104 +1,104 @@ //===------------------------ stdexcept.cpp -------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "stdexcept" #include "new" #include "string" #include "system_error" -#include "__refstring" +#include "include/refstring.h" /* For _LIBCPPABI_VERSION */ #if !defined(_LIBCPP_BUILDING_HAS_NO_ABI_LIBRARY) && \ (defined(LIBCXX_BUILDING_LIBCXXABI) || defined(__APPLE__) || defined(LIBCXXRT)) #include #endif static_assert(sizeof(std::__libcpp_refstring) == sizeof(const char *), ""); namespace std // purposefully not using versioning namespace { logic_error::logic_error(const string& msg) : __imp_(msg.c_str()) { } logic_error::logic_error(const char* msg) : __imp_(msg) { } logic_error::logic_error(const logic_error& le) _NOEXCEPT : __imp_(le.__imp_) { } logic_error& logic_error::operator=(const logic_error& le) _NOEXCEPT { __imp_ = le.__imp_; return *this; } #if !defined(_LIBCPPABI_VERSION) && !defined(LIBSTDCXX) logic_error::~logic_error() _NOEXCEPT { } const char* logic_error::what() const _NOEXCEPT { return __imp_.c_str(); } #endif runtime_error::runtime_error(const string& msg) : __imp_(msg.c_str()) { } runtime_error::runtime_error(const char* msg) : __imp_(msg) { } runtime_error::runtime_error(const runtime_error& le) _NOEXCEPT : __imp_(le.__imp_) { } runtime_error& runtime_error::operator=(const runtime_error& le) _NOEXCEPT { __imp_ = le.__imp_; return *this; } #if !defined(_LIBCPPABI_VERSION) && !defined(LIBSTDCXX) runtime_error::~runtime_error() _NOEXCEPT { } const char* runtime_error::what() const _NOEXCEPT { return __imp_.c_str(); } domain_error::~domain_error() _NOEXCEPT {} invalid_argument::~invalid_argument() _NOEXCEPT {} length_error::~length_error() _NOEXCEPT {} out_of_range::~out_of_range() _NOEXCEPT {} range_error::~range_error() _NOEXCEPT {} overflow_error::~overflow_error() _NOEXCEPT {} underflow_error::~underflow_error() _NOEXCEPT {} #endif } // std diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 6f2eac0546fc..7b8a8322a11f 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,87 +1,120 @@ macro(pythonize_bool var) if (${var}) set(${var} True) else() set(${var} False) endif() endmacro() set(LIBCXX_LIT_VARIANT "libcxx" CACHE STRING "Configuration variant to use for LIT.") # The tests shouldn't link to any ABI library when it has been linked into # libc++ statically or via a linker script. if (LIBCXX_ENABLE_STATIC_ABI_LIBRARY OR LIBCXX_ENABLE_ABI_LINKER_SCRIPT) set(LIBCXX_CXX_ABI_LIBNAME "none") endif() # The tests shouldn't link to libunwind if we have a linker script which # already does so. if (LIBCXX_ENABLE_ABI_LINKER_SCRIPT) set(LIBCXXABI_USE_LLVM_UNWINDER OFF) endif() pythonize_bool(LIBCXX_ENABLE_EXCEPTIONS) pythonize_bool(LIBCXX_ENABLE_EXPERIMENTAL_LIBRARY) pythonize_bool(LIBCXX_ENABLE_FILESYSTEM) pythonize_bool(LIBCXX_ENABLE_RTTI) pythonize_bool(LIBCXX_ENABLE_SHARED) pythonize_bool(LIBCXX_BUILD_32_BITS) pythonize_bool(LIBCXX_GENERATE_COVERAGE) pythonize_bool(LIBCXXABI_ENABLE_SHARED) pythonize_bool(LIBCXXABI_USE_LLVM_UNWINDER) pythonize_bool(LIBCXX_HAS_ATOMIC_LIB) pythonize_bool(LIBCXX_HAVE_CXX_ATOMICS_WITH_LIB) pythonize_bool(LIBCXX_BUILD_EXTERNAL_THREAD_LIBRARY) pythonize_bool(LIBCXX_DEBUG_BUILD) # By default, for non-standalone builds, libcxx and libcxxabi share a library # directory. if (NOT LIBCXX_CXX_ABI_LIBRARY_PATH) set(LIBCXX_CXX_ABI_LIBRARY_PATH "${LIBCXX_LIBRARY_DIR}" CACHE PATH "The path to libc++abi library.") endif() set(LIBCXX_TARGET_INFO "libcxx.test.target_info.LocalTI" CACHE STRING "TargetInfo to use when setting up test environment.") set(LIBCXX_EXECUTOR "None" CACHE STRING "Executor to use when running tests.") set(AUTO_GEN_COMMENT "## Autogenerated by libcxx configuration.\n# Do not edit!") configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in ${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg @ONLY) set(LIBCXX_TEST_DEPS "") if (LIBCXX_ENABLE_EXPERIMENTAL_LIBRARY) set(LIBCXX_TEST_DEPS cxx_experimental) endif() if (LIBCXX_BUILD_EXTERNAL_THREAD_LIBRARY) list(APPEND LIBCXX_TEST_DEPS cxx_external_threads) endif() if (LIBCXX_INCLUDE_TESTS) include(AddLLVM) # for add_lit_testsuite add_lit_testsuite(check-cxx "Running libcxx tests" ${CMAKE_CURRENT_BINARY_DIR} DEPENDS cxx ${LIBCXX_TEST_DEPS}) add_custom_target(check-libcxx DEPENDS check-cxx) endif() if (LIBCXX_GENERATE_COVERAGE) include(CodeCoverage) set(output_dir "${CMAKE_CURRENT_BINARY_DIR}/coverage") set(capture_dirs "${LIBCXX_LIB_CMAKEFILES_DIR}/cxx_objects.dir/" "${LIBCXX_LIB_CMAKEFILES_DIR}/cxx.dir/" "${LIBCXX_LIB_CMAKEFILES_DIR}/cxx_experimental.dir/" "${CMAKE_CURRENT_BINARY_DIR}") set(extract_dirs "${LIBCXX_SOURCE_DIR}/include;${LIBCXX_SOURCE_DIR}/src") setup_lcov_test_target_coverage("cxx" "${output_dir}" "${capture_dirs}" "${extract_dirs}") endif() + + +if (LIBCXX_CONFIGURE_IDE) + # Create dummy targets for each of the tests in the test suite, this allows + # IDE's such as CLion to correctly highlight the tests because it knows + # roughly what include paths/compile flags/macro definitions are needed. + include_directories(support) + file(GLOB_RECURSE LIBCXX_TESTS ${CMAKE_CURRENT_SOURCE_DIR}/*.pass.cpp) + file(GLOB LIBCXX_TEST_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/support/*) + file(GLOB_RECURSE LIBCXX_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/../include/*) + add_executable(libcxx_test_objects EXCLUDE_FROM_ALL + ${LIBCXX_TESTS} ${LIBCXX_TEST_HEADERS} ${LIBCXX_HEADERS}) + add_dependencies(libcxx_test_objects cxx) + + set(STATIC_ROOT ${LIBCXX_SOURCE_DIR}/test/std/experimental/filesystem/Inputs/static_test_env) + add_definitions(-DLIBCXX_FILESYSTEM_STATIC_TEST_ROOT="${STATIC_ROOT}") + + set(DYNAMIC_ROOT ${LIBCXX_BINARY_DIR}/test/filesystem/Output/dynamic_env) + add_definitions(-DLIBCXX_FILESYSTEM_DYNAMIC_TEST_ROOT="${DYNAMIC_ROOT}") + + set(DYNAMIC_HELPER "python ${LIBCXX_SOURCE_DIR}/test/support/filesystem_dynamic_test_helper.py ") + add_definitions(-DLIBCXX_FILESYSTEM_DYNAMIC_TEST_HELPER="${DYNAMIC_HELPER}") + + split_list(LIBCXX_COMPILE_FLAGS) + split_list(LIBCXX_LINK_FLAGS) + + set_target_properties(libcxx_test_objects + PROPERTIES + COMPILE_FLAGS "${LIBCXX_COMPILE_FLAGS}" + LINK_FLAGS "${LIBCXX_LINK_FLAGS}" + EXCLUDE_FROM_ALL ON + ) +endif() diff --git a/test/libcxx/experimental/containers/sequences/dynarray/dynarray.cons/default_throws_bad_alloc.pass.cpp b/test/libcxx/experimental/containers/sequences/dynarray/dynarray.cons/default_throws_bad_alloc.pass.cpp index 9c6cad8ee2d3..4009841355f9 100644 --- a/test/libcxx/experimental/containers/sequences/dynarray/dynarray.cons/default_throws_bad_alloc.pass.cpp +++ b/test/libcxx/experimental/containers/sequences/dynarray/dynarray.cons/default_throws_bad_alloc.pass.cpp @@ -1,35 +1,35 @@ //===----------------------------------------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // UNSUPPORTED: libcpp-no-exceptions // XFAIL: availability // dynarray.cons // explicit dynarray(size_type c); // UNSUPPORTED: c++98, c++03, c++11 // The sanitizers replace new/delete with versions that do not throw bad_alloc. -// UNSUPPORTED: sanitizer-new-delete, ubsan +// UNSUPPORTED: sanitizer-new-delete #include #include #include #include using std::experimental::dynarray; int main() { try { dynarray((std::numeric_limits::max() / sizeof(int)) - 1); } catch (std::bad_alloc &) { return 0; } catch (...) { assert(false); } assert(false); } diff --git a/test/libcxx/experimental/filesystem/convert_file_time.sh.cpp b/test/libcxx/experimental/filesystem/convert_file_time.sh.cpp new file mode 100644 index 000000000000..972d51813961 --- /dev/null +++ b/test/libcxx/experimental/filesystem/convert_file_time.sh.cpp @@ -0,0 +1,200 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11 + +// + +// typedef TrivialClock file_time_type; + +// RUN: %build -I%libcxx_src_root/src/experimental/filesystem +// RUN: %run + +#include +#include +#include +#include +#include +#include + +#include "filesystem_time_helper.h" + +using namespace std::chrono; +namespace fs = std::experimental::filesystem; +using fs::file_time_type; +using fs::fs_time_util; + +enum TestKind { TK_64Bit, TK_32Bit, TK_FloatingPoint }; + +template +constexpr TestKind getTestKind() { + if (sizeof(TimeT) == 8 && !std::is_floating_point::value) + return TK_64Bit; + else if (sizeof(TimeT) == 4 && !std::is_floating_point::value) + return TK_32Bit; + else if (std::is_floating_point::value) + return TK_FloatingPoint; + else + assert(false && "test kind not supported"); +} + +template , + TestKind = getTestKind()> +struct check_is_representable; + +template +struct check_is_representable + : public Base { + + using Base::convert_timespec; + using Base::is_representable; + using Base::max_nsec; + using Base::max_seconds; + using Base::min_nsec_timespec; + using Base::min_seconds; + + static constexpr auto max_time_t = std::numeric_limits::max(); + static constexpr auto min_time_t = std::numeric_limits::min(); + + static constexpr bool test_timespec() { + static_assert(is_representable(TimeSpecT{max_seconds, max_nsec}), ""); + static_assert(!is_representable(TimeSpecT{max_seconds + 1, 0}), ""); + static_assert(!is_representable(TimeSpecT{max_seconds, max_nsec + 1}), ""); + static_assert(!is_representable(TimeSpecT{max_time_t, 0}), ""); + static_assert(is_representable(TimeSpecT{min_seconds, 0}), ""); + static_assert( + is_representable(TimeSpecT{min_seconds - 1, min_nsec_timespec}), ""); + static_assert( + is_representable(TimeSpecT{min_seconds - 1, min_nsec_timespec + 1}), + ""); + static_assert( + !is_representable(TimeSpecT{min_seconds - 1, min_nsec_timespec - 1}), + ""); + static_assert(!is_representable(TimeSpecT{min_time_t, 999999999}), ""); + return true; + } + + static constexpr bool test_file_time_type() { + static_assert(Base::is_representable(FileTimeT::max()), ""); + static_assert(Base::is_representable(FileTimeT::min()), ""); + return true; + } + + static constexpr bool test_convert_timespec() { + static_assert(convert_timespec(TimeSpecT{max_seconds, max_nsec}) == + FileTimeT::max(), + ""); + static_assert(convert_timespec(TimeSpecT{max_seconds, max_nsec - 1}) < + FileTimeT::max(), + ""); + static_assert(convert_timespec(TimeSpecT{max_seconds - 1, 999999999}) < + FileTimeT::max(), + ""); + static_assert(convert_timespec(TimeSpecT{ + min_seconds - 1, min_nsec_timespec}) == FileTimeT::min(), + ""); + static_assert( + convert_timespec(TimeSpecT{min_seconds - 1, min_nsec_timespec + 1}) > + FileTimeT::min(), + ""); + static_assert( + convert_timespec(TimeSpecT{min_seconds, 0}) > FileTimeT::min(), ""); + return true; + } + + static bool test() { + static_assert(test_timespec(), ""); + static_assert(test_file_time_type(), ""); + static_assert(test_convert_timespec(), ""); + return true; + } +}; + +template +struct check_is_representable + : public Base { + static constexpr auto max_time_t = std::numeric_limits::max(); + static constexpr auto min_time_t = std::numeric_limits::min(); + + using Base::convert_timespec; + using Base::is_representable; + using Base::max_nsec; + using Base::max_seconds; + using Base::min_nsec_timespec; + using Base::min_seconds; + + static constexpr bool test_timespec() { + static_assert(is_representable(TimeSpecT{max_time_t, 999999999}), ""); + static_assert(is_representable(TimeSpecT{max_time_t, 1000000000}), ""); + static_assert(is_representable(TimeSpecT{min_time_t, 0}), ""); + return true; + } + + static constexpr bool test_file_time_type() { + static_assert(!is_representable(FileTimeT::max()), ""); + static_assert(!is_representable(FileTimeT::min()), ""); + static_assert(is_representable(FileTimeT(seconds(max_time_t))), ""); + static_assert(is_representable(FileTimeT(seconds(min_time_t))), ""); + return true; + } + + static constexpr bool test_convert_timespec() { + // FIXME add tests for 32 bit builds + return true; + } + + static bool test() { + static_assert(test_timespec(), ""); + static_assert(test_file_time_type(), ""); + static_assert(test_convert_timespec(), ""); + return true; + } +}; + +template +struct check_is_representable : public Base { + + static bool test() { return true; } +}; + +template +struct TestTimeSpec { + TimeT tv_sec; + NSecT tv_nsec; +}; + +template +struct TestClock { + typedef Dur duration; + typedef typename duration::rep rep; + typedef typename duration::period period; + typedef std::chrono::time_point time_point; + static constexpr const bool is_steady = false; + + static time_point now() noexcept { return {}; } +}; + +template > +using TestFileTimeT = time_point >; + +int main() { + assert(( + check_is_representable::test())); + assert((check_is_representable, int64_t, + TestTimeSpec >::test())); + assert((check_is_representable, int32_t, + TestTimeSpec >::test())); + + // Test that insane platforms like ppc64 linux, which use long double as time_t, + // at least compile. + assert((check_is_representable, double, + TestTimeSpec >::test())); +} diff --git a/test/libcxx/numerics/c.math/constexpr-fns.pass.cpp b/test/libcxx/numerics/c.math/constexpr-fns.pass.cpp index 9123be1f0990..a58c389cd7ac 100644 --- a/test/libcxx/numerics/c.math/constexpr-fns.pass.cpp +++ b/test/libcxx/numerics/c.math/constexpr-fns.pass.cpp @@ -1,32 +1,32 @@ //===----------------------------------------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // Check that the overloads of std::__libcpp_{isnan,isinf,isfinite} that take // floating-point values are evaluatable from constexpr contexts. // // These functions need to be constexpr in order to be called from CUDA, see // https://reviews.llvm.org/D25403. They don't actually need to be // constexpr-evaluatable, but that's what we check here, since we can't check // true constexpr-ness. // // This fails with gcc because __builtin_isnan and friends, which libcpp_isnan // and friends call, are not themselves constexpr-evaluatable. // // UNSUPPORTED: c++98, c++03 // XFAIL: gcc #include -static_assert(std::__libcpp_isnan(0.) == false, ""); -static_assert(std::__libcpp_isinf(0.0) == false, ""); -static_assert(std::__libcpp_isfinite(0.0) == true, ""); +static_assert(std::__libcpp_isnan_or_builtin(0.) == false, ""); +static_assert(std::__libcpp_isinf_or_builtin(0.0) == false, ""); +static_assert(std::__libcpp_isfinite_or_builtin(0.0) == true, ""); int main() { } diff --git a/test/libcxx/numerics/c.math/fdelayed-template-parsing.sh.cpp b/test/libcxx/numerics/c.math/fdelayed-template-parsing.sh.cpp new file mode 100644 index 000000000000..37aaa2acf1d9 --- /dev/null +++ b/test/libcxx/numerics/c.math/fdelayed-template-parsing.sh.cpp @@ -0,0 +1,28 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// test that cmath builds with -fdelayed-template-parsing + +// REQUIRES: fdelayed-template-parsing + +// RUN: %build -fdelayed-template-parsing +// RUN: %run + +#include +#include + +#include "test_macros.h" + +int main() { + assert(std::isfinite(1.0)); + assert(!std::isinf(1.0)); + assert(!std::isnan(1.0)); +} + +using namespace std; diff --git a/test/libcxx/utilities/optional/optional.object/special_member_gen.pass.cpp b/test/libcxx/utilities/optional/optional.object/special_member_gen.pass.cpp deleted file mode 100644 index 9493d6bb766c..000000000000 --- a/test/libcxx/utilities/optional/optional.object/special_member_gen.pass.cpp +++ /dev/null @@ -1,66 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is dual licensed under the MIT and the University of Illinois Open -// Source Licenses. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -// UNSUPPORTED: c++98, c++03, c++11, c++14 -// - - -#include -#include -#include - -#include "archetypes.hpp" - -template -struct SpecialMemberTest { - using O = std::optional; - - template