Compare commits
36
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1922c8f2b4 | ||
|
|
266d23c9b4 | ||
|
|
381829c2c1 | ||
|
|
f64d7e3130 | ||
|
|
64a428f622 | ||
|
|
a9df4d1bb3 | ||
|
|
c195f66709 | ||
|
|
a09708a487 | ||
|
|
02ef1186d6 | ||
|
|
962fd25b25 | ||
|
|
f7cdd17584 | ||
|
|
e5df7dd77f | ||
|
|
c5ca4f569d | ||
|
|
76a2024e13 | ||
|
|
4b8029a55c | ||
|
|
74700b2c04 | ||
|
|
7d16bc814c | ||
|
|
1f56d0f745 | ||
|
|
87f735237b | ||
|
|
e7b4ab950a | ||
|
|
3b85d48cf1 | ||
|
|
089194ddaf | ||
|
|
7631f72651 | ||
|
|
b62203a4b6 | ||
|
|
fd8b46f79b | ||
|
|
bf5cd2d3b1 | ||
|
|
22839311d1 | ||
|
|
cce54a1bcb | ||
|
|
e8e34d02a6 | ||
|
|
5a0840a737 | ||
|
|
281419de2f | ||
|
|
9bfc0b94ec | ||
|
|
b9b2a2eb46 | ||
|
|
4af4a86520 | ||
|
|
851abee07a | ||
|
|
8d1bdb2e43 |
@@ -0,0 +1,225 @@
|
||||
# simple ci config the idea is to use the latest ubuntu, macos, and windows that github runners give us
|
||||
# test a few different compilers (gcc/clang) in debug and release
|
||||
# and run our tests via ctest
|
||||
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
# Jobs are skipped when ONLY Markdown (*.md) files are changed
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
|
||||
jobs:
|
||||
|
||||
linux:
|
||||
name: '${{ matrix.os }} / ${{ matrix.build-type }} / ${{ matrix.compiler-desc }} '
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
build: [1, 2, 3, 4]
|
||||
include:
|
||||
# -------------------------------------------------------------------
|
||||
# CLANG, Release
|
||||
# -------------------------------------------------------------------
|
||||
- build: 1
|
||||
build-type: Release
|
||||
build-shared: 'ON'
|
||||
cxx-standard: 17
|
||||
cxx-compiler: clang++
|
||||
cxx-flags: ''
|
||||
cc-compiler: clang
|
||||
compiler-desc: clang
|
||||
os: ubuntu-latest
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
# CLANG, Debug
|
||||
# -------------------------------------------------------------------
|
||||
- build: 2
|
||||
build-type: Debug
|
||||
build-shared: 'ON'
|
||||
cxx-standard: 17
|
||||
cxx-compiler: clang++
|
||||
cxx-flags: ''
|
||||
cc-compiler: clang
|
||||
compiler-desc: clang
|
||||
os: ubuntu-latest
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
# gcc, Release
|
||||
# -------------------------------------------------------------------
|
||||
- build: 3
|
||||
build-type: Release
|
||||
build-shared: 'ON'
|
||||
cxx-standard: 17
|
||||
cxx-compiler: g++
|
||||
cxx-flags: ''
|
||||
cc-compiler: gcc
|
||||
compiler-desc: gcc
|
||||
os: ubuntu-latest
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
# gcc, Debug
|
||||
# -------------------------------------------------------------------
|
||||
- build: 4
|
||||
build-type: Debug
|
||||
build-shared: 'ON'
|
||||
cxx-standard: 17
|
||||
cxx-compiler: g++
|
||||
cxx-flags: ''
|
||||
cc-compiler: gcc
|
||||
compiler-desc: gcc
|
||||
os: ubuntu-latest
|
||||
|
||||
env:
|
||||
CXX: ${{ matrix.cxx-compiler }}
|
||||
CC: ${{ matrix.cc-compiler }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- name: Create build directories
|
||||
run: |
|
||||
mkdir _install
|
||||
mkdir _build
|
||||
- name: Configure
|
||||
run: |
|
||||
cmake .. \
|
||||
-DCMAKE_INSTALL_PREFIX=${{ github.workspace }}/_install \
|
||||
-DCMAKE_BUILD_TYPE=${{ matrix.build-type }} \
|
||||
-DCMAKE_CXX_STANDARD=${{ matrix.cxx-standard }} \
|
||||
-DCMAKE_CXX_FLAGS=${{ matrix.cxx-flags }} \
|
||||
-DCMAKE_VERBOSE_MAKEFILE:BOOL='OFF' \
|
||||
-DBUILD_SHARED_LIBS=${{ matrix.build-shared }} \
|
||||
working-directory: _build
|
||||
- name: Build
|
||||
run: |
|
||||
cmake --build . \
|
||||
--config ${{ matrix.build-type }}
|
||||
working-directory: _build
|
||||
- name: Test
|
||||
run: |
|
||||
ctest --build-config ${{ matrix.build-type }} --verbose
|
||||
working-directory: _build
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# macOS
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
macos:
|
||||
name: '${{ matrix.os }} / ${{ matrix.build-type }}'
|
||||
runs-on: macos-latest
|
||||
strategy:
|
||||
matrix:
|
||||
build: [1, 2]
|
||||
include:
|
||||
|
||||
# Release
|
||||
- build: 1
|
||||
build-type: Release
|
||||
build-shared: 'ON'
|
||||
cxx-standard: 17
|
||||
cxx-flags: ''
|
||||
os: macos-latest
|
||||
|
||||
# Debug
|
||||
- build: 2
|
||||
build-type: Debug
|
||||
build-shared: 'ON'
|
||||
build-docs: 'OFF'
|
||||
cxx-standard: 17
|
||||
cxx-flags: ''
|
||||
os: macos-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- name: Create build directories
|
||||
run: |
|
||||
mkdir _install
|
||||
mkdir _build
|
||||
|
||||
- name: Configure
|
||||
run: |
|
||||
cmake ../. \
|
||||
-DCMAKE_INSTALL_PREFIX=${{ github.workspace }}/_install \
|
||||
-DCMAKE_BUILD_TYPE=${{ matrix.build-type }} \
|
||||
-DCMAKE_CXX_STANDARD=${{ matrix.cxx-standard }} \
|
||||
-DCMAKE_CXX_FLAGS=${{ matrix.cxx-flags }} \
|
||||
-DCMAKE_VERBOSE_MAKEFILE:BOOL='OFF' \
|
||||
-DBUILD_SHARED_LIBS=${{ matrix.build-shared }} \
|
||||
working-directory: _build
|
||||
- name: Build
|
||||
run: |
|
||||
cmake --build . \
|
||||
--config ${{ matrix.build-type }} \
|
||||
working-directory: _build
|
||||
- name: Test
|
||||
run: |
|
||||
ctest --build-config ${{ matrix.build-type }} --verbose
|
||||
working-directory: _build
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Windows
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
windows:
|
||||
name: '${{ matrix.os }} / ${{ matrix.build-type }}'
|
||||
runs-on: windows-latest
|
||||
strategy:
|
||||
matrix:
|
||||
build: [1, 2]
|
||||
include:
|
||||
|
||||
# Release
|
||||
- build: 1
|
||||
build-type: Release
|
||||
build-shared: 'ON'
|
||||
cxx-standard: 17
|
||||
cxx-flags: ''
|
||||
os: windows-latest
|
||||
|
||||
# Debug
|
||||
- build: 2
|
||||
build-type: Debug
|
||||
build-shared: 'ON'
|
||||
cxx-standard: 17
|
||||
cxx-flags: ''
|
||||
os: windows-latest
|
||||
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- name: Create build directories
|
||||
run: |
|
||||
mkdir _install
|
||||
mkdir _build
|
||||
shell: bash
|
||||
- name: Configure
|
||||
# the windows build needs the -DCMAKE_WINDOWS_EXPORT_ALL_SYMBOLS to work
|
||||
run: |
|
||||
cmake ../. \
|
||||
-DCMAKE_INSTALL_PREFIX=${{ github.workspace }}/_install \
|
||||
-DCMAKE_WINDOWS_EXPORT_ALL_SYMBOLS='ON'\
|
||||
-DCMAKE_BUILD_TYPE=${{ matrix.build-type }} \
|
||||
-DCMAKE_CXX_STANDARD=${{ matrix.cxx-standard }} \
|
||||
-DCMAKE_CXX_FLAGS=${{ matrix.cxx-flags }} \
|
||||
-DCMAKE_VERBOSE_MAKEFILE:BOOL='OFF' \
|
||||
-DBUILD_SHARED_LIBS=${{ matrix.build-shared }} \
|
||||
shell: bash
|
||||
working-directory: _build
|
||||
- name: Build
|
||||
run: |
|
||||
cmake --build . \
|
||||
--config ${{ matrix.build-type }}
|
||||
shell: bash
|
||||
working-directory: _build
|
||||
- name: Test
|
||||
run: |
|
||||
ctest -C ${{ matrix.build-type }}
|
||||
shell: bash
|
||||
working-directory: _build
|
||||
@@ -0,0 +1,145 @@
|
||||
name: Meson
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
|
||||
jobs:
|
||||
meson-build-and-tests:
|
||||
runs-on: ${{ matrix.platform }}
|
||||
name: ${{ matrix.platform }}, ${{ matrix.mode.name }} ${{ matrix.flavor }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
flavor:
|
||||
- debug
|
||||
- release
|
||||
mode:
|
||||
- name: default
|
||||
extra_envs: {}
|
||||
|
||||
# Alternative compiler setups
|
||||
- name: gcc
|
||||
extra_envs:
|
||||
CC: gcc
|
||||
CXX: g++
|
||||
- name: clang
|
||||
extra_envs:
|
||||
CC: clang
|
||||
CXX: clang++
|
||||
|
||||
- name: sanitize
|
||||
args: >-
|
||||
"-Db_sanitize=address,undefined"
|
||||
extra_envs: {}
|
||||
|
||||
# This is for MSVC, which only supports AddressSanitizer.
|
||||
# https://learn.microsoft.com/en-us/cpp/sanitizers/
|
||||
- name: sanitize+asanonly
|
||||
args: -Db_sanitize=address
|
||||
extra_envs:
|
||||
ASAN_OPTIONS: report_globals=0:halt_on_error=1:abort_on_error=1:print_summary=1
|
||||
|
||||
- name: clang+sanitize
|
||||
args: >-
|
||||
-Db_lundef=false "-Db_sanitize=address,undefined"
|
||||
extra_envs:
|
||||
CC: clang
|
||||
CXX: clang++
|
||||
|
||||
# default clang on GitHub hosted runners is from MSYS2.
|
||||
# Use Visual Studio supplied clang-cl instead.
|
||||
- name: clang-cl+sanitize
|
||||
args: >-
|
||||
"-Db_sanitize=address,undefined"
|
||||
extra_envs:
|
||||
CC: clang-cl
|
||||
CXX: clang-cl
|
||||
platform:
|
||||
- ubuntu-22.04
|
||||
- windows-2022
|
||||
- macos-latest
|
||||
|
||||
exclude:
|
||||
# clang-cl only makes sense on windows.
|
||||
- platform: ubuntu-22.04
|
||||
mode:
|
||||
name: clang-cl+sanitize
|
||||
- platform: macos-latest
|
||||
mode:
|
||||
name: clang-cl+sanitize
|
||||
|
||||
# Use clang-cl instead of MSYS2 clang.
|
||||
#
|
||||
# we already tested clang+sanitize on linux,
|
||||
# if this doesn't work, it should be an issue for MSYS2 team to consider.
|
||||
- platform: windows-2022
|
||||
mode:
|
||||
name: clang
|
||||
- platform: windows-2022
|
||||
mode:
|
||||
name: clang+sanitize
|
||||
|
||||
# MSVC-only sanitizers
|
||||
- platform: ubuntu-22.04
|
||||
mode:
|
||||
name: sanitize+asanonly
|
||||
- platform: macos-latest
|
||||
mode:
|
||||
name: sanitize+asanonly
|
||||
- platform: windows-2022
|
||||
mode:
|
||||
name: sanitize
|
||||
|
||||
# clang is the default on macos
|
||||
# also gcc is an alias to clang
|
||||
- platform: macos-latest
|
||||
mode:
|
||||
name: clang
|
||||
- platform: macos-latest
|
||||
mode:
|
||||
name: gcc
|
||||
|
||||
# gcc is the default on linux
|
||||
- platform: ubuntu-22.04
|
||||
mode:
|
||||
name: gcc
|
||||
|
||||
# only run sanitizer tests on linux
|
||||
#
|
||||
# gcc/clang's codegen shouldn't massively change across platforms,
|
||||
# and linux supports most of the sanitizers.
|
||||
- platform: macos-latest
|
||||
mode:
|
||||
name: clang+sanitize
|
||||
- platform: macos-latest
|
||||
mode:
|
||||
name: sanitize
|
||||
steps:
|
||||
- name: Setup meson
|
||||
run: |
|
||||
pipx install meson ninja
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
- name: Activate MSVC and Configure
|
||||
if: ${{ matrix.platform == 'windows-2022' }}
|
||||
env: ${{ matrix.mode.extra_envs }}
|
||||
run: |
|
||||
meson setup build-${{ matrix.flavor }} --buildtype=${{ matrix.flavor }} -Ddefault_library=static ${{ matrix.mode.args }} --vsenv
|
||||
- name: Configuring
|
||||
if: ${{ matrix.platform != 'windows-2022' }}
|
||||
env: ${{ matrix.mode.extra_envs }}
|
||||
run: |
|
||||
meson setup build-${{ matrix.flavor }} --buildtype=${{ matrix.flavor }} ${{ matrix.mode.args }}
|
||||
- name: Building
|
||||
run: |
|
||||
meson compile -C build-${{ matrix.flavor }}
|
||||
- name: Running tests
|
||||
env: ${{ matrix.mode.extra_envs }}
|
||||
run: |
|
||||
meson test -C build-${{ matrix.flavor }} --timeout-multiplier 0
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: failure()
|
||||
with:
|
||||
name: ${{ matrix.platform }}-${{ matrix.mode.name }}-${{ matrix.flavor }}-logs
|
||||
path: build-${{ matrix.flavor }}/meson-logs
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
project(pystring LANGUAGES CXX VERSION 1.2.0)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
|
||||
option (BUILD_SHARED_LIBS "Build shared libraries (set to OFF to build static libs)" ON)
|
||||
|
||||
# If the user hasn't configured cmake with an explicit
|
||||
# -DCMAKE_INSTALL_PREFIX=..., then set it to safely install into ./dist, to
|
||||
# help prevent the user from accidentally writing over /usr/local or whatever.
|
||||
if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT
|
||||
AND PROJECT_IS_TOP_LEVEL)
|
||||
set (CMAKE_INSTALL_PREFIX "${PROJECT_SOURCE_DIR}/dist" CACHE PATH
|
||||
"Installation location" FORCE)
|
||||
endif()
|
||||
message (STATUS "Installation path will be ${CMAKE_INSTALL_PREFIX}")
|
||||
include(GNUInstallDirs)
|
||||
|
||||
# --- Compiled library target: pystring::pystring ---
|
||||
add_library(pystring
|
||||
pystring.cpp
|
||||
pystring.h
|
||||
)
|
||||
|
||||
set_target_properties(pystring PROPERTIES
|
||||
VERSION ${PROJECT_VERSION}
|
||||
SOVERSION ${PROJECT_VERSION_MAJOR}
|
||||
)
|
||||
|
||||
target_include_directories(pystring PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
)
|
||||
|
||||
install(TARGETS pystring
|
||||
EXPORT pystringTargets
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
)
|
||||
|
||||
|
||||
# --- Header-only target: pystring::pystring_header_only ---
|
||||
add_library(pystring_header_only INTERFACE)
|
||||
|
||||
target_compile_definitions(pystring_header_only INTERFACE PYSTRING_HEADER_ONLY)
|
||||
|
||||
target_include_directories(pystring_header_only INTERFACE
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
)
|
||||
|
||||
install(TARGETS pystring_header_only
|
||||
EXPORT pystringTargets
|
||||
)
|
||||
|
||||
install(FILES pystring.h pystring_impl.h
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}
|
||||
)
|
||||
|
||||
# --- Export & package config ---
|
||||
install(EXPORT pystringTargets
|
||||
FILE pystringTargets.cmake
|
||||
NAMESPACE pystring::
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/pystring
|
||||
)
|
||||
|
||||
include(CMakePackageConfigHelpers)
|
||||
|
||||
configure_package_config_file(
|
||||
cmake/pystringConfig.cmake.in
|
||||
pystringConfig.cmake
|
||||
INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/pystring
|
||||
)
|
||||
|
||||
write_basic_package_version_file(
|
||||
pystringConfigVersion.cmake
|
||||
VERSION ${PROJECT_VERSION}
|
||||
COMPATIBILITY SameMajorVersion
|
||||
)
|
||||
|
||||
install(FILES
|
||||
${CMAKE_CURRENT_BINARY_DIR}/pystringConfig.cmake
|
||||
${CMAKE_CURRENT_BINARY_DIR}/pystringConfigVersion.cmake
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/pystring
|
||||
)
|
||||
|
||||
# --- Tests ---
|
||||
add_executable(pystring_test test.cpp)
|
||||
target_link_libraries(pystring_test pystring)
|
||||
|
||||
add_executable(pystring_test_header_only test.cpp)
|
||||
target_link_libraries(pystring_test_header_only pystring_header_only)
|
||||
|
||||
# Compile-time check that PYSTRING_HEADER_ONLY propagates correctly
|
||||
add_executable(pystring_test_header_only_define test_header_only_define.cpp)
|
||||
target_link_libraries(pystring_test_header_only_define pystring_header_only)
|
||||
|
||||
enable_testing()
|
||||
add_test(NAME PyStringTest COMMAND pystring_test)
|
||||
add_test(NAME PyStringTestHeaderOnly COMMAND pystring_test_header_only)
|
||||
@@ -1,30 +1,27 @@
|
||||
Copyright (c) 2008-2010, Sony Pictures Imageworks Inc
|
||||
All rights reserved.
|
||||
Copyright (c) 2008-present Contributors to the Pystring project.
|
||||
All Rights Reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
Neither the name of the organization Sony Pictures Imageworks nor the
|
||||
names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
LIBTOOL = libtool
|
||||
LIBDIR = /usr/lib
|
||||
CXX = g++
|
||||
CXXFLAGS = -g -O3 -Wall -Wextra -Wshadow -Wconversion -Wcast-qual -Wformat=2
|
||||
LIBTOOL ?= libtool
|
||||
PREFIX ?= /usr
|
||||
INCLUDEDIR ?= ${PREFIX}/include/pystring
|
||||
LIBDIR ?= ${PREFIX}/lib
|
||||
CXX ?= g++
|
||||
CXXFLAGS ?= -g -O3 -Wall -Wextra -Wshadow -Wconversion -Wcast-qual -Wformat=2
|
||||
|
||||
all: libpystring.la
|
||||
|
||||
@@ -12,7 +14,8 @@ libpystring.la: pystring.lo
|
||||
$(LIBTOOL) --mode=link --tag=CXX $(CXX) -o $@ $< -rpath $(LIBDIR)
|
||||
|
||||
install: libpystring.la
|
||||
$(LIBTOOL) --mode=install install -c $< $(LIBDIR)/$<
|
||||
$(LIBTOOL) --mode=install install -Dm755 $< $(DESTDIR)$(LIBDIR)/$<
|
||||
$(LIBTOOL) --mode=install install -Dm644 pystring.h $(DESTDIR)$(INCLUDEDIR)/pystring.h
|
||||
|
||||
clean:
|
||||
$(RM) -fr pystring.lo pystring.o libpystring.la .libs
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
Pystring is a collection of C++ functions which match the interface and behavior of python's string class methods using std::string. Implemented in C++, it does not require or make use of a python interpreter. It provides convenience and familiarity for common string operations not included in the standard C++ library. It's also useful in environments where both C++ and python are used.
|
||||
|
||||
Overlapping functionality (such as index and slice/substr) of std::string is included to match python interfaces.
|
||||
|
||||
Originally developed at Sony Pictures Imageworks.
|
||||
http://opensource.imageworks.com/
|
||||
|
||||
Note: Despite the infrequent updates, this repo is not dead/abandoned - just stable! We use it every day at Imageworks.
|
||||
@@ -0,0 +1,17 @@
|
||||
[](https://repology.org/project/pystring/versions)
|
||||
|
||||
Pystring is a collection of C++ functions which match the interface and
|
||||
behavior of python's string class methods using std::string. Implemented in
|
||||
C++, it does not require or make use of a python interpreter. It provides
|
||||
convenience and familiarity for common string operations not included in the
|
||||
standard C++ library. It's also useful in environments where both C++ and
|
||||
python are used.
|
||||
|
||||
Overlapping functionality (such as index and slice/substr) of std::string is
|
||||
included to match python interfaces.
|
||||
|
||||
Originally developed at Sony Pictures Imageworks.
|
||||
http://opensource.imageworks.com/
|
||||
|
||||
Note: Despite the infrequent updates, this repo is not dead/abandoned - just
|
||||
stable! We use it every day at Imageworks.
|
||||
@@ -0,0 +1,8 @@
|
||||
@PACKAGE_INIT@
|
||||
|
||||
# Prevent double-definition errors
|
||||
if(NOT TARGET pystring::pystring AND NOT TARGET pystring::pystring_header_only)
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/pystringTargets.cmake")
|
||||
endif()
|
||||
|
||||
check_required_components(pystring)
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
project(
|
||||
'pystring',
|
||||
'cpp',
|
||||
version: '1.2.0',
|
||||
license: 'BSD-3-Clause',
|
||||
license_files: 'LICENSE',
|
||||
meson_version: '>=1.3',
|
||||
default_options: ['cpp_std=c++17,c++11', 'warning_level=3'],
|
||||
)
|
||||
|
||||
inc = include_directories('.')
|
||||
hdrs = files('pystring.h')
|
||||
|
||||
# --- Compiled library target ---
|
||||
pystring_lib = library(
|
||||
'pystring',
|
||||
files('pystring.cpp'),
|
||||
implicit_include_directories: false,
|
||||
include_directories: inc,
|
||||
version: meson.project_version(),
|
||||
install: true,
|
||||
)
|
||||
|
||||
pystring_dep = declare_dependency(
|
||||
link_with: pystring_lib,
|
||||
include_directories: inc,
|
||||
)
|
||||
|
||||
install_headers(hdrs, subdir: 'pystring')
|
||||
|
||||
pkgconfig = import('pkgconfig')
|
||||
pkgconfig.generate(
|
||||
pystring_lib,
|
||||
description: 'C++ functions matching the interface and behavior of python string methods with std::string',
|
||||
)
|
||||
|
||||
# --- Header-only target ---
|
||||
pystring_header_only_dep = declare_dependency(
|
||||
include_directories: inc,
|
||||
compile_args: ['-DPYSTRING_HEADER_ONLY'],
|
||||
)
|
||||
|
||||
install_headers(hdrs, files('pystring_impl.h'), subdir: 'pystring')
|
||||
|
||||
# --- Override default dependency ---
|
||||
meson.override_dependency('pystring', pystring_dep)
|
||||
|
||||
# --- Tests ---
|
||||
test(
|
||||
'PyStringTest',
|
||||
executable(
|
||||
'pystring_test',
|
||||
'test.cpp',
|
||||
dependencies: pystring_dep,
|
||||
build_by_default: false,
|
||||
),
|
||||
)
|
||||
|
||||
test(
|
||||
'PyStringTestHeaderOnly',
|
||||
executable(
|
||||
'pystring_test_header_only',
|
||||
'test.cpp',
|
||||
dependencies: pystring_header_only_dep,
|
||||
build_by_default: false,
|
||||
),
|
||||
)
|
||||
|
||||
# Compile-time check that PYSTRING_HEADER_ONLY propagates correctly
|
||||
executable(
|
||||
'pystring_test_header_only_define',
|
||||
'test_header_only_define.cpp',
|
||||
dependencies: pystring_header_only_dep,
|
||||
build_by_default: true,
|
||||
)
|
||||
+7
-1662
File diff suppressed because it is too large
Load Diff
+123
-99
@@ -1,39 +1,17 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (c) 2008-2010, Sony Pictures Imageworks Inc
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// Neither the name of the organization Sony Pictures Imageworks nor the
|
||||
// names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS
|
||||
// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER
|
||||
// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright Contributors to the Pystring project.
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
// https://github.com/imageworks/pystring/blob/master/LICENSE
|
||||
|
||||
|
||||
#ifndef INCLUDED_PYSTRING_H
|
||||
#define INCLUDED_PYSTRING_H
|
||||
|
||||
#ifdef PYSTRING_HEADER_ONLY
|
||||
#define PYSTRING_INLINE inline
|
||||
#else
|
||||
#define PYSTRING_INLINE
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -60,102 +38,102 @@ namespace pystring
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Return a copy of the string with only its first character capitalized.
|
||||
///
|
||||
std::string capitalize( const std::string & str );
|
||||
PYSTRING_INLINE std::string capitalize( const std::string & str );
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Return centered in a string of length width. Padding is done using spaces.
|
||||
///
|
||||
std::string center( const std::string & str, int width );
|
||||
PYSTRING_INLINE std::string center( const std::string & str, int width );
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Return the number of occurrences of substring sub in string S[start:end]. Optional
|
||||
/// arguments start and end are interpreted as in slice notation.
|
||||
///
|
||||
int count( const std::string & str, const std::string & substr, int start = 0, int end = MAX_32BIT_INT);
|
||||
PYSTRING_INLINE int count( const std::string & str, const std::string & substr, int start = 0, int end = MAX_32BIT_INT);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Return True if the string ends with the specified suffix, otherwise return False. With
|
||||
/// optional start, test beginning at that position. With optional end, stop comparing at that position.
|
||||
///
|
||||
bool endswith( const std::string & str, const std::string & suffix, int start = 0, int end = MAX_32BIT_INT );
|
||||
PYSTRING_INLINE bool endswith( const std::string & str, const std::string & suffix, int start = 0, int end = MAX_32BIT_INT );
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Return a copy of the string where all tab characters are expanded using spaces. If tabsize
|
||||
/// is not given, a tab size of 8 characters is assumed.
|
||||
///
|
||||
std::string expandtabs( const std::string & str, int tabsize = 8);
|
||||
PYSTRING_INLINE std::string expandtabs( const std::string & str, int tabsize = 8);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Return the lowest index in the string where substring sub is found, such that sub is
|
||||
/// contained in the range [start, end). Optional arguments start and end are interpreted as
|
||||
/// in slice notation. Return -1 if sub is not found.
|
||||
///
|
||||
int find( const std::string & str, const std::string & sub, int start = 0, int end = MAX_32BIT_INT );
|
||||
PYSTRING_INLINE int find( const std::string & str, const std::string & sub, int start = 0, int end = MAX_32BIT_INT );
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Synonym of find right now. Python version throws exceptions. This one currently doesn't
|
||||
///
|
||||
int index( const std::string & str, const std::string & sub, int start = 0, int end = MAX_32BIT_INT );
|
||||
PYSTRING_INLINE int index( const std::string & str, const std::string & sub, int start = 0, int end = MAX_32BIT_INT );
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Return true if all characters in the string are alphanumeric and there is at least one
|
||||
/// character, false otherwise.
|
||||
///
|
||||
bool isalnum( const std::string & str );
|
||||
PYSTRING_INLINE bool isalnum( const std::string & str );
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Return true if all characters in the string are alphabetic and there is at least one
|
||||
/// character, false otherwise
|
||||
///
|
||||
bool isalpha( const std::string & str );
|
||||
PYSTRING_INLINE bool isalpha( const std::string & str );
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Return true if all characters in the string are digits and there is at least one
|
||||
/// character, false otherwise.
|
||||
///
|
||||
bool isdigit( const std::string & str );
|
||||
PYSTRING_INLINE bool isdigit( const std::string & str );
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Return true if all cased characters in the string are lowercase and there is at least one
|
||||
/// cased character, false otherwise.
|
||||
///
|
||||
bool islower( const std::string & str );
|
||||
PYSTRING_INLINE bool islower( const std::string & str );
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Return true if there are only whitespace characters in the string and there is at least
|
||||
/// one character, false otherwise.
|
||||
///
|
||||
bool isspace( const std::string & str );
|
||||
PYSTRING_INLINE bool isspace( const std::string & str );
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Return true if the string is a titlecased string and there is at least one character,
|
||||
/// i.e. uppercase characters may only follow uncased characters and lowercase characters only
|
||||
/// cased ones. Return false otherwise.
|
||||
///
|
||||
bool istitle( const std::string & str );
|
||||
PYSTRING_INLINE bool istitle( const std::string & str );
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Return true if all cased characters in the string are uppercase and there is at least one
|
||||
/// cased character, false otherwise.
|
||||
///
|
||||
bool isupper( const std::string & str );
|
||||
PYSTRING_INLINE bool isupper( const std::string & str );
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Return a string which is the concatenation of the strings in the sequence seq.
|
||||
/// The separator between elements is the str argument
|
||||
///
|
||||
std::string join( const std::string & str, const std::vector< std::string > & seq );
|
||||
PYSTRING_INLINE std::string join( const std::string & str, const std::vector< std::string > & seq );
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Return the string left justified in a string of length width. Padding is done using
|
||||
/// spaces. The original string is returned if width is less than str.size().
|
||||
///
|
||||
std::string ljust( const std::string & str, int width );
|
||||
PYSTRING_INLINE std::string ljust( const std::string & str, int width );
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Return a copy of the string converted to lowercase.
|
||||
///
|
||||
std::string lower( const std::string & str );
|
||||
PYSTRING_INLINE std::string lower( const std::string & str );
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Return a copy of the string with leading characters removed. If chars is omitted or None,
|
||||
@@ -163,13 +141,13 @@ namespace pystring
|
||||
/// characters in the string will be stripped from the beginning of the string this method
|
||||
/// is called on (argument "str" ).
|
||||
///
|
||||
std::string lstrip( const std::string & str, const std::string & chars = "" );
|
||||
PYSTRING_INLINE std::string lstrip( const std::string & str, const std::string & chars = "" );
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Return a copy of the string, concatenated N times, together.
|
||||
/// Corresponds to the __mul__ operator.
|
||||
///
|
||||
std::string mul( const std::string & str, int n);
|
||||
PYSTRING_INLINE std::string mul( const std::string & str, int n);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Split the string around first occurance of sep.
|
||||
@@ -177,32 +155,50 @@ namespace pystring
|
||||
/// be the text before sep, sep itself, and the remaining text. If sep is
|
||||
/// not found, the original string will be returned with two empty strings.
|
||||
///
|
||||
void partition( const std::string & str, const std::string & sep, std::vector< std::string > & result );
|
||||
PYSTRING_INLINE void partition( const std::string & str, const std::string & sep, std::vector< std::string > & result );
|
||||
inline std::vector< std::string > partition( const std::string & str, const std::string & sep )
|
||||
{
|
||||
std::vector< std::string > result;
|
||||
partition( str, sep, result );
|
||||
return result;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief If str starts with prefix return a copy of the string with prefix at the start
|
||||
/// removed otherwise return an unmodified copy of the string.
|
||||
///
|
||||
PYSTRING_INLINE std::string removeprefix( const std::string & str, const std::string & prefix );
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief If str ends with suffix return a copy of the string with suffix at the end removed
|
||||
/// otherwise return an unmodified copy of the string.
|
||||
///
|
||||
PYSTRING_INLINE std::string removesuffix( const std::string & str, const std::string & suffix );
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Return a copy of the string with all occurrences of substring old replaced by new. If
|
||||
/// the optional argument count is given, only the first count occurrences are replaced.
|
||||
///
|
||||
std::string replace( const std::string & str, const std::string & oldstr, const std::string & newstr, int count = -1);
|
||||
PYSTRING_INLINE std::string replace( const std::string & str, const std::string & oldstr, const std::string & newstr, int count = -1);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Return the highest index in the string where substring sub is found, such that sub is
|
||||
/// contained within s[start,end]. Optional arguments start and end are interpreted as in
|
||||
/// slice notation. Return -1 on failure.
|
||||
///
|
||||
int rfind( const std::string & str, const std::string & sub, int start = 0, int end = MAX_32BIT_INT );
|
||||
PYSTRING_INLINE int rfind( const std::string & str, const std::string & sub, int start = 0, int end = MAX_32BIT_INT );
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Currently a synonym of rfind. The python version raises exceptions. This one currently
|
||||
/// does not
|
||||
///
|
||||
int rindex( const std::string & str, const std::string & sub, int start = 0, int end = MAX_32BIT_INT );
|
||||
PYSTRING_INLINE int rindex( const std::string & str, const std::string & sub, int start = 0, int end = MAX_32BIT_INT );
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Return the string right justified in a string of length width. Padding is done using
|
||||
/// spaces. The original string is returned if width is less than str.size().
|
||||
///
|
||||
std::string rjust( const std::string & str, int width);
|
||||
PYSTRING_INLINE std::string rjust( const std::string & str, int width);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Split the string around last occurance of sep.
|
||||
@@ -210,21 +206,33 @@ namespace pystring
|
||||
/// be the text before sep, sep itself, and the remaining text. If sep is
|
||||
/// not found, the original string will be returned with two empty strings.
|
||||
///
|
||||
void rpartition( const std::string & str, const std::string & sep, std::vector< std::string > & result );
|
||||
PYSTRING_INLINE void rpartition( const std::string & str, const std::string & sep, std::vector< std::string > & result );
|
||||
inline std::vector< std::string > rpartition ( const std::string & str, const std::string & sep )
|
||||
{
|
||||
std::vector< std::string > result;
|
||||
rpartition( str, sep, result );
|
||||
return result;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Return a copy of the string with trailing characters removed. If chars is "", whitespace
|
||||
/// characters are removed. If not "", the characters in the string will be stripped from the
|
||||
/// end of the string this method is called on.
|
||||
///
|
||||
std::string rstrip( const std::string & str, const std::string & chars = "" );
|
||||
PYSTRING_INLINE std::string rstrip( const std::string & str, const std::string & chars = "" );
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Fills the "result" list with the words in the string, using sep as the delimiter string.
|
||||
/// If maxsplit is > -1, at most maxsplit splits are done. If sep is "",
|
||||
/// any whitespace string is a separator.
|
||||
///
|
||||
void split( const std::string & str, std::vector< std::string > & result, const std::string & sep = "", int maxsplit = -1);
|
||||
PYSTRING_INLINE void split( const std::string & str, std::vector< std::string > & result, const std::string & sep = "", int maxsplit = -1);
|
||||
inline std::vector< std::string > split( const std::string & str, const std::string & sep = "", int maxsplit = -1)
|
||||
{
|
||||
std::vector< std::string > result;
|
||||
split( str, result, sep, maxsplit );
|
||||
return result;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Fills the "result" list with the words in the string, using sep as the delimiter string.
|
||||
@@ -233,61 +241,73 @@ namespace pystring
|
||||
/// If maxsplit is > -1, at most maxsplit splits are done. If sep is "",
|
||||
/// any whitespace string is a separator.
|
||||
///
|
||||
void rsplit( const std::string & str, std::vector< std::string > & result, const std::string & sep = "", int maxsplit = -1);
|
||||
PYSTRING_INLINE void rsplit( const std::string & str, std::vector< std::string > & result, const std::string & sep = "", int maxsplit = -1);
|
||||
inline std::vector< std::string > rsplit( const std::string & str, const std::string & sep = "", int maxsplit = -1)
|
||||
{
|
||||
std::vector< std::string > result;
|
||||
rsplit( str, result, sep, maxsplit);
|
||||
return result;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Return a list of the lines in the string, breaking at line boundaries. Line breaks
|
||||
/// are not included in the resulting list unless keepends is given and true.
|
||||
///
|
||||
void splitlines( const std::string & str, std::vector< std::string > & result, bool keepends = false );
|
||||
PYSTRING_INLINE void splitlines( const std::string & str, std::vector< std::string > & result, bool keepends = false );
|
||||
inline std::vector< std::string > splitlines( const std::string & str, bool keepends = false )
|
||||
{
|
||||
std::vector< std::string > result;
|
||||
splitlines( str, result, keepends);
|
||||
return result;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Return True if string starts with the prefix, otherwise return False. With optional start,
|
||||
/// test string beginning at that position. With optional end, stop comparing string at that
|
||||
/// position
|
||||
///
|
||||
bool startswith( const std::string & str, const std::string & prefix, int start = 0, int end = MAX_32BIT_INT );
|
||||
PYSTRING_INLINE bool startswith( const std::string & str, const std::string & prefix, int start = 0, int end = MAX_32BIT_INT );
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Return a copy of the string with leading and trailing characters removed. If chars is "",
|
||||
/// whitespace characters are removed. If given not "", the characters in the string will be
|
||||
/// stripped from the both ends of the string this method is called on.
|
||||
///
|
||||
std::string strip( const std::string & str, const std::string & chars = "" );
|
||||
PYSTRING_INLINE std::string strip( const std::string & str, const std::string & chars = "" );
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Return a copy of the string with uppercase characters converted to lowercase and vice versa.
|
||||
///
|
||||
std::string swapcase( const std::string & str );
|
||||
PYSTRING_INLINE std::string swapcase( const std::string & str );
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Return a titlecased version of the string: words start with uppercase characters,
|
||||
/// all remaining cased characters are lowercase.
|
||||
///
|
||||
std::string title( const std::string & str );
|
||||
PYSTRING_INLINE std::string title( const std::string & str );
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Return a copy of the string where all characters occurring in the optional argument
|
||||
/// deletechars are removed, and the remaining characters have been mapped through the given
|
||||
/// translation table, which must be a string of length 256.
|
||||
///
|
||||
std::string translate( const std::string & str, const std::string & table, const std::string & deletechars = "");
|
||||
PYSTRING_INLINE std::string translate( const std::string & str, const std::string & table, const std::string & deletechars = "");
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Return a copy of the string converted to uppercase.
|
||||
///
|
||||
std::string upper( const std::string & str );
|
||||
PYSTRING_INLINE std::string upper( const std::string & str );
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Return the numeric string left filled with zeros in a string of length width. The original
|
||||
/// string is returned if width is less than str.size().
|
||||
///
|
||||
std::string zfill( const std::string & str, int width );
|
||||
PYSTRING_INLINE std::string zfill( const std::string & str, int width );
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief function matching python's slice functionality.
|
||||
///
|
||||
std::string slice( const std::string & str, int start = 0, int end = MAX_32BIT_INT);
|
||||
PYSTRING_INLINE std::string slice( const std::string & str, int start = 0, int end = MAX_32BIT_INT);
|
||||
|
||||
///
|
||||
/// @ }
|
||||
@@ -325,26 +345,26 @@ namespace path
|
||||
/// program; where basename for '/foo/bar/' returns 'bar', the basename() function returns an
|
||||
/// empty string ('').
|
||||
|
||||
std::string basename(const std::string & path);
|
||||
std::string basename_nt(const std::string & path);
|
||||
std::string basename_posix(const std::string & path);
|
||||
PYSTRING_INLINE std::string basename(const std::string & path);
|
||||
PYSTRING_INLINE std::string basename_nt(const std::string & path);
|
||||
PYSTRING_INLINE std::string basename_posix(const std::string & path);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Return the directory name of pathname path. This is the first half of the pair
|
||||
/// returned by split(path).
|
||||
|
||||
std::string dirname(const std::string & path);
|
||||
std::string dirname_nt(const std::string & path);
|
||||
std::string dirname_posix(const std::string & path);
|
||||
PYSTRING_INLINE std::string dirname(const std::string & path);
|
||||
PYSTRING_INLINE std::string dirname_nt(const std::string & path);
|
||||
PYSTRING_INLINE std::string dirname_posix(const std::string & path);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Return True if path is an absolute pathname. On Unix, that means it begins with a
|
||||
/// slash, on Windows that it begins with a (back)slash after chopping off a potential drive
|
||||
/// letter.
|
||||
|
||||
bool isabs(const std::string & path);
|
||||
bool isabs_nt(const std::string & path);
|
||||
bool isabs_posix(const std::string & s);
|
||||
PYSTRING_INLINE bool isabs(const std::string & path);
|
||||
PYSTRING_INLINE bool isabs_nt(const std::string & path);
|
||||
PYSTRING_INLINE bool isabs_posix(const std::string & s);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Return a normalized absolutized version of the pathname path.
|
||||
@@ -352,9 +372,9 @@ namespace path
|
||||
/// NOTE: This differs from the interface of the python equivalent in that it requires you
|
||||
/// to pass in the current working directory as an argument.
|
||||
|
||||
std::string abspath(const std::string & path, const std::string & cwd);
|
||||
std::string abspath_nt(const std::string & path, const std::string & cwd);
|
||||
std::string abspath_posix(const std::string & path, const std::string & cwd);
|
||||
PYSTRING_INLINE std::string abspath(const std::string & path, const std::string & cwd);
|
||||
PYSTRING_INLINE std::string abspath_nt(const std::string & path, const std::string & cwd);
|
||||
PYSTRING_INLINE std::string abspath_posix(const std::string & path, const std::string & cwd);
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -367,13 +387,13 @@ namespace path
|
||||
/// current directory on drive C: (c:foo), not c:\foo.
|
||||
|
||||
/// This dispatches based on the compilation OS
|
||||
std::string join(const std::string & path1, const std::string & path2);
|
||||
std::string join_nt(const std::string & path1, const std::string & path2);
|
||||
std::string join_posix(const std::string & path1, const std::string & path2);
|
||||
PYSTRING_INLINE std::string join(const std::string & path1, const std::string & path2);
|
||||
PYSTRING_INLINE std::string join_nt(const std::string & path1, const std::string & path2);
|
||||
PYSTRING_INLINE std::string join_posix(const std::string & path1, const std::string & path2);
|
||||
|
||||
std::string join(const std::vector< std::string > & paths);
|
||||
std::string join_nt(const std::vector< std::string > & paths);
|
||||
std::string join_posix(const std::vector< std::string > & paths);
|
||||
PYSTRING_INLINE std::string join(const std::vector< std::string > & paths);
|
||||
PYSTRING_INLINE std::string join_nt(const std::vector< std::string > & paths);
|
||||
PYSTRING_INLINE std::string join_posix(const std::vector< std::string > & paths);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Normalize a pathname. This collapses redundant separators and up-level references
|
||||
@@ -382,9 +402,9 @@ namespace path
|
||||
/// It should be understood that this may change the meaning of the path if it contains
|
||||
/// symbolic links!
|
||||
|
||||
std::string normpath(const std::string & path);
|
||||
std::string normpath_nt(const std::string & path);
|
||||
std::string normpath_posix(const std::string & path);
|
||||
PYSTRING_INLINE std::string normpath(const std::string & path);
|
||||
PYSTRING_INLINE std::string normpath_nt(const std::string & path);
|
||||
PYSTRING_INLINE std::string normpath_posix(const std::string & path);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Split the pathname path into a pair, (head, tail) where tail is the last pathname
|
||||
@@ -395,9 +415,9 @@ namespace path
|
||||
/// join(head, tail) returns a path to the same location as path (but the strings may
|
||||
/// differ).
|
||||
|
||||
void split(std::string & head, std::string & tail, const std::string & path);
|
||||
void split_nt(std::string & head, std::string & tail, const std::string & path);
|
||||
void split_posix(std::string & head, std::string & tail, const std::string & path);
|
||||
PYSTRING_INLINE void split(std::string & head, std::string & tail, const std::string & path);
|
||||
PYSTRING_INLINE void split_nt(std::string & head, std::string & tail, const std::string & path);
|
||||
PYSTRING_INLINE void split_posix(std::string & head, std::string & tail, const std::string & path);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Split the pathname path into a pair (drive, tail) where drive is either a drive
|
||||
@@ -405,18 +425,18 @@ namespace path
|
||||
/// drive will always be the empty string. In all cases, drive + tail will be the same as
|
||||
/// path.
|
||||
|
||||
void splitdrive(std::string & drivespec, std::string & pathspec, const std::string & path);
|
||||
void splitdrive_nt(std::string & drivespec, std::string & pathspec, const std::string & p);
|
||||
void splitdrive_posix(std::string & drivespec, std::string & pathspec, const std::string & path);
|
||||
PYSTRING_INLINE void splitdrive(std::string & drivespec, std::string & pathspec, const std::string & path);
|
||||
PYSTRING_INLINE void splitdrive_nt(std::string & drivespec, std::string & pathspec, const std::string & p);
|
||||
PYSTRING_INLINE void splitdrive_posix(std::string & drivespec, std::string & pathspec, const std::string & path);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Split the pathname path into a pair (root, ext) such that root + ext == path, and
|
||||
/// ext is empty or begins with a period and contains at most one period. Leading periods on
|
||||
/// the basename are ignored; splitext('.cshrc') returns ('.cshrc', '').
|
||||
|
||||
void splitext(std::string & root, std::string & ext, const std::string & path);
|
||||
void splitext_nt(std::string & root, std::string & ext, const std::string & path);
|
||||
void splitext_posix(std::string & root, std::string & ext, const std::string & path);
|
||||
PYSTRING_INLINE void splitext(std::string & root, std::string & ext, const std::string & path);
|
||||
PYSTRING_INLINE void splitext_nt(std::string & root, std::string & ext, const std::string & path);
|
||||
PYSTRING_INLINE void splitext_posix(std::string & root, std::string & ext, const std::string & path);
|
||||
|
||||
///
|
||||
/// @ }
|
||||
@@ -426,4 +446,8 @@ namespace path
|
||||
|
||||
} // namespace pystring
|
||||
|
||||
#if PYSTRING_HEADER_ONLY
|
||||
#include "pystring_impl.h"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
+1693
File diff suppressed because it is too large
Load Diff
@@ -1,8 +1,31 @@
|
||||
// Copyright Contributors to the Pystring project.
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
// https://github.com/imageworks/pystring/blob/master/LICENSE
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "pystring.h"
|
||||
#include "unittest.h"
|
||||
|
||||
// Helper wrappers (for pystring functions that don't have direct return values)
|
||||
|
||||
namespace {
|
||||
static std::vector<std::string> pystring_split(const std::string& s, int maxsplit)
|
||||
{ std::vector<std::string> r; pystring::split(s, r, "", maxsplit); return r; }
|
||||
static std::vector<std::string> pystring_split(const std::string& s, const std::string& sep, int maxsplit)
|
||||
{ std::vector<std::string> r; pystring::split(s, r, sep, maxsplit); return r; }
|
||||
static std::vector<std::string> pystring_rsplit(const std::string& s, int maxsplit)
|
||||
{ std::vector<std::string> r; pystring::rsplit(s, r, "", maxsplit); return r; }
|
||||
static std::vector<std::string> pystring_rsplit(const std::string& s, const std::string& sep, int maxsplit)
|
||||
{ std::vector<std::string> r; pystring::rsplit(s, r, sep, maxsplit); return r; }
|
||||
static std::vector<std::string> pystring_partition(const std::string& s, const std::string& sep)
|
||||
{ std::vector<std::string> r; pystring::partition(s, sep, r); return r; }
|
||||
static std::vector<std::string> pystring_rpartition(const std::string& s, const std::string& sep)
|
||||
{ std::vector<std::string> r; pystring::rpartition(s, sep, r); return r; }
|
||||
static std::vector<std::string> pystring_splitlines(const std::string& s, bool keepends)
|
||||
{ std::vector<std::string> r; pystring::splitlines(s, r, keepends); return r; }
|
||||
} // namespace
|
||||
|
||||
PYSTRING_TEST_APP(PyStringUnitTests)
|
||||
|
||||
PYSTRING_ADD_TEST(pystring, endswith)
|
||||
@@ -29,6 +52,17 @@ PYSTRING_ADD_TEST(pystring, endswith)
|
||||
PYSTRING_CHECK_EQUAL(pystring::endswith("abcdef", "cdef", -10), true);
|
||||
}
|
||||
|
||||
PYSTRING_ADD_TEST(pystring, isupper)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(pystring::isupper("ABC"), true);
|
||||
PYSTRING_CHECK_EQUAL(pystring::isupper("abc"), false);
|
||||
PYSTRING_CHECK_EQUAL(pystring::isupper("ABc"), false);
|
||||
PYSTRING_CHECK_EQUAL(pystring::isupper("AB-C"), true);
|
||||
PYSTRING_CHECK_EQUAL(pystring::isupper("HELLO 123"), true);
|
||||
PYSTRING_CHECK_EQUAL(pystring::isupper("123"), false);
|
||||
PYSTRING_CHECK_EQUAL(pystring::isupper("HELLO!"), true);
|
||||
}
|
||||
|
||||
PYSTRING_ADD_TEST(pystring, find)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(pystring::find("", ""), 0);
|
||||
@@ -94,6 +128,18 @@ PYSTRING_ADD_TEST(pystring, rfind)
|
||||
PYSTRING_CHECK_EQUAL(pystring::rfind("abcabcabc", "abc", 6, 8), -1);
|
||||
}
|
||||
|
||||
PYSTRING_ADD_TEST(pystring, removeprefix)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(pystring::removeprefix("abcdef", "abc"), "def");
|
||||
PYSTRING_CHECK_EQUAL(pystring::removeprefix("abcdef", "bcd"), "abcdef");
|
||||
}
|
||||
|
||||
PYSTRING_ADD_TEST(pystring, removesuffix)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(pystring::removesuffix("abcdef", "def"), "abc");
|
||||
PYSTRING_CHECK_EQUAL(pystring::removesuffix("abcdef", "cde"), "abcdef");
|
||||
}
|
||||
|
||||
PYSTRING_ADD_TEST(pystring, replace)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(pystring::replace("abcdef", "foo", "bar"), "abcdef");
|
||||
@@ -654,3 +700,601 @@ PYSTRING_ADD_TEST(pystring_os_path, splitext)
|
||||
splitext_nt(root, ext, "c:\\a.b.c"); PYSTRING_CHECK_EQUAL(root, "c:\\a.b"); PYSTRING_CHECK_EQUAL(ext, ".c");
|
||||
splitext_nt(root, ext, "c:\\a_b.c"); PYSTRING_CHECK_EQUAL(root, "c:\\a_b"); PYSTRING_CHECK_EQUAL(ext, ".c");
|
||||
}
|
||||
|
||||
// the python3_compat tests were auto generated from python
|
||||
// to make sure that our functions exactly match the values that are being returned in python 3.11
|
||||
|
||||
PYSTRING_ADD_TEST(python3_compat, capitalize)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(pystring::capitalize(""), "");
|
||||
PYSTRING_CHECK_EQUAL(pystring::capitalize("hello"), "Hello");
|
||||
PYSTRING_CHECK_EQUAL(pystring::capitalize("HELLO"), "Hello");
|
||||
PYSTRING_CHECK_EQUAL(pystring::capitalize("Hello World"), "Hello world");
|
||||
PYSTRING_CHECK_EQUAL(pystring::capitalize("hello123"), "Hello123");
|
||||
PYSTRING_CHECK_EQUAL(pystring::capitalize("123"), "123");
|
||||
PYSTRING_CHECK_EQUAL(pystring::capitalize("hElLo"), "Hello");
|
||||
PYSTRING_CHECK_EQUAL(pystring::capitalize("hello world!"), "Hello world!");
|
||||
}
|
||||
|
||||
PYSTRING_ADD_TEST(python3_compat, center)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(pystring::center("hello", 10), " hello ");
|
||||
PYSTRING_CHECK_EQUAL(pystring::center("hello", 3), "hello");
|
||||
PYSTRING_CHECK_EQUAL(pystring::center("", 5), " ");
|
||||
PYSTRING_CHECK_EQUAL(pystring::center("hello", 5), "hello");
|
||||
}
|
||||
|
||||
PYSTRING_ADD_TEST(python3_compat, count_python3)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(pystring::count("", "", 0), 1);
|
||||
PYSTRING_CHECK_EQUAL(pystring::count("bob", ""), 4);
|
||||
PYSTRING_CHECK_EQUAL(pystring::count("", "bob"), 0);
|
||||
PYSTRING_CHECK_EQUAL(pystring::count("hello world", "o", 0), 2);
|
||||
PYSTRING_CHECK_EQUAL(pystring::count("hello world", "l", 0), 3);
|
||||
PYSTRING_CHECK_EQUAL(pystring::count("hello world", "xyz", 0), 0);
|
||||
PYSTRING_CHECK_EQUAL(pystring::count("hello world", "", 0), 12);
|
||||
PYSTRING_CHECK_EQUAL(pystring::count("aaa", "a", 0), 3);
|
||||
PYSTRING_CHECK_EQUAL(pystring::count("aaa", "aa", 0), 1);
|
||||
PYSTRING_CHECK_EQUAL(pystring::count("hello", "l", 2, 5), 2);
|
||||
}
|
||||
|
||||
PYSTRING_ADD_TEST(python3_compat, endswith_python3)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(pystring::endswith("hello world", "hello", 0), false);
|
||||
PYSTRING_CHECK_EQUAL(pystring::endswith("hello world", "world", 0), true);
|
||||
PYSTRING_CHECK_EQUAL(pystring::endswith("hello world", "", 0), true);
|
||||
PYSTRING_CHECK_EQUAL(pystring::endswith("hello world", "hello", 1), false);
|
||||
PYSTRING_CHECK_EQUAL(pystring::endswith("hello world", "ello", 1), false);
|
||||
PYSTRING_CHECK_EQUAL(pystring::endswith("hello", "hello world", 0), false);
|
||||
PYSTRING_CHECK_EQUAL(pystring::endswith("hello world", "world", 0, 5), false);
|
||||
PYSTRING_CHECK_EQUAL(pystring::endswith("hello world", "hello", 0, 5), true);
|
||||
PYSTRING_CHECK_EQUAL(pystring::endswith("", "", 0), true);
|
||||
PYSTRING_CHECK_EQUAL(pystring::endswith("hello", "hello", 0), true);
|
||||
}
|
||||
|
||||
PYSTRING_ADD_TEST(python3_compat, expandtabs)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(pystring::expandtabs("hello\tworld", 8), "hello world");
|
||||
PYSTRING_CHECK_EQUAL(pystring::expandtabs("hello\tworld", 4), "hello world");
|
||||
PYSTRING_CHECK_EQUAL(pystring::expandtabs("\t\t", 4), " ");
|
||||
PYSTRING_CHECK_EQUAL(pystring::expandtabs("no tabs", 4), "no tabs");
|
||||
PYSTRING_CHECK_EQUAL(pystring::expandtabs("a\tb\tc", 4), "a b c");
|
||||
}
|
||||
|
||||
PYSTRING_ADD_TEST(python3_compat, find_python3)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(pystring::find("hello world", "world", 0), 6);
|
||||
PYSTRING_CHECK_EQUAL(pystring::find("hello world", "hello", 0), 0);
|
||||
PYSTRING_CHECK_EQUAL(pystring::find("hello world", "xyz", 0), -1);
|
||||
PYSTRING_CHECK_EQUAL(pystring::find("hello world", "", 0), 0);
|
||||
PYSTRING_CHECK_EQUAL(pystring::find("hello world", "o", 0), 4);
|
||||
PYSTRING_CHECK_EQUAL(pystring::find("hello world", "o", 5), 7);
|
||||
PYSTRING_CHECK_EQUAL(pystring::find("hello world", "o", 0, 5), 4);
|
||||
PYSTRING_CHECK_EQUAL(pystring::find("", "hello", 0), -1);
|
||||
PYSTRING_CHECK_EQUAL(pystring::find("hello", "", 0), 0);
|
||||
PYSTRING_CHECK_EQUAL(pystring::find("abcabc", "bc", 0), 1);
|
||||
PYSTRING_CHECK_EQUAL(pystring::find("abcabc", "bc", 2), 4);
|
||||
}
|
||||
|
||||
PYSTRING_ADD_TEST(python3_compat, isalnum)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(pystring::isalnum(""), false);
|
||||
PYSTRING_CHECK_EQUAL(pystring::isalnum("abc"), true);
|
||||
PYSTRING_CHECK_EQUAL(pystring::isalnum("123"), true);
|
||||
PYSTRING_CHECK_EQUAL(pystring::isalnum("abc123"), true);
|
||||
PYSTRING_CHECK_EQUAL(pystring::isalnum("abc!"), false);
|
||||
PYSTRING_CHECK_EQUAL(pystring::isalnum(" "), false);
|
||||
PYSTRING_CHECK_EQUAL(pystring::isalnum("abc 123"), false);
|
||||
}
|
||||
|
||||
PYSTRING_ADD_TEST(python3_compat, isalpha)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(pystring::isalpha(""), false);
|
||||
PYSTRING_CHECK_EQUAL(pystring::isalpha("abc"), true);
|
||||
PYSTRING_CHECK_EQUAL(pystring::isalpha("ABC"), true);
|
||||
PYSTRING_CHECK_EQUAL(pystring::isalpha("abcABC"), true);
|
||||
PYSTRING_CHECK_EQUAL(pystring::isalpha("abc1"), false);
|
||||
PYSTRING_CHECK_EQUAL(pystring::isalpha("abc!"), false);
|
||||
PYSTRING_CHECK_EQUAL(pystring::isalpha(" "), false);
|
||||
PYSTRING_CHECK_EQUAL(pystring::isalpha("a b"), false);
|
||||
}
|
||||
|
||||
PYSTRING_ADD_TEST(python3_compat, isdigit)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(pystring::isdigit(""), false);
|
||||
PYSTRING_CHECK_EQUAL(pystring::isdigit("0"), true);
|
||||
PYSTRING_CHECK_EQUAL(pystring::isdigit("123"), true);
|
||||
PYSTRING_CHECK_EQUAL(pystring::isdigit("12.3"), false);
|
||||
PYSTRING_CHECK_EQUAL(pystring::isdigit("12 3"), false);
|
||||
PYSTRING_CHECK_EQUAL(pystring::isdigit("abc"), false);
|
||||
PYSTRING_CHECK_EQUAL(pystring::isdigit("123abc"), false);
|
||||
PYSTRING_CHECK_EQUAL(pystring::isdigit(" "), false);
|
||||
}
|
||||
|
||||
PYSTRING_ADD_TEST(python3_compat, islower)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(pystring::islower(""), false);
|
||||
PYSTRING_CHECK_EQUAL(pystring::islower("a"), true);
|
||||
PYSTRING_CHECK_EQUAL(pystring::islower("A"), false);
|
||||
PYSTRING_CHECK_EQUAL(pystring::islower("abc"), true);
|
||||
PYSTRING_CHECK_EQUAL(pystring::islower("ABC"), false);
|
||||
PYSTRING_CHECK_EQUAL(pystring::islower("abC"), false);
|
||||
PYSTRING_CHECK_EQUAL(pystring::islower("abc123"), true);
|
||||
PYSTRING_CHECK_EQUAL(pystring::islower("123"), false);
|
||||
PYSTRING_CHECK_EQUAL(pystring::islower("abc 123"), true);
|
||||
PYSTRING_CHECK_EQUAL(pystring::islower("hello!"), true);
|
||||
PYSTRING_CHECK_EQUAL(pystring::islower("HELLO!"), false);
|
||||
PYSTRING_CHECK_EQUAL(pystring::islower(" "), false);
|
||||
PYSTRING_CHECK_EQUAL(pystring::islower("abc\n"), true);
|
||||
PYSTRING_CHECK_EQUAL(pystring::islower("!@#$"), false);
|
||||
PYSTRING_CHECK_EQUAL(pystring::islower("a!b"), true);
|
||||
PYSTRING_CHECK_EQUAL(pystring::islower("1a"), true);
|
||||
}
|
||||
|
||||
PYSTRING_ADD_TEST(python3_compat, isspace)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(pystring::isspace(""), false);
|
||||
PYSTRING_CHECK_EQUAL(pystring::isspace(" "), true);
|
||||
PYSTRING_CHECK_EQUAL(pystring::isspace(" "), true);
|
||||
PYSTRING_CHECK_EQUAL(pystring::isspace("\t"), true);
|
||||
PYSTRING_CHECK_EQUAL(pystring::isspace("\n"), true);
|
||||
PYSTRING_CHECK_EQUAL(pystring::isspace("\r"), true);
|
||||
PYSTRING_CHECK_EQUAL(pystring::isspace(" \t\n"), true);
|
||||
PYSTRING_CHECK_EQUAL(pystring::isspace("a"), false);
|
||||
PYSTRING_CHECK_EQUAL(pystring::isspace(" a "), false);
|
||||
PYSTRING_CHECK_EQUAL(pystring::isspace(" a"), false);
|
||||
}
|
||||
|
||||
PYSTRING_ADD_TEST(python3_compat, istitle)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(pystring::istitle(""), false);
|
||||
PYSTRING_CHECK_EQUAL(pystring::istitle("Title"), true);
|
||||
PYSTRING_CHECK_EQUAL(pystring::istitle("Title Case"), true);
|
||||
PYSTRING_CHECK_EQUAL(pystring::istitle("title"), false);
|
||||
PYSTRING_CHECK_EQUAL(pystring::istitle("TITLE"), false);
|
||||
PYSTRING_CHECK_EQUAL(pystring::istitle("Title123"), true);
|
||||
PYSTRING_CHECK_EQUAL(pystring::istitle("A"), true);
|
||||
PYSTRING_CHECK_EQUAL(pystring::istitle("a"), false);
|
||||
PYSTRING_CHECK_EQUAL(pystring::istitle("Title Case Here"), true);
|
||||
PYSTRING_CHECK_EQUAL(pystring::istitle("Title Case"), true);
|
||||
PYSTRING_CHECK_EQUAL(pystring::istitle("123 Title"), true);
|
||||
PYSTRING_CHECK_EQUAL(pystring::istitle("Already A Title"), true);
|
||||
PYSTRING_CHECK_EQUAL(pystring::istitle("not A Title"), false);
|
||||
}
|
||||
|
||||
PYSTRING_ADD_TEST(python3_compat, isupper)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(pystring::isupper(""), false);
|
||||
PYSTRING_CHECK_EQUAL(pystring::isupper("A"), true);
|
||||
PYSTRING_CHECK_EQUAL(pystring::isupper("a"), false);
|
||||
PYSTRING_CHECK_EQUAL(pystring::isupper("ABC"), true);
|
||||
PYSTRING_CHECK_EQUAL(pystring::isupper("abc"), false);
|
||||
PYSTRING_CHECK_EQUAL(pystring::isupper("ABc"), false);
|
||||
PYSTRING_CHECK_EQUAL(pystring::isupper("ABC123"), true);
|
||||
PYSTRING_CHECK_EQUAL(pystring::isupper("123"), false);
|
||||
PYSTRING_CHECK_EQUAL(pystring::isupper("ABC 123"), true);
|
||||
PYSTRING_CHECK_EQUAL(pystring::isupper("HELLO!"), true);
|
||||
PYSTRING_CHECK_EQUAL(pystring::isupper("hello!"), false);
|
||||
PYSTRING_CHECK_EQUAL(pystring::isupper(" "), false);
|
||||
PYSTRING_CHECK_EQUAL(pystring::isupper("ABC\n"), true);
|
||||
PYSTRING_CHECK_EQUAL(pystring::isupper("ABC\tDEF"), true);
|
||||
PYSTRING_CHECK_EQUAL(pystring::isupper("!@#$"), false);
|
||||
PYSTRING_CHECK_EQUAL(pystring::isupper("A!B"), true);
|
||||
PYSTRING_CHECK_EQUAL(pystring::isupper("1A"), true);
|
||||
}
|
||||
|
||||
PYSTRING_ADD_TEST(python3_compat, join_python3)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(pystring::join(",", {}), "");
|
||||
PYSTRING_CHECK_EQUAL(pystring::join(",", {""}), "");
|
||||
PYSTRING_CHECK_EQUAL(pystring::join(",", {"a"}), "a");
|
||||
PYSTRING_CHECK_EQUAL(pystring::join(",", {"a", "b", "c"}), "a,b,c");
|
||||
PYSTRING_CHECK_EQUAL(pystring::join("", {"a", "b", "c"}), "abc");
|
||||
PYSTRING_CHECK_EQUAL(pystring::join(", ", {"hello", "world"}), "hello, world");
|
||||
PYSTRING_CHECK_EQUAL(pystring::join("-", {"one", "two", "three"}), "one-two-three");
|
||||
PYSTRING_CHECK_EQUAL(pystring::join("/", {"path", "to", "file"}), "path/to/file");
|
||||
}
|
||||
|
||||
PYSTRING_ADD_TEST(python3_compat, ljust)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(pystring::ljust("hello", 10), "hello ");
|
||||
PYSTRING_CHECK_EQUAL(pystring::ljust("hello", 3), "hello");
|
||||
PYSTRING_CHECK_EQUAL(pystring::ljust("", 5), " ");
|
||||
PYSTRING_CHECK_EQUAL(pystring::ljust("hello", 5), "hello");
|
||||
}
|
||||
|
||||
PYSTRING_ADD_TEST(python3_compat, lower)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(pystring::lower(""), "");
|
||||
PYSTRING_CHECK_EQUAL(pystring::lower("hello"), "hello");
|
||||
PYSTRING_CHECK_EQUAL(pystring::lower("HELLO"), "hello");
|
||||
PYSTRING_CHECK_EQUAL(pystring::lower("Hello World"), "hello world");
|
||||
PYSTRING_CHECK_EQUAL(pystring::lower("hello123"), "hello123");
|
||||
PYSTRING_CHECK_EQUAL(pystring::lower("123"), "123");
|
||||
PYSTRING_CHECK_EQUAL(pystring::lower("hElLo"), "hello");
|
||||
PYSTRING_CHECK_EQUAL(pystring::lower("hello world!"), "hello world!");
|
||||
}
|
||||
|
||||
PYSTRING_ADD_TEST(python3_compat, lstrip)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(pystring::lstrip(""), "");
|
||||
PYSTRING_CHECK_EQUAL(pystring::lstrip(" hello "), "hello ");
|
||||
PYSTRING_CHECK_EQUAL(pystring::lstrip(" hello ", " "), "hello ");
|
||||
PYSTRING_CHECK_EQUAL(pystring::lstrip("xxhelloxx", "x"), "helloxx");
|
||||
PYSTRING_CHECK_EQUAL(pystring::lstrip("\t\nhello\t\n"), "hello\t\n");
|
||||
PYSTRING_CHECK_EQUAL(pystring::lstrip("hello"), "hello");
|
||||
PYSTRING_CHECK_EQUAL(pystring::lstrip(" "), "");
|
||||
PYSTRING_CHECK_EQUAL(pystring::lstrip("aabbcc", "ac"), "bbcc");
|
||||
PYSTRING_CHECK_EQUAL(pystring::lstrip("hello world "), "hello world ");
|
||||
}
|
||||
|
||||
PYSTRING_ADD_TEST(python3_compat, mul)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(pystring::mul("ab", 3), "ababab");
|
||||
PYSTRING_CHECK_EQUAL(pystring::mul("ab", 0), "");
|
||||
PYSTRING_CHECK_EQUAL(pystring::mul("ab", 1), "ab");
|
||||
PYSTRING_CHECK_EQUAL(pystring::mul("", 5), "");
|
||||
PYSTRING_CHECK_EQUAL(pystring::mul("x", 5), "xxxxx");
|
||||
}
|
||||
|
||||
|
||||
PYSTRING_ADD_TEST(python3_compat, removeprefix_python3)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(pystring::removeprefix("hello world", "hello "), "world");
|
||||
PYSTRING_CHECK_EQUAL(pystring::removeprefix("hello world", "xyz"), "hello world");
|
||||
PYSTRING_CHECK_EQUAL(pystring::removeprefix("hello world", ""), "hello world");
|
||||
PYSTRING_CHECK_EQUAL(pystring::removeprefix("hello", "hello"), "");
|
||||
PYSTRING_CHECK_EQUAL(pystring::removeprefix("", "x"), "");
|
||||
}
|
||||
|
||||
PYSTRING_ADD_TEST(python3_compat, removesuffix_python3)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(pystring::removesuffix("hello world", "hello "), "hello world");
|
||||
PYSTRING_CHECK_EQUAL(pystring::removesuffix("hello world", "xyz"), "hello world");
|
||||
PYSTRING_CHECK_EQUAL(pystring::removesuffix("hello world", ""), "hello world");
|
||||
PYSTRING_CHECK_EQUAL(pystring::removesuffix("hello", "hello"), "");
|
||||
PYSTRING_CHECK_EQUAL(pystring::removesuffix("", "x"), "");
|
||||
}
|
||||
|
||||
PYSTRING_ADD_TEST(python3_compat, replace_python3)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(pystring::replace("hello world", "world", "python", -1), "hello python");
|
||||
PYSTRING_CHECK_EQUAL(pystring::replace("hello world", "o", "0", -1), "hell0 w0rld");
|
||||
PYSTRING_CHECK_EQUAL(pystring::replace("hello world", "o", "0", 1), "hell0 world");
|
||||
PYSTRING_CHECK_EQUAL(pystring::replace("hello world", "xyz", "abc", -1), "hello world");
|
||||
PYSTRING_CHECK_EQUAL(pystring::replace("hello world", "", "_", -1), "_h_e_l_l_o_ _w_o_r_l_d_");
|
||||
PYSTRING_CHECK_EQUAL(pystring::replace("aaa", "a", "bb", -1), "bbbbbb");
|
||||
PYSTRING_CHECK_EQUAL(pystring::replace("aaa", "a", "bb", 2), "bbbba");
|
||||
PYSTRING_CHECK_EQUAL(pystring::replace("", "a", "b", -1), "");
|
||||
PYSTRING_CHECK_EQUAL(pystring::replace("hello", "hello", "", -1), "");
|
||||
}
|
||||
|
||||
PYSTRING_ADD_TEST(python3_compat, replace_overlap)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(pystring::replace("aaaaa", "aa", "b", -1), "bba");
|
||||
PYSTRING_CHECK_EQUAL(pystring::replace("aaaa", "aa", "b", -1), "bb");
|
||||
PYSTRING_CHECK_EQUAL(pystring::replace("aaa", "aa", "b", -1), "ba");
|
||||
PYSTRING_CHECK_EQUAL(pystring::replace("abababa", "aba", "X", -1), "XbX");
|
||||
PYSTRING_CHECK_EQUAL(pystring::replace("aaaaaa", "aaa", "x", -1), "xx");
|
||||
PYSTRING_CHECK_EQUAL(pystring::replace("abcabcabc", "abc", "x", 2), "xxabc");
|
||||
PYSTRING_CHECK_EQUAL(pystring::replace("abcabcabc", "abc", "x", 1), "xabcabc");
|
||||
PYSTRING_CHECK_EQUAL(pystring::replace("aaaa", "a", "", -1), "");
|
||||
PYSTRING_CHECK_EQUAL(pystring::replace("aaaa", "aa", "", -1), "");
|
||||
PYSTRING_CHECK_EQUAL(pystring::replace("abc", "d", "x", -1), "abc");
|
||||
PYSTRING_CHECK_EQUAL(pystring::replace("", "a", "x", -1), "");
|
||||
PYSTRING_CHECK_EQUAL(pystring::replace("", "", "x", -1), "x");
|
||||
PYSTRING_CHECK_EQUAL(pystring::replace("a", "", "-", -1), "-a-");
|
||||
PYSTRING_CHECK_EQUAL(pystring::replace("mississippi", "issi", "X", -1), "mXssippi");
|
||||
PYSTRING_CHECK_EQUAL(pystring::replace("11111", "11", "x", -1), "xx1");
|
||||
}
|
||||
|
||||
PYSTRING_ADD_TEST(python3_compat, rfind_python3)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(pystring::rfind("hello world", "world", 0), 6);
|
||||
PYSTRING_CHECK_EQUAL(pystring::rfind("hello world", "hello", 0), 0);
|
||||
PYSTRING_CHECK_EQUAL(pystring::rfind("hello world", "xyz", 0), -1);
|
||||
PYSTRING_CHECK_EQUAL(pystring::rfind("hello world", "", 0), 11);
|
||||
PYSTRING_CHECK_EQUAL(pystring::rfind("hello world", "o", 0), 7);
|
||||
PYSTRING_CHECK_EQUAL(pystring::rfind("hello world", "o", 5), 7);
|
||||
PYSTRING_CHECK_EQUAL(pystring::rfind("hello world", "o", 0, 5), 4);
|
||||
PYSTRING_CHECK_EQUAL(pystring::rfind("", "hello", 0), -1);
|
||||
PYSTRING_CHECK_EQUAL(pystring::rfind("hello", "", 0), 5);
|
||||
PYSTRING_CHECK_EQUAL(pystring::rfind("abcabc", "bc", 0), 4);
|
||||
PYSTRING_CHECK_EQUAL(pystring::rfind("abcabc", "bc", 2), 4);
|
||||
}
|
||||
|
||||
PYSTRING_ADD_TEST(python3_compat, rjust)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(pystring::rjust("hello", 10), " hello");
|
||||
PYSTRING_CHECK_EQUAL(pystring::rjust("hello", 3), "hello");
|
||||
PYSTRING_CHECK_EQUAL(pystring::rjust("", 5), " ");
|
||||
PYSTRING_CHECK_EQUAL(pystring::rjust("hello", 5), "hello");
|
||||
}
|
||||
|
||||
|
||||
PYSTRING_ADD_TEST(python3_compat, rstrip)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(pystring::rstrip(""), "");
|
||||
PYSTRING_CHECK_EQUAL(pystring::rstrip(" hello "), " hello");
|
||||
PYSTRING_CHECK_EQUAL(pystring::rstrip(" hello ", " "), " hello");
|
||||
PYSTRING_CHECK_EQUAL(pystring::rstrip("xxhelloxx", "x"), "xxhello");
|
||||
PYSTRING_CHECK_EQUAL(pystring::rstrip("\t\nhello\t\n"), "\t\nhello");
|
||||
PYSTRING_CHECK_EQUAL(pystring::rstrip("hello"), "hello");
|
||||
PYSTRING_CHECK_EQUAL(pystring::rstrip(" "), "");
|
||||
PYSTRING_CHECK_EQUAL(pystring::rstrip("aabbcc", "ac"), "aabb");
|
||||
PYSTRING_CHECK_EQUAL(pystring::rstrip("hello world "), "hello world");
|
||||
}
|
||||
|
||||
PYSTRING_ADD_TEST(python3_compat, slice_python3)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(pystring::slice("hello", 0, 5), "hello");
|
||||
PYSTRING_CHECK_EQUAL(pystring::slice("hello", 1, 4), "ell");
|
||||
PYSTRING_CHECK_EQUAL(pystring::slice("hello", 0, -1), "hell");
|
||||
PYSTRING_CHECK_EQUAL(pystring::slice("hello", -3, -1), "ll");
|
||||
PYSTRING_CHECK_EQUAL(pystring::slice("hello", 2, 2), "");
|
||||
PYSTRING_CHECK_EQUAL(pystring::slice("hello", 3, 1), "");
|
||||
PYSTRING_CHECK_EQUAL(pystring::slice("", 0, 0), "");
|
||||
PYSTRING_CHECK_EQUAL(pystring::slice("hello world", 6, 11), "world");
|
||||
}
|
||||
|
||||
|
||||
PYSTRING_ADD_TEST(python3_compat, startswith_python3)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(pystring::startswith("hello world", "hello", 0), true);
|
||||
PYSTRING_CHECK_EQUAL(pystring::startswith("hello world", "world", 0), false);
|
||||
PYSTRING_CHECK_EQUAL(pystring::startswith("hello world", "", 0), true);
|
||||
PYSTRING_CHECK_EQUAL(pystring::startswith("hello world", "hello", 1), false);
|
||||
PYSTRING_CHECK_EQUAL(pystring::startswith("hello world", "ello", 1), true);
|
||||
PYSTRING_CHECK_EQUAL(pystring::startswith("hello", "hello world", 0), false);
|
||||
PYSTRING_CHECK_EQUAL(pystring::startswith("hello world", "world", 0, 5), false);
|
||||
PYSTRING_CHECK_EQUAL(pystring::startswith("hello world", "hello", 0, 5), true);
|
||||
PYSTRING_CHECK_EQUAL(pystring::startswith("", "", 0), true);
|
||||
PYSTRING_CHECK_EQUAL(pystring::startswith("hello", "hello", 0), true);
|
||||
}
|
||||
|
||||
PYSTRING_ADD_TEST(python3_compat, strip)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(pystring::strip(""), "");
|
||||
PYSTRING_CHECK_EQUAL(pystring::strip(" hello "), "hello");
|
||||
PYSTRING_CHECK_EQUAL(pystring::strip(" hello ", " "), "hello");
|
||||
PYSTRING_CHECK_EQUAL(pystring::strip("xxhelloxx", "x"), "hello");
|
||||
PYSTRING_CHECK_EQUAL(pystring::strip("\t\nhello\t\n"), "hello");
|
||||
PYSTRING_CHECK_EQUAL(pystring::strip("hello"), "hello");
|
||||
PYSTRING_CHECK_EQUAL(pystring::strip(" "), "");
|
||||
PYSTRING_CHECK_EQUAL(pystring::strip("aabbcc", "ac"), "bb");
|
||||
PYSTRING_CHECK_EQUAL(pystring::strip("hello world "), "hello world");
|
||||
}
|
||||
|
||||
PYSTRING_ADD_TEST(python3_compat, swapcase)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(pystring::swapcase(""), "");
|
||||
PYSTRING_CHECK_EQUAL(pystring::swapcase("hello"), "HELLO");
|
||||
PYSTRING_CHECK_EQUAL(pystring::swapcase("HELLO"), "hello");
|
||||
PYSTRING_CHECK_EQUAL(pystring::swapcase("Hello World"), "hELLO wORLD");
|
||||
PYSTRING_CHECK_EQUAL(pystring::swapcase("hello123"), "HELLO123");
|
||||
PYSTRING_CHECK_EQUAL(pystring::swapcase("123"), "123");
|
||||
PYSTRING_CHECK_EQUAL(pystring::swapcase("hElLo"), "HeLlO");
|
||||
PYSTRING_CHECK_EQUAL(pystring::swapcase("hello world!"), "HELLO WORLD!");
|
||||
}
|
||||
|
||||
PYSTRING_ADD_TEST(python3_compat, title)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(pystring::title(""), "");
|
||||
PYSTRING_CHECK_EQUAL(pystring::title("hello world"), "Hello World");
|
||||
PYSTRING_CHECK_EQUAL(pystring::title("HELLO WORLD"), "Hello World");
|
||||
PYSTRING_CHECK_EQUAL(pystring::title("hello"), "Hello");
|
||||
PYSTRING_CHECK_EQUAL(pystring::title("it's a test"), "It'S A Test");
|
||||
PYSTRING_CHECK_EQUAL(pystring::title("they're bill's friends from the UK"), "They'Re Bill'S Friends From The Uk");
|
||||
PYSTRING_CHECK_EQUAL(pystring::title("hello123world"), "Hello123World");
|
||||
}
|
||||
|
||||
PYSTRING_ADD_TEST(python3_compat, upper)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(pystring::upper(""), "");
|
||||
PYSTRING_CHECK_EQUAL(pystring::upper("hello"), "HELLO");
|
||||
PYSTRING_CHECK_EQUAL(pystring::upper("HELLO"), "HELLO");
|
||||
PYSTRING_CHECK_EQUAL(pystring::upper("Hello World"), "HELLO WORLD");
|
||||
PYSTRING_CHECK_EQUAL(pystring::upper("hello123"), "HELLO123");
|
||||
PYSTRING_CHECK_EQUAL(pystring::upper("123"), "123");
|
||||
PYSTRING_CHECK_EQUAL(pystring::upper("hElLo"), "HELLO");
|
||||
PYSTRING_CHECK_EQUAL(pystring::upper("hello world!"), "HELLO WORLD!");
|
||||
}
|
||||
|
||||
PYSTRING_ADD_TEST(python3_compat, zfill)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(pystring::zfill("42", 5), "00042");
|
||||
PYSTRING_CHECK_EQUAL(pystring::zfill("42", 2), "42");
|
||||
PYSTRING_CHECK_EQUAL(pystring::zfill("-42", 5), "-0042");
|
||||
PYSTRING_CHECK_EQUAL(pystring::zfill("+42", 5), "+0042");
|
||||
PYSTRING_CHECK_EQUAL(pystring::zfill("hello", 8), "000hello");
|
||||
PYSTRING_CHECK_EQUAL(pystring::zfill("", 3), "000");
|
||||
}
|
||||
|
||||
|
||||
PYSTRING_ADD_TEST(python3_compat, rpartition_python3)
|
||||
{
|
||||
{
|
||||
std::vector<std::string> _e17 = {"hello", " ", "world"};
|
||||
PYSTRING_CHECK_ASSERT((pystring_rpartition("hello world", " ")) == _e17);
|
||||
}
|
||||
{
|
||||
std::vector<std::string> _e19 = {"", "", "hello world"};
|
||||
PYSTRING_CHECK_ASSERT((pystring_rpartition("hello world", "xyz")) == _e19);
|
||||
}
|
||||
{
|
||||
std::vector<std::string> _e21 = {"", "hello", ""};
|
||||
PYSTRING_CHECK_ASSERT((pystring_rpartition("hello", "hello")) == _e21);
|
||||
}
|
||||
{
|
||||
std::vector<std::string> _e23 = {"", "", ""};
|
||||
PYSTRING_CHECK_ASSERT((pystring_rpartition("", "x")) == _e23);
|
||||
}
|
||||
{
|
||||
std::vector<std::string> _e25 = {"aXb", "X", "c"};
|
||||
PYSTRING_CHECK_ASSERT((pystring_rpartition("aXbXc", "X")) == _e25);
|
||||
}
|
||||
{
|
||||
std::vector<std::string> _e27 = {"hello ", "world", ""};
|
||||
PYSTRING_CHECK_ASSERT((pystring_rpartition("hello world", "world")) == _e27);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PYSTRING_ADD_TEST(python3_compat, rsplit_python3)
|
||||
{
|
||||
{
|
||||
std::vector<std::string> _e12 = {"hello world", "foo"};
|
||||
PYSTRING_CHECK_ASSERT((pystring_rsplit("hello world foo", " ", 1)) == _e12);
|
||||
}
|
||||
{
|
||||
std::vector<std::string> _e13 = {"a,b", "c", "d"};
|
||||
PYSTRING_CHECK_ASSERT((pystring_rsplit("a,b,c,d", ",", 2)) == _e13);
|
||||
}
|
||||
{
|
||||
std::vector<std::string> _e14 = {" hello", "world"};
|
||||
PYSTRING_CHECK_ASSERT((pystring_rsplit(" hello world ", 1)) == _e14);
|
||||
}
|
||||
{
|
||||
std::vector<std::string> _e15 = {"hello", "world"};
|
||||
PYSTRING_CHECK_ASSERT((pystring_rsplit("hello world", -1)) == _e15);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PYSTRING_ADD_TEST(python3_compat, split_python3)
|
||||
{
|
||||
{
|
||||
std::vector<std::string> _e0 = {};
|
||||
PYSTRING_CHECK_ASSERT((pystring_split("", -1)) == _e0);
|
||||
}
|
||||
{
|
||||
std::vector<std::string> _e1 = {"hello", "world"};
|
||||
PYSTRING_CHECK_ASSERT((pystring_split("hello world", -1)) == _e1);
|
||||
}
|
||||
{
|
||||
std::vector<std::string> _e2 = {"hello", "world"};
|
||||
PYSTRING_CHECK_ASSERT((pystring_split(" hello world ", -1)) == _e2);
|
||||
}
|
||||
{
|
||||
std::vector<std::string> _e3 = {"hello", "world"};
|
||||
PYSTRING_CHECK_ASSERT((pystring_split("hello world", " ", -1)) == _e3);
|
||||
}
|
||||
{
|
||||
std::vector<std::string> _e4 = {"hello world"};
|
||||
PYSTRING_CHECK_ASSERT((pystring_split("hello world", " ", 0)) == _e4);
|
||||
}
|
||||
{
|
||||
std::vector<std::string> _e5 = {"hello", "world foo"};
|
||||
PYSTRING_CHECK_ASSERT((pystring_split("hello world foo", " ", 1)) == _e5);
|
||||
}
|
||||
{
|
||||
std::vector<std::string> _e6 = {"a", "b", "c", "d"};
|
||||
PYSTRING_CHECK_ASSERT((pystring_split("a,b,c,d", ",", -1)) == _e6);
|
||||
}
|
||||
{
|
||||
std::vector<std::string> _e7 = {"a", "b", "c,d"};
|
||||
PYSTRING_CHECK_ASSERT((pystring_split("a,b,c,d", ",", 2)) == _e7);
|
||||
}
|
||||
{
|
||||
std::vector<std::string> _e8 = {"a", "b", "c"};
|
||||
PYSTRING_CHECK_ASSERT((pystring_split("aXXbXXc", "XX", -1)) == _e8);
|
||||
}
|
||||
{
|
||||
std::vector<std::string> _e9 = {"hello"};
|
||||
PYSTRING_CHECK_ASSERT((pystring_split("hello", "x", -1)) == _e9);
|
||||
}
|
||||
{
|
||||
std::vector<std::string> _e10 = {};
|
||||
PYSTRING_CHECK_ASSERT((pystring_split(" ", -1)) == _e10);
|
||||
}
|
||||
{
|
||||
std::vector<std::string> _e11 = {"hello", "world"};
|
||||
PYSTRING_CHECK_ASSERT((pystring_split("\thello\tworld\t", -1)) == _e11);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
PYSTRING_ADD_TEST(python3_compat, splitlines)
|
||||
{
|
||||
{
|
||||
std::vector<std::string> _e28 = {};
|
||||
PYSTRING_CHECK_ASSERT((pystring_splitlines("", false)) == _e28);
|
||||
}
|
||||
{
|
||||
std::vector<std::string> _e29 = {};
|
||||
PYSTRING_CHECK_ASSERT((pystring_splitlines("", true)) == _e29);
|
||||
}
|
||||
{
|
||||
std::vector<std::string> _e30 = {"hello"};
|
||||
PYSTRING_CHECK_ASSERT((pystring_splitlines("hello", false)) == _e30);
|
||||
}
|
||||
{
|
||||
std::vector<std::string> _e31 = {"hello"};
|
||||
PYSTRING_CHECK_ASSERT((pystring_splitlines("hello", true)) == _e31);
|
||||
}
|
||||
{
|
||||
std::vector<std::string> _e32 = {"hello", "world"};
|
||||
PYSTRING_CHECK_ASSERT((pystring_splitlines("hello\nworld", false)) == _e32);
|
||||
}
|
||||
{
|
||||
std::vector<std::string> _e33 = {"hello\n", "world"};
|
||||
PYSTRING_CHECK_ASSERT((pystring_splitlines("hello\nworld", true)) == _e33);
|
||||
}
|
||||
{
|
||||
std::vector<std::string> _e34 = {"hello", "world"};
|
||||
PYSTRING_CHECK_ASSERT((pystring_splitlines("hello\r\nworld", false)) == _e34);
|
||||
}
|
||||
{
|
||||
std::vector<std::string> _e35 = {"hello\r\n", "world"};
|
||||
PYSTRING_CHECK_ASSERT((pystring_splitlines("hello\r\nworld", true)) == _e35);
|
||||
}
|
||||
{
|
||||
std::vector<std::string> _e36 = {"hello", "world"};
|
||||
PYSTRING_CHECK_ASSERT((pystring_splitlines("hello\rworld", false)) == _e36);
|
||||
}
|
||||
{
|
||||
std::vector<std::string> _e37 = {"hello\r", "world"};
|
||||
PYSTRING_CHECK_ASSERT((pystring_splitlines("hello\rworld", true)) == _e37);
|
||||
}
|
||||
{
|
||||
std::vector<std::string> _e38 = {"line1", "line2", "line3"};
|
||||
PYSTRING_CHECK_ASSERT((pystring_splitlines("line1\nline2\nline3", false)) == _e38);
|
||||
}
|
||||
{
|
||||
std::vector<std::string> _e39 = {"line1\n", "line2\n", "line3"};
|
||||
PYSTRING_CHECK_ASSERT((pystring_splitlines("line1\nline2\nline3", true)) == _e39);
|
||||
}
|
||||
{
|
||||
std::vector<std::string> _e40 = {"hello"};
|
||||
PYSTRING_CHECK_ASSERT((pystring_splitlines("hello\n", false)) == _e40);
|
||||
}
|
||||
{
|
||||
std::vector<std::string> _e41 = {"hello\n"};
|
||||
PYSTRING_CHECK_ASSERT((pystring_splitlines("hello\n", true)) == _e41);
|
||||
}
|
||||
{
|
||||
std::vector<std::string> _e42 = {"", "hello"};
|
||||
PYSTRING_CHECK_ASSERT((pystring_splitlines("\nhello", false)) == _e42);
|
||||
}
|
||||
{
|
||||
std::vector<std::string> _e43 = {"\n", "hello"};
|
||||
PYSTRING_CHECK_ASSERT((pystring_splitlines("\nhello", true)) == _e43);
|
||||
}
|
||||
{
|
||||
std::vector<std::string> _e44 = {"hello", "", "world"};
|
||||
PYSTRING_CHECK_ASSERT((pystring_splitlines("hello\n\nworld", false)) == _e44);
|
||||
}
|
||||
{
|
||||
std::vector<std::string> _e45 = {"hello\n", "\n", "world"};
|
||||
PYSTRING_CHECK_ASSERT((pystring_splitlines("hello\n\nworld", true)) == _e45);
|
||||
}
|
||||
{
|
||||
std::vector<std::string> _e46 = {"hello", ""};
|
||||
PYSTRING_CHECK_ASSERT((pystring_splitlines("hello\n\n", false)) == _e46);
|
||||
}
|
||||
{
|
||||
std::vector<std::string> _e47 = {"hello\n", "\n"};
|
||||
PYSTRING_CHECK_ASSERT((pystring_splitlines("hello\n\n", true)) == _e47);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
// test_header_only_mode.cpp
|
||||
#ifndef PYSTRING_HEADER_ONLY
|
||||
#error "PYSTRING_HEADER_ONLY must be defined when using the header-only target"
|
||||
#endif
|
||||
int main() { return 0; }
|
||||
+11
-40
@@ -1,35 +1,6 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (c) 2008-2010, Sony Pictures Imageworks Inc
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// Neither the name of the organization Sony Pictures Imageworks nor the
|
||||
// names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS
|
||||
// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER
|
||||
// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright Contributors to the Pystring project.
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
// https://github.com/imageworks/pystring/blob/master/LICENSE
|
||||
|
||||
#ifndef INCLUDED_PYSTRING_UNITTEST_H
|
||||
#define INCLUDED_PYSTRING_UNITTEST_H
|
||||
@@ -52,11 +23,11 @@ struct PYSTRINGTest
|
||||
PYSTRINGTestFunc function;
|
||||
};
|
||||
|
||||
typedef std::vector<PYSTRINGTest*> UnitTests;
|
||||
typedef std::vector<PYSTRINGTest> UnitTests;
|
||||
|
||||
UnitTests& GetUnitTests();
|
||||
|
||||
struct AddTest { AddTest(PYSTRINGTest* test); };
|
||||
struct AddTest { AddTest(PYSTRINGTest&& test); };
|
||||
|
||||
/// PYSTRING_CHECK_* macros checks if the conditions is met, and if not,
|
||||
/// prints an error message indicating the module and line where the
|
||||
@@ -131,22 +102,22 @@ struct AddTest { AddTest(PYSTRINGTest* test); };
|
||||
|
||||
#define PYSTRING_ADD_TEST(group, name) \
|
||||
static void pystringtest_##group##_##name(); \
|
||||
AddTest pystringaddtest_##group##_##name(new PYSTRINGTest(#group, #name, pystringtest_##group##_##name)); \
|
||||
AddTest pystringaddtest_##group##_##name(PYSTRINGTest(#group, #name, pystringtest_##group##_##name)); \
|
||||
static void pystringtest_##group##_##name()
|
||||
|
||||
#define PYSTRING_TEST_SETUP() \
|
||||
int unit_test_failures = 0
|
||||
|
||||
#define PYSTRING_TEST_APP(app) \
|
||||
std::vector<PYSTRINGTest*>& GetUnitTests() { \
|
||||
static std::vector<PYSTRINGTest*> pystring_unit_tests; \
|
||||
std::vector<PYSTRINGTest>& GetUnitTests() { \
|
||||
static std::vector<PYSTRINGTest> pystring_unit_tests; \
|
||||
return pystring_unit_tests; } \
|
||||
AddTest::AddTest(PYSTRINGTest* test){GetUnitTests().push_back(test);}; \
|
||||
AddTest::AddTest(PYSTRINGTest&& test){GetUnitTests().emplace_back(test);} \
|
||||
PYSTRING_TEST_SETUP(); \
|
||||
int main(int, char **) { std::cerr << "\n" << #app <<"\n\n"; \
|
||||
for(size_t i = 0; i < GetUnitTests().size(); ++i) { \
|
||||
int _tmp = unit_test_failures; GetUnitTests()[i]->function(); \
|
||||
std::cerr << "Test [" << GetUnitTests()[i]->group << "] [" << GetUnitTests()[i]->name << "] - "; \
|
||||
int _tmp = unit_test_failures; GetUnitTests()[i].function(); \
|
||||
std::cerr << "Test [" << GetUnitTests()[i].group << "] [" << GetUnitTests()[i].name << "] - "; \
|
||||
std::cerr << (_tmp == unit_test_failures ? "PASSED" : "FAILED") << "\n"; } \
|
||||
std::cerr << "\n" << unit_test_failures << " tests failed\n\n"; \
|
||||
return unit_test_failures; }
|
||||
|
||||
Reference in New Issue
Block a user