Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7d16bc814c | ||
|
|
1f56d0f745 | ||
|
|
87f735237b | ||
|
|
e7b4ab950a | ||
|
|
3b85d48cf1 | ||
|
|
089194ddaf | ||
|
|
7631f72651 | ||
|
|
b62203a4b6 | ||
|
|
fd8b46f79b | ||
|
|
bf5cd2d3b1 | ||
|
|
22839311d1 | ||
|
|
cce54a1bcb | ||
|
|
281419de2f | ||
|
|
9bfc0b94ec | ||
|
|
b9b2a2eb46 | ||
|
|
4af4a86520 | ||
|
|
8c0f1738fc | ||
|
|
20dac44746 | ||
|
|
3670fab511 | ||
|
|
851abee07a | ||
|
|
8d1bdb2e43 | ||
|
|
c2de99deb4 | ||
|
|
f38e93591b | ||
|
|
9dc73e8533 | ||
|
|
ae50dda1ea | ||
|
|
a5c3cfa274 | ||
|
|
6c7eadc6c2 | ||
|
|
1080f1a199 | ||
|
|
235bcf5ddf | ||
|
|
fef753074e | ||
|
|
aa52269ea2 | ||
|
|
53e5b88e08 | ||
|
|
0f4ab0dd3f | ||
|
|
38b83f0373 | ||
|
|
b09b4ae913 | ||
|
|
af3cdaaa7c | ||
|
|
1076a670f2 | ||
|
|
4e785229c4 | ||
|
|
2ded9b2604 |
@@ -0,0 +1,481 @@
|
||||
# borrowed this from:
|
||||
# https://raw.githubusercontent.com/AcademySoftwareFoundation/Imath/main/.github/workflows/ci_workflow.yml
|
||||
# with some slight simplification
|
||||
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
# Jobs are skipped when ONLY Markdown (*.md) files are changed
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
|
||||
jobs:
|
||||
# Linux jobs run in Docker containers, so the latest OS version is OK. macOS
|
||||
# and Windows jobs need to be locked to specific virtual environment
|
||||
# versions to mitigate issues from OS updates, and will require maintenance
|
||||
# as OS versions are retired.
|
||||
#
|
||||
# GH Actions (Free plan) supports 20 concurrent jobs, with 5 concurrent macOS
|
||||
# jobs. This workflow tries to utilize (but not exceed) that budget to
|
||||
# promote timely CI.
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Linux
|
||||
# ---------------------------------------------------------------------------
|
||||
# TODO: Add ARM build. Add sanitize build.
|
||||
|
||||
linux:
|
||||
name: 'Linux CentOS 7 VFX CY${{ matrix.vfx-cy }}
|
||||
<${{ matrix.compiler-desc }} ,
|
||||
config=${{ matrix.build-type }},
|
||||
shared=${{ matrix.build-shared }},
|
||||
cxx=${{ matrix.cxx-standard }}>'
|
||||
# GH-hosted VM. The build runs in CentOS 7 'container' defined below.
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
# DockerHub: https://hub.docker.com/u/aswf
|
||||
# Source: https://github.com/AcademySoftwareFoundation/aswf-docker
|
||||
image: aswf/ci-openexr:${{ matrix.vfx-cy }}
|
||||
strategy:
|
||||
matrix:
|
||||
build: [1, 2, 3, 4, 9, 10, 11, 12, 13, 14, 15, 20, 21, 22]
|
||||
include:
|
||||
# -------------------------------------------------------------------
|
||||
# GCC, VFX CY2022
|
||||
# -------------------------------------------------------------------
|
||||
# C++17, Python 3.9
|
||||
- build: 1
|
||||
build-type: Release
|
||||
build-shared: 'ON'
|
||||
cxx-standard: 17
|
||||
cxx-compiler: g++
|
||||
cc-compiler: gcc
|
||||
compiler-desc: gcc9.3.1
|
||||
vfx-cy: 2022
|
||||
|
||||
# C++17, Python 3.9.7, Debug
|
||||
- build: 2
|
||||
build-type: Debug
|
||||
build-shared: 'ON'
|
||||
cxx-standard: 17
|
||||
cxx-compiler: g++
|
||||
cc-compiler: gcc
|
||||
compiler-desc: gcc9.3.1
|
||||
vfx-cy: 2022
|
||||
|
||||
# C++17, Python 3.9.7, Static
|
||||
- build: 3
|
||||
build-type: Release
|
||||
build-shared: 'OFF'
|
||||
cxx-standard: 17
|
||||
cxx-compiler: g++
|
||||
cc-compiler: gcc
|
||||
compiler-desc: gcc9.3.1
|
||||
vfx-cy: 2022
|
||||
|
||||
# C++14, Python 3.9.7, Static
|
||||
- build: 4
|
||||
build-type: Release
|
||||
build-shared: 'ON'
|
||||
cxx-standard: 14
|
||||
cxx-compiler: g++
|
||||
cc-compiler: gcc
|
||||
compiler-desc: gcc9.3.1
|
||||
vfx-cy: 2022
|
||||
|
||||
# C++17, no Python
|
||||
# - build: 5
|
||||
# build-type: Release
|
||||
# build-shared: 'ON'
|
||||
# cxx-standard: 17
|
||||
# cxx-compiler: g++
|
||||
# cc-compiler: gcc
|
||||
# compiler-desc: gcc9.3.1
|
||||
# python: 'OFF'
|
||||
# python-desc: no python
|
||||
# vfx-cy: 2022
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
# GCC, VFX CY2021
|
||||
# -------------------------------------------------------------------
|
||||
# C++17, Python 3.7.9
|
||||
- build: 9
|
||||
build-type: Release
|
||||
build-shared: 'ON'
|
||||
cxx-standard: 17
|
||||
cxx-compiler: g++
|
||||
cc-compiler: gcc
|
||||
compiler-desc: gcc9.3.1
|
||||
python: 'ON'
|
||||
vfx-cy: 2021
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
# GCC, VFX CY2020
|
||||
# -------------------------------------------------------------------
|
||||
# C++14, Python 3.7
|
||||
- build: 10
|
||||
build-type: Release
|
||||
build-shared: 'ON'
|
||||
cxx-standard: 14
|
||||
cxx-compiler: g++
|
||||
cc-compiler: gcc
|
||||
compiler-desc: gcc6.3.1
|
||||
vfx-cy: 2020
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
# GCC, VFX CY2019
|
||||
# -------------------------------------------------------------------
|
||||
# C++11, Python 2.7
|
||||
- build: 11
|
||||
build-type: Release
|
||||
build-shared: 'ON'
|
||||
cxx-standard: 11
|
||||
cxx-compiler: g++
|
||||
cc-compiler: gcc
|
||||
compiler-desc: gcc6.3.1
|
||||
vfx-cy: 2019
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
# Clang, VFX CY2022
|
||||
# -------------------------------------------------------------------
|
||||
# C++17, Python 3.9
|
||||
- build: 12
|
||||
build-type: Release
|
||||
build-shared: 'ON'
|
||||
cxx-standard: 17
|
||||
cxx-compiler: clang++
|
||||
cc-compiler: clang
|
||||
compiler-desc: clang10.4
|
||||
vfx-cy: 2022
|
||||
|
||||
# C++17, Python 3.9.7, Debug
|
||||
- build: 13
|
||||
build-type: Debug
|
||||
build-shared: 'ON'
|
||||
cxx-standard: 17
|
||||
cxx-compiler: clang++
|
||||
cc-compiler: clang
|
||||
compiler-desc: clang10.4
|
||||
vfx-cy: 2022
|
||||
|
||||
# C++17, Python 3.9.7, Static
|
||||
- build: 14
|
||||
build-type: Release
|
||||
build-shared: 'OFF'
|
||||
cxx-standard: 17
|
||||
cxx-compiler: clang++
|
||||
cc-compiler: clang
|
||||
compiler-desc: clang10.4
|
||||
vfx-cy: 2022
|
||||
|
||||
# C++14, Python 3.9.7, Static
|
||||
- build: 15
|
||||
build-type: Release
|
||||
build-shared: 'ON'
|
||||
cxx-standard: 14
|
||||
cxx-compiler: clang++
|
||||
cc-compiler: clang
|
||||
compiler-desc: clang10.4
|
||||
vfx-cy: 2022
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
# Clang, VFX CY2021
|
||||
# -------------------------------------------------------------------
|
||||
# C++17, Python 3.7.9
|
||||
- build: 20
|
||||
build-type: Release
|
||||
build-shared: 'ON'
|
||||
cxx-standard: 17
|
||||
cxx-compiler: clang++
|
||||
cc-compiler: clang
|
||||
compiler-desc: clang10.4
|
||||
vfx-cy: 2021
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
# Clang, VFX CY2020
|
||||
# -------------------------------------------------------------------
|
||||
# C++14, Python 3.7
|
||||
- build: 21
|
||||
build-type: Release
|
||||
build-shared: 'ON'
|
||||
cxx-standard: 14
|
||||
cxx-compiler: clang++
|
||||
cc-compiler: clang
|
||||
compiler-desc: clang7.8
|
||||
vfx-cy: 2020
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
# Clang, VFX CY2019
|
||||
# -------------------------------------------------------------------
|
||||
# C++11, Python 2.7
|
||||
- build: 22
|
||||
build-type: Release
|
||||
build-shared: 'ON'
|
||||
cxx-standard: 11
|
||||
cxx-compiler: clang++
|
||||
cc-compiler: clang
|
||||
compiler-desc: clang7.8
|
||||
vfx-cy: 2019
|
||||
|
||||
env:
|
||||
CXX: ${{ matrix.cxx-compiler }}
|
||||
CC: ${{ matrix.cc-compiler }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
- name: Create build directories
|
||||
run: |
|
||||
mkdir _install
|
||||
mkdir _build
|
||||
- name: Configure
|
||||
run: |
|
||||
cmake .. \
|
||||
-DCMAKE_INSTALL_PREFIX=../_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 . \
|
||||
--target install \
|
||||
--config ${{ matrix.build-type }}
|
||||
working-directory: _build
|
||||
- name: Test
|
||||
run: |
|
||||
ctest -C ${{ matrix.build_type }}
|
||||
working-directory: _build
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# macOS
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
macos_no_python:
|
||||
name: 'macOS 10.15
|
||||
<AppleClang 11.0
|
||||
config=${{ matrix.build-type }},
|
||||
shared=${{ matrix.build-shared }},
|
||||
cxx=${{ matrix.cxx-standard }},
|
||||
docs=${{ matrix.build-docs }}>'
|
||||
runs-on: macos-10.15
|
||||
strategy:
|
||||
matrix:
|
||||
build: [1, 2, 3, 4, 5]
|
||||
include:
|
||||
# C++11
|
||||
- build: 1
|
||||
build-type: Release
|
||||
build-shared: 'ON'
|
||||
build-docs: 'ON'
|
||||
cxx-standard: 17
|
||||
exclude-tests:
|
||||
|
||||
# Debug
|
||||
- build: 2
|
||||
build-type: Debug
|
||||
build-shared: 'ON'
|
||||
build-docs: 'OFF'
|
||||
cxx-standard: 17
|
||||
exclude-tests:
|
||||
|
||||
# Static
|
||||
- build: 3
|
||||
build-type: Debug
|
||||
build-shared: 'OFF'
|
||||
build-docs: 'OFF'
|
||||
cxx-standard: 17
|
||||
exclude-tests:
|
||||
|
||||
# C++14
|
||||
- build: 4
|
||||
build-type: Release
|
||||
build-shared: 'ON'
|
||||
build-docs: 'OFF'
|
||||
cxx-standard: 14
|
||||
exclude-tests:
|
||||
|
||||
# C++11
|
||||
- build: 5
|
||||
build-type: Release
|
||||
build-shared: 'ON'
|
||||
build-docs: 'OFF'
|
||||
cxx-standard: 11
|
||||
exclude-tests:
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
- name: Create build directories
|
||||
run: |
|
||||
mkdir _install
|
||||
mkdir _build
|
||||
|
||||
- name: Configure
|
||||
run: |
|
||||
cmake ../. \
|
||||
-DCMAKE_INSTALL_PREFIX=../_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 . \
|
||||
--target install \
|
||||
--config ${{ matrix.build-type }} \
|
||||
-- -j2
|
||||
working-directory: _build
|
||||
- name: Test
|
||||
run: |
|
||||
ctest -C ${{ matrix.build_type }}
|
||||
working-directory: _build
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Windows
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
windows:
|
||||
name: 'Windows 2019
|
||||
<${{ matrix.compiler-desc }},
|
||||
config=${{ matrix.build-type }},
|
||||
shared=${{ matrix.build-shared }},
|
||||
cxx=${{ matrix.cxx-standard }},
|
||||
docs=${{ matrix.build-docs }}>'
|
||||
runs-on: windows-${{ matrix.osver }}
|
||||
strategy:
|
||||
matrix:
|
||||
build: [1, 3, 4, 6, 7, 8]
|
||||
include:
|
||||
# -------------------------------------------------------------------
|
||||
# VFX CY2022 - C++17 - Windows 2019
|
||||
# -------------------------------------------------------------------
|
||||
# C++17, Release Shared
|
||||
- build: 1
|
||||
build-type: Release
|
||||
build-shared: 'ON'
|
||||
build-docs: 'ON'
|
||||
compiler-desc: msvc16.11
|
||||
cxx-standard: 17
|
||||
vfx-cy: 2022
|
||||
exclude-tests:
|
||||
osver: 2019
|
||||
|
||||
# C++17, Debug -
|
||||
## - build: 2
|
||||
## build-type: Debug
|
||||
## build-shared: 'ON'
|
||||
## build-docs: 'OFF'
|
||||
## cxx-standard: 17
|
||||
## exclude-tests:
|
||||
|
||||
# C++17, Release Static
|
||||
- build: 3
|
||||
build-type: Release
|
||||
build-shared: 'OFF'
|
||||
build-docs: 'OFF'
|
||||
compiler-desc: msvc16.11
|
||||
cxx-standard: 17
|
||||
vfx-cy: 2022
|
||||
exclude-tests:
|
||||
osver: 2019
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
# VFX CY2022 - C++17 - Windows 2022
|
||||
# -------------------------------------------------------------------
|
||||
# C++17, Release Shared
|
||||
- build: 4
|
||||
build-type: Release
|
||||
build-shared: 'ON'
|
||||
build-docs: 'ON'
|
||||
compiler-desc: msvc17.1
|
||||
cxx-standard: 17
|
||||
vfx-cy: 2022
|
||||
exclude-tests:
|
||||
osver: 2022
|
||||
|
||||
# C++17, Debug -
|
||||
## - build: 5
|
||||
## build-type: Debug
|
||||
## build-shared: 'ON'
|
||||
## build-docs: 'OFF'
|
||||
## cxx-standard: 17
|
||||
## exclude-tests:
|
||||
|
||||
# C++17, Release Static
|
||||
- build: 6
|
||||
build-type: Release
|
||||
build-shared: 'OFF'
|
||||
build-docs: 'OFF'
|
||||
compiler-desc: msvc17.1
|
||||
cxx-standard: 17
|
||||
vfx-cy: 2022
|
||||
exclude-tests:
|
||||
osver: 2022
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
# VFX CY2020 - C++14 - Windows 2019
|
||||
# -------------------------------------------------------------------
|
||||
# C++14, Release Shared
|
||||
- build: 7
|
||||
build-type: Release
|
||||
build-shared: 'ON'
|
||||
build-docs: 'OFF'
|
||||
compiler-desc: msvc16.11
|
||||
cxx-standard: 14
|
||||
vfx-cy: 2020
|
||||
exclude-tests:
|
||||
osver: 2019
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
# VFX CY2019 - C++11 - Windows 2019
|
||||
# -------------------------------------------------------------------
|
||||
# C++11, Release Shared
|
||||
- build: 8
|
||||
build-type: Release
|
||||
build-shared: 'ON'
|
||||
build-docs: 'OFF'
|
||||
compiler-desc: msvc16.11
|
||||
cxx-standard: 11
|
||||
exclude-tests:
|
||||
osver: 2019
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
- 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=../_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 . \
|
||||
--target install \
|
||||
--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,5 @@
|
||||
test
|
||||
.libs
|
||||
libpystring.la
|
||||
pystring.lo
|
||||
pystring.o
|
||||
@@ -0,0 +1,22 @@
|
||||
cmake_minimum_required(VERSION 3.2)
|
||||
project(pystring CXX)
|
||||
|
||||
set(BUILD_SHARED_LIBS YES)
|
||||
|
||||
add_library(pystring
|
||||
pystring.cpp
|
||||
pystring.h
|
||||
)
|
||||
|
||||
add_executable (pystring_test test.cpp)
|
||||
TARGET_LINK_LIBRARIES (pystring_test pystring)
|
||||
|
||||
enable_testing()
|
||||
add_test(NAME PyStringTest COMMAND pystring_test)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
install(TARGETS pystring
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
)
|
||||
|
||||
@@ -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,7 @@
|
||||
LIBTOOL = libtool
|
||||
LIBDIR = /usr/lib
|
||||
CXX = g++
|
||||
CXXFLAGS = -g -O3 -Wall
|
||||
LIBTOOL ?= libtool
|
||||
LIBDIR ?= /usr/lib
|
||||
CXX ?= g++
|
||||
CXXFLAGS ?= -g -O3 -Wall -Wextra -Wshadow -Wconversion -Wcast-qual -Wformat=2
|
||||
|
||||
all: libpystring.la
|
||||
|
||||
@@ -16,3 +16,9 @@ install: libpystring.la
|
||||
|
||||
clean:
|
||||
$(RM) -fr pystring.lo pystring.o libpystring.la .libs
|
||||
|
||||
.PHONY: test
|
||||
test:
|
||||
$(RM) -fr test
|
||||
$(CXX) pystring.cpp test.cpp $(CXXFLAGS) -DPYSTRING_UNITTEST=1 -o test
|
||||
./test
|
||||
|
||||
@@ -1,6 +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/
|
||||
@@ -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.
|
||||
+779
-187
File diff suppressed because it is too large
Load Diff
+173
-33
@@ -1,35 +1,7 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// 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
|
||||
@@ -165,6 +137,12 @@ namespace pystring
|
||||
///
|
||||
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);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Split the string around first occurance of sep.
|
||||
/// Three strings will always placed into result. If sep is found, the strings will
|
||||
@@ -172,6 +150,12 @@ namespace pystring
|
||||
/// 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 );
|
||||
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 Return a copy of the string with all occurrences of substring old replaced by new. If
|
||||
@@ -205,6 +189,12 @@ namespace pystring
|
||||
/// 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 );
|
||||
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
|
||||
@@ -219,6 +209,12 @@ namespace pystring
|
||||
/// any whitespace string is a separator.
|
||||
///
|
||||
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.
|
||||
@@ -228,12 +224,24 @@ namespace pystring
|
||||
/// any whitespace string is a separator.
|
||||
///
|
||||
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 );
|
||||
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,
|
||||
@@ -286,6 +294,138 @@ namespace pystring
|
||||
///
|
||||
/// @ }
|
||||
///
|
||||
}
|
||||
|
||||
|
||||
namespace os
|
||||
{
|
||||
namespace path
|
||||
{
|
||||
// All of the function below have three versions.
|
||||
// Example:
|
||||
// join(...)
|
||||
// join_nt(...)
|
||||
// join_posix(...)
|
||||
//
|
||||
// The regular function dispatches to the other versions - based on the OS
|
||||
// at compile time - to match the result you'd get from the python
|
||||
// interepreter on the same operating system
|
||||
//
|
||||
// Should you want to 'lock off' to a particular version of the string
|
||||
// manipulation across *all* operating systems, use the version with the
|
||||
// _OS you are interested in. I.e., you can use posix style path joining,
|
||||
// even on Windows, with join_posix.
|
||||
//
|
||||
// The naming, (nt, posix) matches the cpython source implementation.
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @defgroup functions pystring::os::path
|
||||
/// @{
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Return the base name of pathname path. This is the second half of the pair returned
|
||||
/// by split(path). Note that the result of this function is different from the Unix basename
|
||||
/// 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);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @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);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @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);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Return a normalized absolutized version of the pathname 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);
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Join one or more path components intelligently. If any component is an absolute
|
||||
/// path, all previous components (on Windows, including the previous drive letter, if there
|
||||
/// was one) are thrown away, and joining continues. The return value is the concatenation of
|
||||
/// path1, and optionally path2, etc., with exactly one directory separator (os.sep) inserted
|
||||
/// between components, unless path2 is empty. Note that on Windows, since there is a current
|
||||
/// directory for each drive, os.path.join("c:", "foo") represents a path relative to the
|
||||
/// 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);
|
||||
|
||||
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);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Normalize a pathname. This collapses redundant separators and up-level references
|
||||
/// so that A//B, A/B/, A/./B and A/foo/../B all become A/B. It does not normalize the case
|
||||
/// (use normcase() for that). On Windows, it converts forward slashes to backward slashes.
|
||||
/// 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);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Split the pathname path into a pair, (head, tail) where tail is the last pathname
|
||||
/// component and head is everything leading up to that. The tail part will never contain a
|
||||
/// slash; if path ends in a slash, tail will be empty. If there is no slash in path, head
|
||||
/// will be empty. If path is empty, both head and tail are empty. Trailing slashes are
|
||||
/// stripped from head unless it is the root (one or more slashes only). In all cases,
|
||||
/// 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);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Split the pathname path into a pair (drive, tail) where drive is either a drive
|
||||
/// specification or the empty string. On systems which do not use drive specifications,
|
||||
/// 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);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// @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);
|
||||
|
||||
///
|
||||
/// @ }
|
||||
///
|
||||
} // namespace path
|
||||
} // namespace os
|
||||
|
||||
} // namespace pystring
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,660 @@
|
||||
// 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"
|
||||
|
||||
PYSTRING_TEST_APP(PyStringUnitTests)
|
||||
|
||||
PYSTRING_ADD_TEST(pystring, endswith)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(pystring::endswith("", ""), true);
|
||||
PYSTRING_CHECK_EQUAL(pystring::endswith("", "a"), false);
|
||||
PYSTRING_CHECK_EQUAL(pystring::endswith("a", ""), true);
|
||||
PYSTRING_CHECK_EQUAL(pystring::endswith("", ".mesh"), false);
|
||||
PYSTRING_CHECK_EQUAL(pystring::endswith("help", ".mesh"), false);
|
||||
PYSTRING_CHECK_EQUAL(pystring::endswith("help", ".mesh", 0), false);
|
||||
PYSTRING_CHECK_EQUAL(pystring::endswith("help", ".mesh", 1), false);
|
||||
PYSTRING_CHECK_EQUAL(pystring::endswith("help", ".mesh", 1, 2), false);
|
||||
PYSTRING_CHECK_EQUAL(pystring::endswith("help", ".mesh", 1, 1), false);
|
||||
PYSTRING_CHECK_EQUAL(pystring::endswith("help", ".mesh", 1, -1), false);
|
||||
PYSTRING_CHECK_EQUAL(pystring::endswith("help", ".mesh", -1), false);
|
||||
PYSTRING_CHECK_EQUAL(pystring::endswith(".mesh", ".mesh"), true);
|
||||
PYSTRING_CHECK_EQUAL(pystring::endswith("a.mesh", ".mesh"), true);
|
||||
PYSTRING_CHECK_EQUAL(pystring::endswith("a.", "."), true);
|
||||
PYSTRING_CHECK_EQUAL(pystring::endswith("abcdef", "ef"), true);
|
||||
PYSTRING_CHECK_EQUAL(pystring::endswith("abcdef", "cdef"), true);
|
||||
PYSTRING_CHECK_EQUAL(pystring::endswith("abcdef", "cdef", 2), true);
|
||||
PYSTRING_CHECK_EQUAL(pystring::endswith("abcdef", "cdef", 3), false);
|
||||
PYSTRING_CHECK_EQUAL(pystring::endswith("abcdef", "cdef", 2, 3), false);
|
||||
PYSTRING_CHECK_EQUAL(pystring::endswith("abcdef", "cdef", -10), true);
|
||||
}
|
||||
|
||||
PYSTRING_ADD_TEST(pystring, find)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(pystring::find("", ""), 0);
|
||||
PYSTRING_CHECK_EQUAL(pystring::find("", "a"), -1);
|
||||
PYSTRING_CHECK_EQUAL(pystring::find("a", ""), 0);
|
||||
PYSTRING_CHECK_EQUAL(pystring::find("a", "a"), 0);
|
||||
PYSTRING_CHECK_EQUAL(pystring::find("abcdef", ""), 0);
|
||||
PYSTRING_CHECK_EQUAL(pystring::find("abcdef", "", -1), 5);
|
||||
PYSTRING_CHECK_EQUAL(pystring::find("abcdef", "", -2), 4);
|
||||
PYSTRING_CHECK_EQUAL(pystring::find("abcdef", "", -5), 1);
|
||||
PYSTRING_CHECK_EQUAL(pystring::find("abcdef", "", -6), 0);
|
||||
PYSTRING_CHECK_EQUAL(pystring::find("abcdef", "", -7), 0);
|
||||
|
||||
PYSTRING_CHECK_EQUAL(pystring::find("abcdef", "def"), 3);
|
||||
PYSTRING_CHECK_EQUAL(pystring::find("abcdef", "def", 3), 3);
|
||||
PYSTRING_CHECK_EQUAL(pystring::find("abcdef", "def", 4), -1);
|
||||
PYSTRING_CHECK_EQUAL(pystring::find("abcdef", "def", -5), 3);
|
||||
PYSTRING_CHECK_EQUAL(pystring::find("abcdef", "def", -1), -1);
|
||||
|
||||
PYSTRING_CHECK_EQUAL(pystring::find("abcabcabc", "bc", -2), 7);
|
||||
PYSTRING_CHECK_EQUAL(pystring::find("abcabcabc", "bc", -1), -1);
|
||||
PYSTRING_CHECK_EQUAL(pystring::find("abcabcabc", "bc", 0), 1);
|
||||
PYSTRING_CHECK_EQUAL(pystring::find("abcabcabc", "bc", 1), 1);
|
||||
PYSTRING_CHECK_EQUAL(pystring::find("abcabcabc", "bc", 2), 4);
|
||||
PYSTRING_CHECK_EQUAL(pystring::find("abcabcabc", "bc", 4), 4);
|
||||
PYSTRING_CHECK_EQUAL(pystring::find("abcabcabc", "bc", 7), 7);
|
||||
PYSTRING_CHECK_EQUAL(pystring::find("abcabcabc", "bc", 4, 3), -1);
|
||||
PYSTRING_CHECK_EQUAL(pystring::find("abcabcabc", "bc", 4, 4), -1);
|
||||
PYSTRING_CHECK_EQUAL(pystring::find("abcabcabc", "bc", 4, 5), -1);
|
||||
PYSTRING_CHECK_EQUAL(pystring::find("abcabcabc", "bc", 4, -1), 4);
|
||||
PYSTRING_CHECK_EQUAL(pystring::find("abcabcabc", "bc", 4, 6), 4);
|
||||
}
|
||||
|
||||
PYSTRING_ADD_TEST(pystring, rfind)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(pystring::rfind("", ""), 0);
|
||||
PYSTRING_CHECK_EQUAL(pystring::rfind("", "a"), -1);
|
||||
PYSTRING_CHECK_EQUAL(pystring::rfind("a", ""), 1);
|
||||
PYSTRING_CHECK_EQUAL(pystring::rfind("a", "a"), 0);
|
||||
|
||||
PYSTRING_CHECK_EQUAL(pystring::rfind("abcdef", ""), 6);
|
||||
PYSTRING_CHECK_EQUAL(pystring::rfind("abcdef", "", 0, 1), 1);
|
||||
PYSTRING_CHECK_EQUAL(pystring::rfind("abcdef", "", 0, 5), 5);
|
||||
PYSTRING_CHECK_EQUAL(pystring::rfind("abcdef", "", 0,-1), 5);
|
||||
PYSTRING_CHECK_EQUAL(pystring::rfind("abcdef", "", 0,-3), 3);
|
||||
|
||||
PYSTRING_CHECK_EQUAL(pystring::rfind("abcdef", "def"), 3);
|
||||
PYSTRING_CHECK_EQUAL(pystring::rfind("abcdef", "def", 3), 3);
|
||||
PYSTRING_CHECK_EQUAL(pystring::rfind("abcdef", "def", 4), -1);
|
||||
PYSTRING_CHECK_EQUAL(pystring::rfind("abcdef", "def", -5), 3);
|
||||
PYSTRING_CHECK_EQUAL(pystring::rfind("abcdef", "def", -1), -1);
|
||||
|
||||
PYSTRING_CHECK_EQUAL(pystring::rfind("abcabcabc", "bc", -2), 7);
|
||||
PYSTRING_CHECK_EQUAL(pystring::rfind("abcabcabc", "bc", -1), -1);
|
||||
PYSTRING_CHECK_EQUAL(pystring::rfind("abcabcabc", "bc", 0), 7);
|
||||
PYSTRING_CHECK_EQUAL(pystring::rfind("abcabcabc", "bc", 1), 7);
|
||||
PYSTRING_CHECK_EQUAL(pystring::rfind("abcabcabc", "bc", 4), 7);
|
||||
PYSTRING_CHECK_EQUAL(pystring::rfind("abcabcabc", "bc", 7), 7);
|
||||
PYSTRING_CHECK_EQUAL(pystring::rfind("abcabcabc", "bc", 4, -5), -1);
|
||||
PYSTRING_CHECK_EQUAL(pystring::rfind("abcabcabc", "bc", 4, -10), -1);
|
||||
PYSTRING_CHECK_EQUAL(pystring::rfind("abcabcabc", "bc", 4, 20), 7);
|
||||
|
||||
PYSTRING_CHECK_EQUAL(pystring::rfind("abcabcabc", "abc", 6, 8), -1);
|
||||
}
|
||||
|
||||
PYSTRING_ADD_TEST(pystring, replace)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(pystring::replace("abcdef", "foo", "bar"), "abcdef");
|
||||
PYSTRING_CHECK_EQUAL(pystring::replace("abcdef", "ab", "cd"), "cdcdef");
|
||||
PYSTRING_CHECK_EQUAL(pystring::replace("abcdef", "ab", ""), "cdef");
|
||||
PYSTRING_CHECK_EQUAL(pystring::replace("abcabc", "ab", ""), "cc");
|
||||
PYSTRING_CHECK_EQUAL(pystring::replace("abcdef", "", ""), "abcdef");
|
||||
PYSTRING_CHECK_EQUAL(pystring::replace("abcdef", "", "."), ".a.b.c.d.e.f.");
|
||||
}
|
||||
|
||||
PYSTRING_ADD_TEST(pystring, slice)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(pystring::slice(""), "");
|
||||
PYSTRING_CHECK_EQUAL(pystring::slice("", 1), "");
|
||||
PYSTRING_CHECK_EQUAL(pystring::slice("", -1), "");
|
||||
PYSTRING_CHECK_EQUAL(pystring::slice("", -1,2), "");
|
||||
PYSTRING_CHECK_EQUAL(pystring::slice("abcdef"), "abcdef");
|
||||
PYSTRING_CHECK_EQUAL(pystring::slice("abcdef",0), "abcdef");
|
||||
PYSTRING_CHECK_EQUAL(pystring::slice("abcdef",1), "bcdef");
|
||||
PYSTRING_CHECK_EQUAL(pystring::slice("abcdef",2), "cdef");
|
||||
PYSTRING_CHECK_EQUAL(pystring::slice("abcdef",2,2), "");
|
||||
PYSTRING_CHECK_EQUAL(pystring::slice("abcdef",2,3), "c");
|
||||
PYSTRING_CHECK_EQUAL(pystring::slice("abcdef",2,1), "");
|
||||
PYSTRING_CHECK_EQUAL(pystring::slice("abcdef",2,-1), "cde");
|
||||
PYSTRING_CHECK_EQUAL(pystring::slice("abcdef",2,-2), "cd");
|
||||
PYSTRING_CHECK_EQUAL(pystring::slice("abcdef",2,-3), "c");
|
||||
PYSTRING_CHECK_EQUAL(pystring::slice("abcdef",2,-4), "");
|
||||
PYSTRING_CHECK_EQUAL(pystring::slice("abcdef",2,-5), "");
|
||||
PYSTRING_CHECK_EQUAL(pystring::slice("abcdef",-1), "f");
|
||||
PYSTRING_CHECK_EQUAL(pystring::slice("abcdef",-2), "ef");
|
||||
PYSTRING_CHECK_EQUAL(pystring::slice("abcdef",-99), "abcdef");
|
||||
PYSTRING_CHECK_EQUAL(pystring::slice("abcdef",-99,-98), "");
|
||||
PYSTRING_CHECK_EQUAL(pystring::slice("abcdef",-2, 3), "");
|
||||
PYSTRING_CHECK_EQUAL(pystring::slice("abcdef",-2, 10), "ef");
|
||||
PYSTRING_CHECK_EQUAL(pystring::slice("abcdef",-1), "f");
|
||||
PYSTRING_CHECK_EQUAL(pystring::slice("abcdef",0,-1), "abcde");
|
||||
}
|
||||
|
||||
PYSTRING_ADD_TEST(pystring, split)
|
||||
{
|
||||
std::vector< std::string > result;
|
||||
|
||||
{
|
||||
result.clear();
|
||||
pystring::split("", result, "/", 1);
|
||||
PYSTRING_CHECK_EQUAL(result.size(), 1);
|
||||
if(result.size()==1)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(result[0], "");
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
result.clear();
|
||||
pystring::split("/", result, "/", 1);
|
||||
PYSTRING_CHECK_EQUAL(result.size(), 2);
|
||||
if(result.size()==2)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(result[0], "");
|
||||
PYSTRING_CHECK_EQUAL(result[1], "");
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
result.clear();
|
||||
pystring::split(" ", result, " ", 1);
|
||||
PYSTRING_CHECK_EQUAL(result.size(), 2);
|
||||
if(result.size()==2)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(result[0], "");
|
||||
PYSTRING_CHECK_EQUAL(result[1], "");
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
result.clear();
|
||||
pystring::split(" /", result, "/", 1);
|
||||
PYSTRING_CHECK_EQUAL(result.size(), 2);
|
||||
if(result.size()==2)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(result[0], " ");
|
||||
PYSTRING_CHECK_EQUAL(result[1], "");
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
result.clear();
|
||||
pystring::split(" //", result, "/", 1);
|
||||
PYSTRING_CHECK_EQUAL(result.size(), 2);
|
||||
if(result.size()==2)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(result[0], " ");
|
||||
PYSTRING_CHECK_EQUAL(result[1], "/");
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
result.clear();
|
||||
pystring::split("a ", result, " ", 1);
|
||||
PYSTRING_CHECK_EQUAL(result.size(), 2);
|
||||
if(result.size()==2)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(result[0], "a");
|
||||
PYSTRING_CHECK_EQUAL(result[1], " ");
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
result.clear();
|
||||
pystring::split("//as//rew//gdf", result, "//");
|
||||
PYSTRING_CHECK_EQUAL(result.size(), 4);
|
||||
if(result.size()==4)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(result[0], "");
|
||||
PYSTRING_CHECK_EQUAL(result[1], "as");
|
||||
PYSTRING_CHECK_EQUAL(result[2], "rew");
|
||||
PYSTRING_CHECK_EQUAL(result[3], "gdf");
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
result.clear();
|
||||
pystring::split("/root", result, "/", 1);
|
||||
PYSTRING_CHECK_EQUAL(result.size(), 2);
|
||||
if(result.size()==2)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(result[0], "");
|
||||
PYSTRING_CHECK_EQUAL(result[1], "root");
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
result.clear();
|
||||
pystring::split("/root/world", result, "/", 0);
|
||||
PYSTRING_CHECK_EQUAL(result.size(), 1);
|
||||
if(result.size()==1)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(result[0], "/root/world");
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
result.clear();
|
||||
pystring::split("/root/world", result, "/", 1);
|
||||
PYSTRING_CHECK_EQUAL(result.size(), 2);
|
||||
if(result.size()==2)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(result[0], "");
|
||||
PYSTRING_CHECK_EQUAL(result[1], "root/world");
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
result.clear();
|
||||
pystring::split("/root/world", result, "/", 2);
|
||||
PYSTRING_CHECK_EQUAL(result.size(), 3);
|
||||
if(result.size()==3)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(result[0], "");
|
||||
PYSTRING_CHECK_EQUAL(result[1], "root");
|
||||
PYSTRING_CHECK_EQUAL(result[2], "world");
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
result.clear();
|
||||
pystring::split("/root/world", result, "/", -1);
|
||||
PYSTRING_CHECK_EQUAL(result.size(), 3);
|
||||
if(result.size()==3)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(result[0], "");
|
||||
PYSTRING_CHECK_EQUAL(result[1], "root");
|
||||
PYSTRING_CHECK_EQUAL(result[2], "world");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PYSTRING_ADD_TEST(pystring, rsplit)
|
||||
{
|
||||
std::vector< std::string > result;
|
||||
{
|
||||
result.clear();
|
||||
pystring::rsplit("", result, "/", 1);
|
||||
PYSTRING_CHECK_EQUAL(result.size(), 1);
|
||||
if(result.size()==1)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(result[0], "");
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// "".rsplit(None, 1)
|
||||
result.clear();
|
||||
pystring::rsplit("", result, "", 1);
|
||||
PYSTRING_CHECK_EQUAL(result.size(), 0);
|
||||
}
|
||||
|
||||
{
|
||||
// " ".rsplit(None, 1)
|
||||
result.clear();
|
||||
pystring::rsplit(" ", result, "", 1);
|
||||
PYSTRING_CHECK_EQUAL(result.size(), 0);
|
||||
}
|
||||
|
||||
{
|
||||
result.clear();
|
||||
pystring::rsplit(" ", result, "", 1);
|
||||
PYSTRING_CHECK_EQUAL(result.size(), 0);
|
||||
}
|
||||
|
||||
{
|
||||
result.clear();
|
||||
pystring::rsplit("/", result, "/", 1);
|
||||
PYSTRING_CHECK_EQUAL(result.size(), 2);
|
||||
if(result.size()==2)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(result[0], "");
|
||||
PYSTRING_CHECK_EQUAL(result[1], "");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
result.clear();
|
||||
pystring::rsplit(" /", result, "/", 1);
|
||||
PYSTRING_CHECK_EQUAL(result.size(), 2);
|
||||
if(result.size()==2)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(result[0], " ");
|
||||
PYSTRING_CHECK_EQUAL(result[1], "");
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
result.clear();
|
||||
pystring::rsplit(" //", result, "/", 1);
|
||||
PYSTRING_CHECK_EQUAL(result.size(), 2);
|
||||
if(result.size()==2)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(result[0], " /");
|
||||
PYSTRING_CHECK_EQUAL(result[1], "");
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
result.clear();
|
||||
pystring::rsplit("/root", result, "/", 1);
|
||||
PYSTRING_CHECK_EQUAL(result.size(), 2);
|
||||
if(result.size()==2)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(result[0], "");
|
||||
PYSTRING_CHECK_EQUAL(result[1], "root");
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
result.clear();
|
||||
pystring::rsplit("/root/world", result, "/", 0);
|
||||
PYSTRING_CHECK_EQUAL(result.size(), 1);
|
||||
if(result.size()==1)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(result[0], "/root/world");
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
result.clear();
|
||||
pystring::rsplit("/root/world", result, "/", 1);
|
||||
PYSTRING_CHECK_EQUAL(result.size(), 2);
|
||||
if(result.size()==2)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(result[0], "/root");
|
||||
PYSTRING_CHECK_EQUAL(result[1], "world");
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
result.clear();
|
||||
pystring::rsplit("/root/world", result, "/", 2);
|
||||
PYSTRING_CHECK_EQUAL(result.size(), 3);
|
||||
if(result.size()==3)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(result[0], "");
|
||||
PYSTRING_CHECK_EQUAL(result[1], "root");
|
||||
PYSTRING_CHECK_EQUAL(result[2], "world");
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
result.clear();
|
||||
pystring::rsplit("/root/world", result, "/", -1);
|
||||
PYSTRING_CHECK_EQUAL(result.size(), 3);
|
||||
if(result.size()==3)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(result[0], "");
|
||||
PYSTRING_CHECK_EQUAL(result[1], "root");
|
||||
PYSTRING_CHECK_EQUAL(result[2], "world");
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// " root world".rsplit(None, 0)
|
||||
result.clear();
|
||||
pystring::rsplit(" root world", result, "", 0);
|
||||
PYSTRING_CHECK_EQUAL(result.size(), 1);
|
||||
if(result.size()==1)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(result[0], " root world");
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// " root world".rsplit(None, 1)
|
||||
result.clear();
|
||||
pystring::rsplit(" root world", result, "", 1);
|
||||
PYSTRING_CHECK_EQUAL(result.size(), 2);
|
||||
if(result.size()==2)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(result[0], " root");
|
||||
PYSTRING_CHECK_EQUAL(result[1], "world");
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// " root world".rsplit(None, 2)
|
||||
result.clear();
|
||||
pystring::rsplit(" root world", result, "", 2);
|
||||
PYSTRING_CHECK_EQUAL(result.size(), 2);
|
||||
if(result.size()==2)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(result[0], "root");
|
||||
PYSTRING_CHECK_EQUAL(result[1], "world");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
// " root world".rsplit(" ", 0)
|
||||
result.clear();
|
||||
pystring::rsplit(" root world", result, " ", 0);
|
||||
PYSTRING_CHECK_EQUAL(result.size(), 1);
|
||||
if(result.size()==1)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(result[0], " root world");
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// " root world".rsplit(" ", 1)
|
||||
result.clear();
|
||||
pystring::rsplit(" root world", result, " ", 1);
|
||||
PYSTRING_CHECK_EQUAL(result.size(), 2);
|
||||
if(result.size()==2)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(result[0], " root");
|
||||
PYSTRING_CHECK_EQUAL(result[1], "world");
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// " root world".rsplit(" ", 2)
|
||||
result.clear();
|
||||
pystring::rsplit(" root world", result, " ", 2);
|
||||
PYSTRING_CHECK_EQUAL(result.size(), 3);
|
||||
if(result.size()==3)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(result[0], "");
|
||||
PYSTRING_CHECK_EQUAL(result[1], "root");
|
||||
PYSTRING_CHECK_EQUAL(result[2], "world");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
PYSTRING_ADD_TEST(pystring, startswith)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(pystring::startswith("", ""), true);
|
||||
PYSTRING_CHECK_EQUAL(pystring::startswith("", "a"), false);
|
||||
PYSTRING_CHECK_EQUAL(pystring::startswith("a", ""), true);
|
||||
PYSTRING_CHECK_EQUAL(pystring::startswith("abc", "ab"), true);
|
||||
PYSTRING_CHECK_EQUAL(pystring::startswith("abc", "abc"), true);
|
||||
PYSTRING_CHECK_EQUAL(pystring::startswith("abc", "abcd"), false);
|
||||
PYSTRING_CHECK_EQUAL(pystring::startswith("abcdef", "abc"), true);
|
||||
PYSTRING_CHECK_EQUAL(pystring::startswith("abcdef", "abc", 1), false);
|
||||
PYSTRING_CHECK_EQUAL(pystring::startswith("abcdef", "bc", 1), true);
|
||||
}
|
||||
|
||||
PYSTRING_ADD_TEST(pystring, strip)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(pystring::strip(""), "");
|
||||
PYSTRING_CHECK_EQUAL(pystring::strip("a"), "a");
|
||||
PYSTRING_CHECK_EQUAL(pystring::strip("a "), "a");
|
||||
PYSTRING_CHECK_EQUAL(pystring::strip(" a"), "a");
|
||||
PYSTRING_CHECK_EQUAL(pystring::strip("\n a "), "a");
|
||||
PYSTRING_CHECK_EQUAL(pystring::strip("\r\n a \r\n"), "a");
|
||||
PYSTRING_CHECK_EQUAL(pystring::strip("\r\n a \r\n\t"), "a");
|
||||
}
|
||||
|
||||
PYSTRING_ADD_TEST(pystring, translate)
|
||||
{
|
||||
char t1data[256];
|
||||
for(int i=0; i<256; ++i) t1data[i] = (char)i;
|
||||
std::string t1(t1data, 256);
|
||||
PYSTRING_CHECK_EQUAL(pystring::translate("", t1), "");
|
||||
PYSTRING_CHECK_EQUAL(pystring::translate("cheese", t1), "cheese");
|
||||
PYSTRING_CHECK_EQUAL(pystring::translate("cheese", t1, "e"), "chs");
|
||||
|
||||
char t2data[256];
|
||||
for(int i=0; i<256; ++i) t2data[i] = (char)i;
|
||||
t2data[101] = 111; // Map e -> o
|
||||
std::string t2(t2data, 256);
|
||||
PYSTRING_CHECK_EQUAL(pystring::translate("", t2), "");
|
||||
PYSTRING_CHECK_EQUAL(pystring::translate("cheese", t2), "chooso");
|
||||
}
|
||||
|
||||
|
||||
PYSTRING_ADD_TEST(pystring, abspath)
|
||||
{
|
||||
PYSTRING_CHECK_EQUAL(pystring::os::path::abspath_posix("", "/net"), "/net");
|
||||
PYSTRING_CHECK_EQUAL(pystring::os::path::abspath_posix("../jeremys", "/net/soft_scratch/users/stevel"), "/net/soft_scratch/users/jeremys");
|
||||
PYSTRING_CHECK_EQUAL(pystring::os::path::abspath_posix("../../../../tmp/a", "/net/soft_scratch/users/stevel"), "/tmp/a");
|
||||
|
||||
PYSTRING_CHECK_EQUAL(pystring::os::path::abspath_nt("", "c:\\net"), "c:\\net");
|
||||
PYSTRING_CHECK_EQUAL(pystring::os::path::abspath_nt("..\\jeremys", "c:\\net\\soft_scratch\\users\\stevel"), "c:\\net\\soft_scratch\\users\\jeremys");
|
||||
PYSTRING_CHECK_EQUAL(pystring::os::path::abspath_nt("..\\..\\..\\..\\tmp\\a", "c:\\net\\soft_scratch\\users\\stevel"), "c:\\tmp\\a");
|
||||
}
|
||||
|
||||
PYSTRING_ADD_TEST(pystring_os_path, splitdrive)
|
||||
{
|
||||
using namespace pystring::os::path;
|
||||
|
||||
std::string drivespec, pathspec;
|
||||
splitdrive_posix(drivespec, pathspec, "/Users/test"); PYSTRING_CHECK_EQUAL(drivespec, ""); PYSTRING_CHECK_EQUAL(pathspec, "/Users/test");
|
||||
splitdrive_nt(drivespec, pathspec, "C:\\Users\\test"); PYSTRING_CHECK_EQUAL(drivespec, "C:" ); PYSTRING_CHECK_EQUAL(pathspec, "\\Users\\test" );
|
||||
splitdrive_nt(drivespec, pathspec, "\\Users\\test"); PYSTRING_CHECK_EQUAL(drivespec, "" ); PYSTRING_CHECK_EQUAL(pathspec, "\\Users\\test" );
|
||||
}
|
||||
|
||||
PYSTRING_ADD_TEST(pystring_os_path, isabs)
|
||||
{
|
||||
using namespace pystring::os::path;
|
||||
|
||||
PYSTRING_CHECK_EQUAL(isabs_posix("/Users/test"), true );
|
||||
PYSTRING_CHECK_EQUAL(isabs_posix("\\Users\\test"), false);
|
||||
PYSTRING_CHECK_EQUAL(isabs_posix("../Users"), false);
|
||||
PYSTRING_CHECK_EQUAL(isabs_posix("Users"), false);
|
||||
|
||||
PYSTRING_CHECK_EQUAL(isabs_nt("C:\\Users\\test"), true);
|
||||
PYSTRING_CHECK_EQUAL(isabs_nt("C:/Users"), true);
|
||||
PYSTRING_CHECK_EQUAL(isabs_nt("/Users"), true);
|
||||
PYSTRING_CHECK_EQUAL(isabs_nt("../Users"), false);
|
||||
PYSTRING_CHECK_EQUAL(isabs_nt("..\\Users"), false);
|
||||
}
|
||||
|
||||
PYSTRING_ADD_TEST(pystring_os_path, join)
|
||||
{
|
||||
using namespace pystring::os::path;
|
||||
|
||||
PYSTRING_CHECK_EQUAL(join_posix("a","b"), "a/b" );
|
||||
PYSTRING_CHECK_EQUAL(join_posix("/a","b"), "/a/b" );
|
||||
PYSTRING_CHECK_EQUAL(join_posix("/a","/b"), "/b" );
|
||||
PYSTRING_CHECK_EQUAL(join_posix("a","/b"), "/b" );
|
||||
PYSTRING_CHECK_EQUAL(join_posix("//a","b"), "//a/b" );
|
||||
PYSTRING_CHECK_EQUAL(join_posix("//a","b//"), "//a/b//" );
|
||||
PYSTRING_CHECK_EQUAL(join_posix("../a","/b"), "/b" );
|
||||
PYSTRING_CHECK_EQUAL(join_posix("../a","b"), "../a/b" );
|
||||
|
||||
std::vector< std::string > paths;
|
||||
PYSTRING_CHECK_EQUAL(join_posix(paths), "" );
|
||||
paths.push_back("/a");
|
||||
PYSTRING_CHECK_EQUAL(join_posix(paths), "/a" );
|
||||
paths.push_back("b");
|
||||
PYSTRING_CHECK_EQUAL(join_posix(paths), "/a/b" );
|
||||
paths.push_back("c/");
|
||||
PYSTRING_CHECK_EQUAL(join_posix(paths), "/a/b/c/" );
|
||||
paths.push_back("d");
|
||||
PYSTRING_CHECK_EQUAL(join_posix(paths), "/a/b/c/d" );
|
||||
paths.push_back("/e");
|
||||
PYSTRING_CHECK_EQUAL(join_posix(paths), "/e" );
|
||||
|
||||
PYSTRING_CHECK_EQUAL(join_nt("c:","/a"), "c:/a" );
|
||||
PYSTRING_CHECK_EQUAL(join_nt("c:/","/a"), "c:/a" );
|
||||
PYSTRING_CHECK_EQUAL(join_nt("c:/a","/b"), "/b" );
|
||||
PYSTRING_CHECK_EQUAL(join_nt("c:","d:/"), "d:/" );
|
||||
PYSTRING_CHECK_EQUAL(join_nt("c:/","d:/"), "d:/" );
|
||||
PYSTRING_CHECK_EQUAL(join_nt("a","b"), "a\\b" );
|
||||
PYSTRING_CHECK_EQUAL(join_nt("\\a","b"), "\\a\\b" );
|
||||
PYSTRING_CHECK_EQUAL(join_nt("c:\\a","b"), "c:\\a\\b" );
|
||||
PYSTRING_CHECK_EQUAL(join_nt("c:\\a","c:\\b"), "c:\\b" );
|
||||
PYSTRING_CHECK_EQUAL(join_nt("..\\a","b"), "..\\a\\b" );
|
||||
}
|
||||
|
||||
PYSTRING_ADD_TEST(pystring_os_path, normpath)
|
||||
{
|
||||
using namespace pystring::os::path;
|
||||
|
||||
PYSTRING_CHECK_EQUAL(normpath_posix("A//B"), "A/B" );
|
||||
PYSTRING_CHECK_EQUAL(normpath_posix("A/./B"), "A/B" );
|
||||
PYSTRING_CHECK_EQUAL(normpath_posix("A/foo/../B"), "A/B" );
|
||||
PYSTRING_CHECK_EQUAL(normpath_posix("/A//B"), "/A/B" );
|
||||
PYSTRING_CHECK_EQUAL(normpath_posix("//A//B"), "//A/B" );
|
||||
PYSTRING_CHECK_EQUAL(normpath_posix("///A//B"), "/A/B" );
|
||||
PYSTRING_CHECK_EQUAL(normpath_posix("../A"), "../A" );
|
||||
PYSTRING_CHECK_EQUAL(normpath_posix("../A../"), "../A.." );
|
||||
PYSTRING_CHECK_EQUAL(normpath_posix("FOO/../A../././B"), "A../B" );
|
||||
|
||||
PYSTRING_CHECK_EQUAL(normpath_nt(""), "." );
|
||||
PYSTRING_CHECK_EQUAL(normpath_nt("A"), "A" );
|
||||
PYSTRING_CHECK_EQUAL(normpath_nt("A./B"), "A.\\B" );
|
||||
PYSTRING_CHECK_EQUAL(normpath_nt("C:\\"), "C:\\" );
|
||||
PYSTRING_CHECK_EQUAL(normpath_nt("C:\\A"), "C:\\A" );
|
||||
PYSTRING_CHECK_EQUAL(normpath_nt("C:/A"), "C:\\A" );
|
||||
PYSTRING_CHECK_EQUAL(normpath_nt("C:/A..\\"), "C:\\A.." );
|
||||
PYSTRING_CHECK_EQUAL(normpath_nt("C:/A..\\..\\"), "C:\\" );
|
||||
PYSTRING_CHECK_EQUAL(normpath_nt("C:\\\\A"), "C:\\A" );
|
||||
PYSTRING_CHECK_EQUAL(normpath_nt("C:\\\\\\A\\\\B"), "C:\\A\\B" );
|
||||
}
|
||||
|
||||
PYSTRING_ADD_TEST(pystring_os_path, split)
|
||||
{
|
||||
using namespace pystring::os::path;
|
||||
|
||||
std::string head, tail;
|
||||
split_posix(head, tail, ""); PYSTRING_CHECK_EQUAL(head, "" ); PYSTRING_CHECK_EQUAL(tail, "" );
|
||||
split_posix(head, tail, "/"); PYSTRING_CHECK_EQUAL(head, "/" ); PYSTRING_CHECK_EQUAL(tail, "" );
|
||||
split_posix(head, tail, "a"); PYSTRING_CHECK_EQUAL(head, "" ); PYSTRING_CHECK_EQUAL(tail, "a" );
|
||||
split_posix(head, tail, "a/"); PYSTRING_CHECK_EQUAL(head, "a" ); PYSTRING_CHECK_EQUAL(tail, "" );
|
||||
split_posix(head, tail, "/a"); PYSTRING_CHECK_EQUAL(head, "/" ); PYSTRING_CHECK_EQUAL(tail, "a" );
|
||||
split_posix(head, tail, "/a/b/"); PYSTRING_CHECK_EQUAL(head, "/a/b" ); PYSTRING_CHECK_EQUAL(tail, "" );
|
||||
split_posix(head, tail, "/a/b"); PYSTRING_CHECK_EQUAL(head, "/a" ); PYSTRING_CHECK_EQUAL(tail, "b" );
|
||||
split_posix(head, tail, "/a/b//"); PYSTRING_CHECK_EQUAL(head, "/a/b" ); PYSTRING_CHECK_EQUAL(tail, "" );
|
||||
split_posix(head, tail, "/a/b/////////////"); PYSTRING_CHECK_EQUAL(head, "/a/b" ); PYSTRING_CHECK_EQUAL(tail, "" );
|
||||
|
||||
|
||||
split_nt(head, tail, ""); PYSTRING_CHECK_EQUAL(head, "" ); PYSTRING_CHECK_EQUAL(tail, "" );
|
||||
split_nt(head, tail, "\\"); PYSTRING_CHECK_EQUAL(head, "\\" ); PYSTRING_CHECK_EQUAL(tail, "" );
|
||||
split_nt(head, tail, "a"); PYSTRING_CHECK_EQUAL(head, "" ); PYSTRING_CHECK_EQUAL(tail, "a" );
|
||||
split_nt(head, tail, "a\\"); PYSTRING_CHECK_EQUAL(head, "a" ); PYSTRING_CHECK_EQUAL(tail, "" );
|
||||
split_nt(head, tail, "c:\\a"); PYSTRING_CHECK_EQUAL(head, "c:\\" ); PYSTRING_CHECK_EQUAL(tail, "a" );
|
||||
split_nt(head, tail, "c:\\a\\b"); PYSTRING_CHECK_EQUAL(head, "c:\\a" ); PYSTRING_CHECK_EQUAL(tail, "b" );
|
||||
split_nt(head, tail, "c:\\a\\b\\"); PYSTRING_CHECK_EQUAL(head, "c:\\a\\b" ); PYSTRING_CHECK_EQUAL(tail, "" );
|
||||
split_nt(head, tail, "D:\\dir\\\\"); PYSTRING_CHECK_EQUAL(head, "D:\\dir" ); PYSTRING_CHECK_EQUAL(tail, "" );
|
||||
|
||||
}
|
||||
|
||||
PYSTRING_ADD_TEST(pystring_os_path, splitext)
|
||||
{
|
||||
using namespace pystring::os::path;
|
||||
|
||||
std::string root, ext;
|
||||
splitext_nt(root, ext, ""); PYSTRING_CHECK_EQUAL(root, ""); PYSTRING_CHECK_EQUAL(ext, "");
|
||||
splitext_nt(root, ext, "."); PYSTRING_CHECK_EQUAL(root, "."); PYSTRING_CHECK_EQUAL(ext, "");
|
||||
splitext_nt(root, ext, ".foo"); PYSTRING_CHECK_EQUAL(root, ".foo"); PYSTRING_CHECK_EQUAL(ext, "");
|
||||
splitext_nt(root, ext, ".foo."); PYSTRING_CHECK_EQUAL(root, ".foo"); PYSTRING_CHECK_EQUAL(ext, ".");
|
||||
splitext_nt(root, ext, ".foo.e"); PYSTRING_CHECK_EQUAL(root, ".foo"); PYSTRING_CHECK_EQUAL(ext, ".e");
|
||||
splitext_nt(root, ext, "c"); PYSTRING_CHECK_EQUAL(root, "c"); PYSTRING_CHECK_EQUAL(ext, "");
|
||||
splitext_nt(root, ext, "a_b.c"); PYSTRING_CHECK_EQUAL(root, "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");
|
||||
splitext_nt(root, ext, "c:\\a_b.c"); PYSTRING_CHECK_EQUAL(root, "c:\\a_b"); PYSTRING_CHECK_EQUAL(ext, ".c");
|
||||
}
|
||||
+125
@@ -0,0 +1,125 @@
|
||||
// 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
|
||||
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
#include <vector>
|
||||
|
||||
extern int unit_test_failures;
|
||||
|
||||
void unittest_fail();
|
||||
|
||||
typedef void (*PYSTRINGTestFunc)();
|
||||
|
||||
struct PYSTRINGTest
|
||||
{
|
||||
PYSTRINGTest(std::string testgroup, std::string testname, PYSTRINGTestFunc test) :
|
||||
group(testgroup), name(testname), function(test) { };
|
||||
std::string group, name;
|
||||
PYSTRINGTestFunc function;
|
||||
};
|
||||
|
||||
typedef std::vector<PYSTRINGTest*> UnitTests;
|
||||
|
||||
UnitTests& GetUnitTests();
|
||||
|
||||
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
|
||||
/// error occurred, but does NOT abort. This is helpful for unit tests
|
||||
/// where we do not want one failure.
|
||||
#define PYSTRING_CHECK_ASSERT(x) \
|
||||
((x) ? ((void)0) \
|
||||
: ((std::cout << __FILE__ << ":" << __LINE__ << ":\n" \
|
||||
<< "FAILED: " << #x << "\n"), \
|
||||
(void)++unit_test_failures))
|
||||
|
||||
#define PYSTRING_CHECK_EQUAL(x,y) \
|
||||
(((x) == (y)) ? ((void)0) \
|
||||
: ((std::cout << __FILE__ << ":" << __LINE__ << ":\n" \
|
||||
<< "FAILED: " << #x << " == " << #y << "\n" \
|
||||
<< "\tvalues were '" << (x) << "' and '" << (y) << "'\n"), \
|
||||
(void)++unit_test_failures))
|
||||
|
||||
#define PYSTRING_CHECK_NE(x,y) \
|
||||
(((x) != (y)) ? ((void)0) \
|
||||
: ((std::cout << __FILE__ << ":" << __LINE__ << ":\n" \
|
||||
<< "FAILED: " << #x << " != " << #y << "\n" \
|
||||
<< "\tvalues were '" << (x) << "' and '" << (y) << "'\n"), \
|
||||
(void)++unit_test_failures))
|
||||
|
||||
#define PYSTRING_CHECK_LT(x,y) \
|
||||
(((x) < (y)) ? ((void)0) \
|
||||
: ((std::cout << __FILE__ << ":" << __LINE__ << ":\n" \
|
||||
<< "FAILED: " << #x << " < " << #y << "\n" \
|
||||
<< "\tvalues were '" << (x) << "' and '" << (y) << "'\n"), \
|
||||
(void)++unit_test_failures))
|
||||
|
||||
#define PYSTRING_CHECK_GT(x,y) \
|
||||
(((x) > (y)) ? ((void)0) \
|
||||
: ((std::cout << __FILE__ << ":" << __LINE__ << ":\n" \
|
||||
<< "FAILED: " << #x << " > " << #y << "\n" \
|
||||
<< "\tvalues were '" << (x) << "' and '" << (y) << "'\n"), \
|
||||
(void)++unit_test_failures))
|
||||
|
||||
#define PYSTRING_CHECK_LE(x,y) \
|
||||
(((x) <= (y)) ? ((void)0) \
|
||||
: ((std::cout << __FILE__ << ":" << __LINE__ << ":\n" \
|
||||
<< "FAILED: " << #x << " <= " << #y << "\n" \
|
||||
<< "\tvalues were '" << (x) << "' and '" << (y) << "'\n"), \
|
||||
(void)++unit_test_failures))
|
||||
|
||||
#define PYSTRING_CHECK_GE(x,y) \
|
||||
(((x) >= (y)) ? ((void)0) \
|
||||
: ((std::cout << __FILE__ << ":" << __LINE__ << ":\n" \
|
||||
<< "FAILED: " << #x << " >= " << #y << "\n" \
|
||||
<< "\tvalues were '" << (x) << "' and '" << (y) << "'\n"), \
|
||||
(void)++unit_test_failures))
|
||||
|
||||
#define PYSTRING_CHECK_CLOSE(x,y,tol) \
|
||||
((std::abs((x) - (y)) < tol) ? ((void)0) \
|
||||
: ((std::cout << __FILE__ << ":" << __LINE__ << ":\n" \
|
||||
<< "FAILED: abs(" << #x << " - " << #y << ") < " << #tol << "\n" \
|
||||
<< "\tvalues were '" << (x) << "', '" << (y) << "' and '" << (tol) << "'\n"), \
|
||||
(void)++unit_test_failures))
|
||||
|
||||
#define PYSTRING_CHECK_THOW(S, E) \
|
||||
try { S; throw "throwanything"; } catch( E const& ex ) { } catch (...) { \
|
||||
std::cout << __FILE__ << ":" << __LINE__ << ":\n" \
|
||||
<< "FAILED: " << #E << " is expected to be thrown\n"; \
|
||||
++unit_test_failures; }
|
||||
|
||||
#define PYSTRING_CHECK_NO_THOW(S) \
|
||||
try { S; } catch (...) { \
|
||||
std::cout << __FILE__ << ":" << __LINE__ << ":\n" \
|
||||
<< "FAILED: exception thrown from " << #S <<"\n"; \
|
||||
++unit_test_failures; }
|
||||
|
||||
#define PYSTRING_ADD_TEST(group, name) \
|
||||
static void pystringtest_##group##_##name(); \
|
||||
AddTest pystringaddtest_##group##_##name(new 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; \
|
||||
return pystring_unit_tests; } \
|
||||
AddTest::AddTest(PYSTRINGTest* test){GetUnitTests().push_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 << "] - "; \
|
||||
std::cerr << (_tmp == unit_test_failures ? "PASSED" : "FAILED") << "\n"; } \
|
||||
std::cerr << "\n" << unit_test_failures << " tests failed\n\n"; \
|
||||
return unit_test_failures; }
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user