1 Commits
Author SHA1 Message Date
Larry Gritz 9164452a01 Revise license formatting to match other modern projects.
No change to the fact that this project is BSD-3-clause licensed.

But this slight rewording/reformatting:

* Brings the notices in line with the exact wording we use in other
  projects such as OSL.

* Now will be correctly recognized by GitHub and other automated
  license checkers as being EXACTLY the same as the canonical BSD
  3-clause license.

This was approved by SPI legal.
2022-06-08 12:07:16 -07:00
13 changed files with 1720 additions and 3035 deletions
-225
View File
@@ -1,225 +0,0 @@
# 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
-145
View File
@@ -1,145 +0,0 @@
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
View File
@@ -1,103 +0,0 @@
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)
+5 -8
View File
@@ -1,9 +1,7 @@
LIBTOOL ?= libtool
PREFIX ?= /usr
INCLUDEDIR ?= ${PREFIX}/include/pystring
LIBDIR ?= ${PREFIX}/lib
CXX ?= g++
CXXFLAGS ?= -g -O3 -Wall -Wextra -Wshadow -Wconversion -Wcast-qual -Wformat=2
LIBTOOL = libtool
LIBDIR = /usr/lib
CXX = g++
CXXFLAGS = -g -O3 -Wall -Wextra -Wshadow -Wconversion -Wcast-qual -Wformat=2
all: libpystring.la
@@ -14,8 +12,7 @@ libpystring.la: pystring.lo
$(LIBTOOL) --mode=link --tag=CXX $(CXX) -o $@ $< -rpath $(LIBDIR)
install: libpystring.la
$(LIBTOOL) --mode=install install -Dm755 $< $(DESTDIR)$(LIBDIR)/$<
$(LIBTOOL) --mode=install install -Dm644 pystring.h $(DESTDIR)$(INCLUDEDIR)/pystring.h
$(LIBTOOL) --mode=install install -c $< $(LIBDIR)/$<
clean:
$(RM) -fr pystring.lo pystring.o libpystring.la .libs
-2
View File
@@ -1,5 +1,3 @@
[![Repology](https://img.shields.io/repology/repositories/pystring)](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
-8
View File
@@ -1,8 +0,0 @@
@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
View File
@@ -1,75 +0,0 @@
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,
)
+1640 -4
View File
File diff suppressed because it is too large Load Diff
+67 -119
View File
@@ -6,12 +6,6 @@
#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>
@@ -38,102 +32,102 @@ namespace pystring
//////////////////////////////////////////////////////////////////////////////////////////////
/// @brief Return a copy of the string with only its first character capitalized.
///
PYSTRING_INLINE std::string capitalize( const std::string & str );
std::string capitalize( const std::string & str );
//////////////////////////////////////////////////////////////////////////////////////////////
/// @brief Return centered in a string of length width. Padding is done using spaces.
///
PYSTRING_INLINE std::string center( const std::string & str, int width );
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.
///
PYSTRING_INLINE int count( const std::string & str, const std::string & substr, int start = 0, int end = MAX_32BIT_INT);
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.
///
PYSTRING_INLINE bool endswith( const std::string & str, const std::string & suffix, int start = 0, int end = MAX_32BIT_INT );
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.
///
PYSTRING_INLINE std::string expandtabs( const std::string & str, int tabsize = 8);
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.
///
PYSTRING_INLINE int find( const std::string & str, const std::string & sub, int start = 0, int end = MAX_32BIT_INT );
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
///
PYSTRING_INLINE int index( const std::string & str, const std::string & sub, int start = 0, int end = MAX_32BIT_INT );
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.
///
PYSTRING_INLINE bool isalnum( const std::string & str );
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
///
PYSTRING_INLINE bool isalpha( const std::string & str );
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.
///
PYSTRING_INLINE bool isdigit( const std::string & str );
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.
///
PYSTRING_INLINE bool islower( const std::string & str );
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.
///
PYSTRING_INLINE bool isspace( const std::string & str );
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.
///
PYSTRING_INLINE bool istitle( const std::string & str );
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.
///
PYSTRING_INLINE bool isupper( const std::string & str );
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
///
PYSTRING_INLINE std::string join( const std::string & str, const std::vector< std::string > & seq );
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().
///
PYSTRING_INLINE std::string ljust( const std::string & str, int width );
std::string ljust( const std::string & str, int width );
//////////////////////////////////////////////////////////////////////////////////////////////
/// @brief Return a copy of the string converted to lowercase.
///
PYSTRING_INLINE std::string lower( const std::string & str );
std::string lower( const std::string & str );
//////////////////////////////////////////////////////////////////////////////////////////////
/// @brief Return a copy of the string with leading characters removed. If chars is omitted or None,
@@ -141,13 +135,13 @@ namespace pystring
/// characters in the string will be stripped from the beginning of the string this method
/// is called on (argument "str" ).
///
PYSTRING_INLINE std::string lstrip( const std::string & str, const std::string & chars = "" );
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.
///
PYSTRING_INLINE std::string mul( const std::string & str, int n);
std::string mul( const std::string & str, int n);
//////////////////////////////////////////////////////////////////////////////////////////////
/// @brief Split the string around first occurance of sep.
@@ -155,50 +149,32 @@ 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.
///
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 );
void partition( const std::string & str, const std::string & sep, std::vector< std::string > & result );
//////////////////////////////////////////////////////////////////////////////////////////////
/// @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.
///
PYSTRING_INLINE std::string replace( const std::string & str, const std::string & oldstr, const std::string & newstr, int count = -1);
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.
///
PYSTRING_INLINE int rfind( const std::string & str, const std::string & sub, int start = 0, int end = MAX_32BIT_INT );
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
///
PYSTRING_INLINE int rindex( const std::string & str, const std::string & sub, int start = 0, int end = MAX_32BIT_INT );
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().
///
PYSTRING_INLINE std::string rjust( const std::string & str, int width);
std::string rjust( const std::string & str, int width);
//////////////////////////////////////////////////////////////////////////////////////////////
/// @brief Split the string around last occurance of sep.
@@ -206,33 +182,21 @@ 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.
///
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;
}
void rpartition( const std::string & str, const std::string & sep, std::vector< std::string > & 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.
///
PYSTRING_INLINE std::string rstrip( const std::string & str, const std::string & chars = "" );
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.
///
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;
}
void split( const std::string & str, std::vector< std::string > & result, const std::string & sep = "", int maxsplit = -1);
//////////////////////////////////////////////////////////////////////////////////////////////
/// @brief Fills the "result" list with the words in the string, using sep as the delimiter string.
@@ -241,73 +205,61 @@ namespace pystring
/// If maxsplit is > -1, at most maxsplit splits are done. If sep is "",
/// any whitespace string is a separator.
///
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;
}
void rsplit( const std::string & str, std::vector< std::string > & result, const std::string & sep = "", int maxsplit = -1);
//////////////////////////////////////////////////////////////////////////////////////////////
/// @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.
///
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;
}
void splitlines( const std::string & str, std::vector< std::string > & result, bool keepends = false );
//////////////////////////////////////////////////////////////////////////////////////////////
/// @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
///
PYSTRING_INLINE bool startswith( const std::string & str, const std::string & prefix, int start = 0, int end = MAX_32BIT_INT );
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.
///
PYSTRING_INLINE std::string strip( const std::string & str, const std::string & chars = "" );
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.
///
PYSTRING_INLINE std::string swapcase( const std::string & str );
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.
///
PYSTRING_INLINE std::string title( const std::string & str );
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.
///
PYSTRING_INLINE std::string translate( const std::string & str, const std::string & table, const std::string & deletechars = "");
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.
///
PYSTRING_INLINE std::string upper( const std::string & str );
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().
///
PYSTRING_INLINE std::string zfill( const std::string & str, int width );
std::string zfill( const std::string & str, int width );
//////////////////////////////////////////////////////////////////////////////////////////////
/// @brief function matching python's slice functionality.
///
PYSTRING_INLINE std::string slice( const std::string & str, int start = 0, int end = MAX_32BIT_INT);
std::string slice( const std::string & str, int start = 0, int end = MAX_32BIT_INT);
///
/// @ }
@@ -345,26 +297,26 @@ namespace path
/// program; where basename for '/foo/bar/' returns 'bar', the basename() function returns an
/// empty string ('').
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);
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).
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);
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.
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);
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.
@@ -372,9 +324,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.
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);
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);
//////////////////////////////////////////////////////////////////////////////////////////////
@@ -387,13 +339,13 @@ namespace path
/// current directory on drive C: (c:foo), not c:\foo.
/// This dispatches based on the compilation OS
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::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::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);
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
@@ -402,9 +354,9 @@ namespace path
/// It should be understood that this may change the meaning of the path if it contains
/// symbolic links!
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);
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
@@ -415,9 +367,9 @@ namespace path
/// join(head, tail) returns a path to the same location as path (but the strings may
/// differ).
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);
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
@@ -425,18 +377,18 @@ namespace path
/// drive will always be the empty string. In all cases, drive + tail will be the same as
/// 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);
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', '').
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);
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);
///
/// @ }
@@ -446,8 +398,4 @@ namespace path
} // namespace pystring
#if PYSTRING_HEADER_ONLY
#include "pystring_impl.h"
#endif
#endif
-1693
View File
File diff suppressed because it is too large Load Diff
-640
View File
@@ -7,25 +7,6 @@
#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)
@@ -52,17 +33,6 @@ 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);
@@ -128,18 +98,6 @@ 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");
@@ -700,601 +658,3 @@ 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);
}
}
-5
View File
@@ -1,5 +0,0 @@
// 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; }
+8 -8
View File
@@ -23,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
@@ -102,22 +102,22 @@ struct AddTest { AddTest(PYSTRINGTest&& test); };
#define PYSTRING_ADD_TEST(group, name) \
static void pystringtest_##group##_##name(); \
AddTest pystringaddtest_##group##_##name(PYSTRINGTest(#group, #name, 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; \
std::vector<PYSTRINGTest*>& GetUnitTests() { \
static std::vector<PYSTRINGTest*> pystring_unit_tests; \
return pystring_unit_tests; } \
AddTest::AddTest(PYSTRINGTest&& test){GetUnitTests().emplace_back(test);} \
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 << "] - "; \
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; }