├── .clang-format ├── .gitattributes ├── .gitignore ├── .travis.yml ├── CMakeLists.txt ├── Jenkinsfile ├── Makefile ├── README.mkdn ├── appveyor.yml ├── codecov.yml ├── constexpr_string.hpp ├── constexpr_string_test.cpp ├── string_view.hpp ├── string_view_test.cpp └── test_runner.py /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | BasedOnStyle: LLVM -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # Windows shortcuts 18 | *.lnk 19 | 20 | # ========================= 21 | # Operating System Files 22 | # ========================= 23 | 24 | # OSX 25 | # ========================= 26 | 27 | .DS_Store 28 | .AppleDouble 29 | .LSOverride 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear on external disk 35 | .Spotlight-V100 36 | .Trashes 37 | 38 | # Directories potentially created on remote AFP share 39 | .AppleDB 40 | .AppleDesktop 41 | Network Trash Folder 42 | Temporary Items 43 | .apdisk 44 | build*/ 45 | _build/ 46 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: cpp 3 | 4 | compiler: 5 | - clang 6 | - gcc 7 | before_install: 8 | - pip install --user 'requests[security]' 9 | - pip install --user cpp-coveralls 10 | install: 11 | - if [ "$CXX" = "g++" ]; then export COVERAGE=$COV; fi 12 | - if [ "$CXX" = "g++" ]; then export CXX="g++-4.8" CC="gcc-4.8"; fi 13 | addons: 14 | apt: 15 | sources: 16 | - ubuntu-toolchain-r-test 17 | packages: 18 | - gcc-4.8 19 | - g++-4.8 20 | - clang 21 | env: 22 | - BUILD_TYPE=Debug CXX_FLAGS=-std=c++03 COV=On 23 | - BUILD_TYPE=Debug CXX_FLAGS=-std=c++11 COV=On 24 | - BUILD_TYPE=Release CXX_FLAGS=-std=c++03 25 | - BUILD_TYPE=Release CXX_FLAGS=-std=c++11 26 | script: 27 | - cmake . -DCOVERAGE=${COVERAGE} -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DCMAKE_CXX_FLAGS=${CXX_FLAGS} && make && CTEST_OUTPUT_ON_FAILURE=1 make test 28 | 29 | after_success: | 30 | 31 | if [ "$CXX" = "g++-4.8" ]; then 32 | export GCOV="gcov-4.8" 33 | elif [ "$CXX" = "g++" ]; then 34 | export GCOV="gcov" 35 | fi 36 | if [ -n "$GCOV" ] && [ -n "$COVERAGE" ]; then 37 | coveralls --gcov ${GCOV} --gcov-options '\-lp' 38 | fi 39 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # CMakeLists files in this project can 2 | # refer to the root source directory of the project as ${HELLO_SOURCE_DIR} and 3 | # to the root binary directory of the project as ${HELLO_BINARY_DIR}. 4 | cmake_minimum_required (VERSION 2.8.7) 5 | project (string_view) 6 | 7 | add_executable(string_view_test string_view.hpp string_view_test.cpp) 8 | 9 | add_executable(constexpr_string_test constexpr_string.hpp constexpr_string_test.cpp) 10 | 11 | 12 | #check for address sanitizer support 13 | if(${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU") 14 | if (${CMAKE_CXX_COMPILER_VERSION} VERSION_GREATER 4.8) 15 | set(HAVE_FLAG_SANITIZE_ADDRESS TRUE) 16 | endif() 17 | elseif (${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang") 18 | if (${CMAKE_CXX_COMPILER_VERSION} VERSION_GREATER 3.2) 19 | set(HAVE_FLAG_SANITIZE_ADDRESS TRUE) 20 | endif() 21 | endif() 22 | if(CYGWIN OR WIN32) 23 | unset(HAVE_FLAG_SANITIZE_ADDRESS) 24 | endif() 25 | 26 | if(HAVE_FLAG_SANITIZE_ADDRESS AND NOT DISABLE_ADDRESS_SANITIZER) 27 | SET_TARGET_PROPERTIES(string_view_test PROPERTIES COMPILE_FLAGS "-fsanitize=address -fno-omit-frame-pointer") 28 | SET_TARGET_PROPERTIES(string_view_test PROPERTIES LINK_FLAGS "-fsanitize=address") 29 | endif(HAVE_FLAG_SANITIZE_ADDRESS AND NOT DISABLE_ADDRESS_SANITIZER) 30 | 31 | enable_testing() 32 | if(COVERAGE) 33 | SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0 -Wall -Woverloaded-virtual -Wwrite-strings -fprofile-arcs -ftest-coverage -coverage -fno-inline -fno-inline-small-functions -fno-default-inline") 34 | SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O0 -Wall -W -fprofile-arcs -ftest-coverage -coverage -fno-inline -fno-inline-small-functions -fno-default-inline") 35 | SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage -coverage -fno-inline -fno-inline-small-functions -fno-default-inline") 36 | endif(COVERAGE) 37 | add_test( 38 | NAME string_view_test 39 | COMMAND $) 40 | add_test( 41 | NAME constexpr_string_test 42 | COMMAND $) 43 | -------------------------------------------------------------------------------- /Jenkinsfile: -------------------------------------------------------------------------------- 1 | node('linux') { 2 | stage 'Build and Test' 3 | checkout scm 4 | sh 'python test_runner.py' 5 | } 6 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | prefix=/usr/local 2 | includedir=$(prefix)/include 3 | 4 | check: test 5 | 6 | test_03: string_view.hpp string_view_test.cpp 7 | $(CXX) -std=c++03 -Wall string_view_test.cpp -o $@ 8 | ./$@ 9 | 10 | test_11: string_view.hpp string_view_test.cpp 11 | $(CXX) -std=c++11 -Wall string_view_test.cpp -o $@ 12 | ./$@ 13 | 14 | test_14: string_view.hpp string_view_test.cpp 15 | $(CXX) -std=c++14 -Wall string_view_test.cpp -o $@ 16 | ./$@ 17 | 18 | test: test_03 test_11 test_14 19 | 20 | clean: 21 | rm -f test_03 22 | rm -f test_11 23 | rm -f test_14 24 | 25 | 26 | .PHONY: test check clean 27 | -------------------------------------------------------------------------------- /README.mkdn: -------------------------------------------------------------------------------- 1 | # string_view for C++03 C++11 C++14 2 | 3 | Licensed under Boost license 4 | 5 | [![Build Status](https://travis-ci.org/satoren/string_view.svg?branch=master)](https://travis-ci.org/satoren/string_view.svg) 6 | [![Coverage Status](https://coveralls.io/repos/github/satoren/string_view/badge.svg?branch=master)](https://coveralls.io/github/satoren/string_view?branch=master) 7 | 8 | ## Introduction 9 | http://en.cppreference.com/w/cpp/experimental/basic_string_view 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | version: 1.0.{build} 2 | configuration: 3 | - Debug 4 | - Release 5 | environment: 6 | matrix: 7 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 8 | CMAKE_GEN_TYPE: '"Visual Studio 9 2008"' 9 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 10 | CMAKE_GEN_TYPE: '"Visual Studio 10 2010"' 11 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 12 | CMAKE_GEN_TYPE: '"Visual Studio 11 2012"' 13 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 14 | CMAKE_GEN_TYPE: '"Visual Studio 12 2013"' 15 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 16 | CMAKE_GEN_TYPE: '"Visual Studio 14 2015"' 17 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 18 | CMAKE_GEN_TYPE: '"Visual Studio 14 2015 Win64"' 19 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 20 | CMAKE_GEN_TYPE: '"Visual Studio 15 2017"' 21 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 22 | CMAKE_GEN_TYPE: '"Visual Studio 15 2017 Win64"' 23 | build_script: 24 | - ps: >- 25 | if(!(Test-Path -Path build )){ 26 | mkdir build 27 | } 28 | 29 | cd build 30 | 31 | cmake ../ -G $env:CMAKE_GEN_TYPE 32 | 33 | cmake --build . --config $env:CONFIGURATION 34 | test_script: 35 | - ps: ctest -C $env:CONFIGURATION --output-on-failure 36 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | comment: 2 | layout: header, changes, diff 3 | coverage: 4 | ignore: 5 | - string_view_test.cpp 6 | status: 7 | patch: false 8 | -------------------------------------------------------------------------------- /constexpr_string.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /* 3 | Boost Software License - Version 1.0 - August 17th, 2003 4 | 5 | Permission is hereby granted, free of charge, to any person or organization 6 | obtaining a copy of the software and accompanying documentation covered by 7 | this license (the "Software") to use, reproduce, display, distribute, 8 | execute, and transmit the Software, and to prepare derivative works of the 9 | Software, and to permit third-parties to whom the Software is furnished to 10 | do so, all subject to the following: 11 | 12 | The copyright notices in the Software and this entire statement, including 13 | the above license grant, this restriction and the following disclaimer, 14 | must be included in all copies of the Software, in whole or in part, and 15 | all derivative works of the Software, unless such copies or derivative 16 | works are solely in the form of machine-executable object code generated by 17 | a source language processor. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 22 | FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 23 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 24 | DEALINGS IN THE SOFTWARE. 25 | */ 26 | 27 | #include 28 | #include 29 | 30 | #if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900) 31 | namespace compiletime { 32 | template struct basic_constexpr_string { 33 | typedef CharT value_type; 34 | typedef CharT *pointer; 35 | typedef const CharT *const_pointer; 36 | typedef CharT &reference; 37 | typedef const CharT &const_reference; 38 | typedef std::size_t size_type; 39 | 40 | constexpr const_pointer c_str() const { return buffer; } 41 | std::basic_string to_string() const { 42 | return std::basic_string(buffer); 43 | } 44 | 45 | constexpr CharT operator[](size_type pos) const { return buffer[pos]; } 46 | 47 | constexpr int compare(const basic_constexpr_string &v) const; 48 | 49 | constexpr bool operator==(const basic_constexpr_string &rhs) const { 50 | return compare(rhs) == 0; 51 | } 52 | constexpr bool operator!=(const basic_constexpr_string &rhs) const { 53 | return compare(rhs) != 0; 54 | } 55 | constexpr bool operator<(const basic_constexpr_string &rhs) const { 56 | return compare(rhs) < 0; 57 | } 58 | constexpr bool operator>(const basic_constexpr_string &rhs) const { 59 | return rhs < *this; 60 | } 61 | constexpr bool operator<=(const basic_constexpr_string &rhs) const { 62 | return !(*this > rhs); 63 | } 64 | constexpr bool operator>=(const basic_constexpr_string &rhs) const { 65 | return !(*this < rhs); 66 | } 67 | 68 | constexpr size_type size() const { return N; } 69 | 70 | CharT buffer[N + 1]; 71 | }; 72 | 73 | #if __cplusplus >= 201402L || (defined(_MSC_VER) && _MSC_VER >= 1900) 74 | using std::index_sequence; 75 | using std::make_index_sequence; 76 | #else 77 | template struct index_sequence {}; 78 | 79 | template , 80 | bool flag = first >= last> 81 | struct make_index_sequence_t { 82 | using type = result; 83 | }; 84 | template 85 | struct make_index_sequence_t, false> 86 | : make_index_sequence_t> { 87 | }; 88 | template 89 | using make_index_sequence = typename make_index_sequence_t<0, N>::type; 90 | #endif 91 | 92 | namespace detail { 93 | template 94 | constexpr basic_constexpr_string 95 | build_string(const CharT *str, index_sequence) { 96 | return basic_constexpr_string{str[Indices]...}; 97 | } 98 | template 100 | constexpr basic_constexpr_string 102 | concat(const CharT (&str1)[N1], index_sequence, 103 | const CharT (&str2)[N2], index_sequence) { 104 | return basic_constexpr_string{ 106 | str1[Indices1]..., str2[Indices2]...}; 107 | } 108 | template 109 | constexpr int compare(const CharT (&str1)[N1], const CharT (&str2)[N2], 110 | std::size_t pos, std::size_t len) { 111 | return len == pos 112 | ? 0 113 | : str1[pos] != str2[pos] ? str1[pos] - str2[pos] 114 | : compare(str1, str2, pos + 1, len); 115 | } 116 | } // namespace detail 117 | 118 | template 119 | constexpr int basic_constexpr_string::compare( 120 | const basic_constexpr_string &n) const { 121 | return detail::compare(buffer, n.buffer, 0, N); 122 | } 123 | 124 | template 125 | constexpr basic_constexpr_string 126 | operator+(const basic_constexpr_string &cstr1, 127 | const basic_constexpr_string &cstr2) { 128 | return detail::concat(cstr1.buffer, make_index_sequence(), cstr2.buffer, 129 | make_index_sequence()); 130 | } 131 | template 132 | std::basic_string 133 | operator+(const std::basic_string &str, 134 | const basic_constexpr_string &cstr) { 135 | std::string ret; 136 | ret.reserve(str.size() + N); 137 | ret.append(str); 138 | ret.append(cstr.buffer); 139 | return ret; 140 | } 141 | template 142 | std::basic_string operator+(const basic_constexpr_string &cstr, 143 | const std::basic_string &str) { 144 | std::string ret; 145 | ret.reserve(str.size() + N); 146 | ret.append(cstr.buffer); 147 | ret.append(str); 148 | return ret; 149 | } 150 | 151 | template 152 | constexpr basic_constexpr_string 153 | to_constexpr_string(const CharT (&str)[N]) { 154 | return detail::build_string(str, make_index_sequence()); 155 | } 156 | 157 | template 158 | using constexpr_string = basic_constexpr_string; 159 | template 160 | using constexpr_wstring = basic_constexpr_string; 161 | 162 | #if defined(_HAS_CONSTEXPR) || __cplusplus >= 201103L || \ 163 | (defined(_MSC_VER) && _MSC_VER >= 1800) 164 | template 165 | using constexpr_u16string = basic_constexpr_string; 166 | template 167 | using constexpr_u32string = basic_constexpr_string; 168 | #endif 169 | } // namespace compiletime 170 | #else 171 | #error Needs at least a C++11 compiler 172 | #endif -------------------------------------------------------------------------------- /constexpr_string_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900) 6 | #include "constexpr_string.hpp" 7 | #endif 8 | 9 | int main() { 10 | #if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900) 11 | using namespace compiletime; 12 | 13 | constexpr auto test = to_constexpr_string("abc"); 14 | constexpr auto test2 = to_constexpr_string("def"); 15 | constexpr auto test3 = test + test2; 16 | 17 | std::string teststr("gh"); 18 | assert(test.to_string() == "abc"); 19 | assert(test3.to_string() == "abcdef"); 20 | assert((test3 + teststr) == "abcdefgh"); 21 | assert((teststr + test3) == "ghabcdef"); 22 | 23 | constexpr bool test_compare = (test == test); 24 | constexpr bool test_compare2 = (test == test2); 25 | static_assert(test_compare, ""); 26 | static_assert(!test_compare2, ""); 27 | #endif 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /string_view.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /* 3 | Boost Software License - Version 1.0 - August 17th, 2003 4 | 5 | Permission is hereby granted, free of charge, to any person or organization 6 | obtaining a copy of the software and accompanying documentation covered by 7 | this license (the "Software") to use, reproduce, display, distribute, 8 | execute, and transmit the Software, and to prepare derivative works of the 9 | Software, and to permit third-parties to whom the Software is furnished to 10 | do so, all subject to the following: 11 | 12 | The copyright notices in the Software and this entire statement, including 13 | the above license grant, this restriction and the following disclaimer, 14 | must be included in all copies of the Software, in whole or in part, and 15 | all derivative works of the Software, unless such copies or derivative 16 | works are solely in the form of machine-executable object code generated by 17 | a source language processor. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 22 | SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 23 | FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 24 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | */ 27 | 28 | #include 29 | #include //for ptrdiff_t 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | #include 36 | 37 | namespace std_backport { 38 | 39 | #define CONSTEXPR_BACKUP CONSTEXPR 40 | #define CONSTEXPR_CPP14_BACKUP CONSTEXPR_CPP14 41 | #undef CONSTEXPR 42 | #if defined(_HAS_CONSTEXPR) || __cplusplus >= 201103L || \ 43 | (defined(_MSC_VER) && _MSC_VER >= 1900) 44 | #define CONSTEXPR constexpr 45 | #define STD_BACKPORT_USE_CONSTEXPR 46 | #else 47 | #define CONSTEXPR 48 | #endif 49 | #if __cplusplus >= 201402L 50 | #define CONSTEXPR_CPP14 constexpr 51 | #else 52 | #define CONSTEXPR_CPP14 53 | #endif 54 | 55 | template class pointer_iterator { 56 | public: 57 | typedef std::random_access_iterator_tag iterator_category; 58 | typedef T *pointer; 59 | typedef T &reference; 60 | typedef reference value_type; 61 | typedef std::ptrdiff_t difference_type; 62 | CONSTEXPR pointer_iterator() : p_(0) {} 63 | CONSTEXPR pointer_iterator(T *x) : p_(x) {} 64 | CONSTEXPR pointer_iterator(const pointer_iterator &it) : p_(it.p_) {} 65 | 66 | CONSTEXPR reference operator*() const { return *p_; } 67 | CONSTEXPR pointer_iterator operator+(difference_type n) const { 68 | return pointer_iterator(p_ + n); 69 | } 70 | CONSTEXPR_CPP14 pointer_iterator &operator+=(difference_type n) { 71 | p_ += n; 72 | return *this; 73 | } 74 | CONSTEXPR pointer_iterator operator-(difference_type n) const { 75 | return pointer_iterator(p_ - n); 76 | } 77 | CONSTEXPR_CPP14 pointer_iterator &operator-=(difference_type n) { 78 | p_ -= n; 79 | return *this; 80 | } 81 | 82 | CONSTEXPR difference_type operator-(pointer_iterator o) const { 83 | return p_ - o.p_; 84 | } 85 | 86 | CONSTEXPR_CPP14 pointer_iterator &operator++() { 87 | p_++; 88 | return *this; 89 | } 90 | CONSTEXPR_CPP14 pointer_iterator operator++(int) { 91 | pointer_iterator tmp(*this); 92 | operator++(); 93 | return tmp; 94 | } 95 | CONSTEXPR_CPP14 pointer_iterator &operator--() { 96 | p_--; 97 | return *this; 98 | } 99 | CONSTEXPR_CPP14 pointer_iterator operator--(int) { 100 | pointer_iterator tmp(*this); 101 | operator--(); 102 | return tmp; 103 | } 104 | CONSTEXPR bool operator==(const pointer_iterator &rhs) const { 105 | return p_ == rhs.p_; 106 | } 107 | CONSTEXPR bool operator!=(const pointer_iterator &rhs) const { 108 | return p_ != rhs.p_; 109 | } 110 | CONSTEXPR bool operator<(const pointer_iterator &rhs) const { 111 | return p_ < rhs.p_; 112 | } 113 | CONSTEXPR bool operator>(const pointer_iterator &rhs) const { 114 | return rhs < *this; 115 | } 116 | CONSTEXPR bool operator<=(const pointer_iterator &rhs) const { 117 | return !(*this > rhs); 118 | } 119 | CONSTEXPR bool operator>=(const pointer_iterator &rhs) const { 120 | return !(*this < rhs); 121 | } 122 | 123 | private: 124 | pointer p_; 125 | }; 126 | 127 | template > 128 | class basic_string_view { 129 | public: 130 | typedef Traits traits_type; 131 | typedef CharT value_type; 132 | typedef CharT *pointer; 133 | typedef const CharT *const_pointer; 134 | typedef CharT &reference; 135 | typedef const CharT &const_reference; 136 | 137 | typedef pointer_iterator const_iterator; 138 | typedef const_iterator iterator; 139 | typedef std::reverse_iterator const_reverse_iterator; 140 | typedef const_reverse_iterator reverse_iterator; 141 | 142 | typedef std::size_t size_type; 143 | typedef std::ptrdiff_t difference_type; 144 | 145 | #if defined(_HAS_CONSTEXPR) || __cplusplus >= 201103L 146 | static constexpr size_type npos = size_type(-1); 147 | #else 148 | static const size_type npos = size_type(-1); 149 | #endif 150 | 151 | CONSTEXPR basic_string_view() : start_(0), length_(0) {} 152 | CONSTEXPR basic_string_view(const basic_string_view &other) 153 | : start_(other.start_), length_(other.length_) {} 154 | template 155 | basic_string_view(const std::basic_string &str) 156 | : start_(0), length_(0) { 157 | if (!str.empty()) { 158 | start_ = &str[0]; 159 | length_ = str.size(); 160 | } 161 | } 162 | CONSTEXPR basic_string_view(const CharT *s, size_type count) 163 | : start_(s), length_(count) {} 164 | CONSTEXPR basic_string_view(const CharT *s) : start_(s), length_(strlen(s)) {} 165 | 166 | basic_string_view &operator=(const basic_string_view &view) { 167 | this->start_ = view.start_; 168 | this->length_ = view.length_; 169 | return *this; 170 | } 171 | 172 | CONSTEXPR const_iterator begin() const { return start_; } 173 | CONSTEXPR const_iterator cbegin() const { return start_; } 174 | 175 | CONSTEXPR const_iterator end() const { return start_ + length_; } 176 | CONSTEXPR const_iterator cend() const { return start_ + length_; } 177 | 178 | CONSTEXPR const_reverse_iterator rbegin() const { 179 | return const_reverse_iterator(start_ + length_); 180 | } 181 | CONSTEXPR const_reverse_iterator rend() const { 182 | return const_reverse_iterator(start_); 183 | } 184 | 185 | CONSTEXPR const_reference operator[](size_type pos) const { 186 | #if __cplusplus >= 201402L 187 | assert(pos < size()); 188 | #endif 189 | return *(start_ + pos); 190 | } 191 | CONSTEXPR const_reference at(size_type pos) const { 192 | return pos >= size() 193 | ? throw std::out_of_range("basic_string_view at out of range") 194 | : *(start_ + pos); 195 | } 196 | CONSTEXPR const_reference front() const { return *begin(); } 197 | CONSTEXPR const_reference back() const { return *end(); } 198 | CONSTEXPR const_pointer data() const { return &(*start_); } 199 | 200 | CONSTEXPR size_type size() const { return std::distance(begin(), end()); } 201 | CONSTEXPR size_type length() const { return std::distance(begin(), end()); } 202 | CONSTEXPR size_type max_size() const { 203 | return std::numeric_limits::max() / 2; 204 | } 205 | CONSTEXPR bool empty() const { return size() == 0; } 206 | CONSTEXPR_CPP14 void remove_prefix(size_type n) { 207 | assert(n <= size()); 208 | start_ += n; 209 | length_ -= n; 210 | } 211 | CONSTEXPR_CPP14 void remove_suffix(size_type n) { 212 | assert(n <= size()); 213 | length_ -= n; 214 | } 215 | CONSTEXPR_CPP14 void swap(basic_string_view &v) { 216 | std::swap(start_, v.start_); 217 | std::swap(length_, v.length_); 218 | } 219 | #if __cplusplus >= 201103L 220 | template > 221 | std::basic_string 222 | to_string(const Allocator &a = Allocator()) const { 223 | return std::basic_string(begin(), end()); 224 | } 225 | template 226 | explicit operator std::basic_string() const { 227 | return std::basic_string(begin(), end()); 228 | } 229 | #else 230 | std::basic_string to_string() const { 231 | return std::basic_string(begin(), end()); 232 | } 233 | template 234 | std::basic_string 235 | to_string(const Allocator &a) const { 236 | return std::basic_string(begin(), end()); 237 | } 238 | template 239 | operator std::basic_string() const { 240 | return std::basic_string(begin(), end()); 241 | } 242 | #endif 243 | size_type copy(CharT *dest, size_type count, size_type pos = 0) const { 244 | if (pos > size()) { 245 | throw std::out_of_range("basic_string_view::copy out of range"); 246 | } 247 | size_t copied = 0; 248 | for (; copied < size(); ++copied) { 249 | dest[copied] = operator[](copied + pos); 250 | } 251 | return copied; 252 | } 253 | CONSTEXPR basic_string_view substr(size_type pos = 0, 254 | size_type count = npos) const { 255 | #ifdef STD_BACKPORT_USE_CONSTEXPR 256 | return pos > size() ? throw std::out_of_range( 257 | "basic_string_view::substr out of range") 258 | : (count > size() - pos) 259 | ? substr(pos, size() - pos) 260 | : basic_string_view(data() + pos, count); 261 | #else 262 | if (pos > size()) { 263 | throw std::out_of_range("basic_string_view::substr out of range"); 264 | } 265 | if (count > size() - pos) { 266 | return substr(pos, size() - pos); 267 | } else { 268 | return basic_string_view(data() + pos, count); 269 | } 270 | #endif 271 | } 272 | CONSTEXPR_CPP14 int compare(basic_string_view v) const { 273 | int r = traits_type::compare(data(), v.data(), std::min(size(), v.size())); 274 | return r == 0 ? static_cast(size()) - static_cast(v.size()) : r; 275 | } 276 | CONSTEXPR_CPP14 int compare(size_type pos1, size_type count1, 277 | basic_string_view v) const { 278 | return substr(pos1, count1).compare(v); 279 | } 280 | CONSTEXPR_CPP14 int compare(size_type pos1, size_type count1, 281 | basic_string_view v, size_type pos2, 282 | size_type count2) const { 283 | return substr(pos1, count1).compare(v.substr(pos2, count2)); 284 | } 285 | CONSTEXPR_CPP14 int compare(const CharT *s) const { 286 | return compare(basic_string_view(s)); 287 | } 288 | CONSTEXPR_CPP14 int compare(size_type pos1, size_type count1, 289 | const CharT *s) const { 290 | return substr(pos1, count1).compare(basic_string_view(s)); 291 | } 292 | CONSTEXPR_CPP14 int compare(size_type pos1, size_type count1, const CharT *s, 293 | size_type count2) const { 294 | return substr(pos1, count1).compare(basic_string_view(s, count2)); 295 | } 296 | 297 | CONSTEXPR size_type find(basic_string_view v, size_type pos = 0) const { 298 | return pos >= size() ? npos 299 | : find_to_pos(std::search(begin() + pos, end(), 300 | v.begin(), v.end())); 301 | } 302 | CONSTEXPR size_type find(CharT c, size_type pos = 0) const { 303 | return find(basic_string_view(&c, 1), pos); 304 | } 305 | CONSTEXPR size_type find(const CharT *s, size_type pos, 306 | size_type count) const { 307 | return find(basic_string_view(s, count), pos); 308 | } 309 | CONSTEXPR size_type find(const CharT *s, size_type pos = 0) const { 310 | return find(basic_string_view(s), pos); 311 | } 312 | 313 | CONSTEXPR size_type rfind(basic_string_view v, size_type pos = npos) const { 314 | return pos > size() 315 | ? rfind(v, size()) 316 | : rfind_to_pos(std::search(const_reverse_iterator(begin() + pos), 317 | rend(), v.rbegin(), v.rend()), 318 | v.size()); 319 | } 320 | CONSTEXPR size_type rfind(CharT c, size_type pos = npos) const { 321 | return rfind(basic_string_view(&c, 1), pos); 322 | } 323 | CONSTEXPR size_type rfind(const CharT *s, size_type pos, 324 | size_type count) const { 325 | return rfind(basic_string_view(s, count), pos); 326 | } 327 | CONSTEXPR size_type rfind(const CharT *s, size_type pos = npos) const { 328 | return rfind(basic_string_view(s), pos); 329 | } 330 | 331 | CONSTEXPR size_type find_first_of(basic_string_view v, 332 | size_type pos = 0) const { 333 | return pos >= size() 334 | ? npos 335 | : v.find(*(start_ + pos)) != npos ? pos 336 | : find_first_of(v, pos + 1); 337 | } 338 | CONSTEXPR size_type find_first_of(CharT c, size_type pos = 0) const { 339 | return find_first_of(basic_string_view(&c, 1), pos); 340 | } 341 | CONSTEXPR size_type find_first_of(const CharT *s, size_type pos, 342 | size_type count) const { 343 | return find_first_of(basic_string_view(s, count), pos); 344 | } 345 | CONSTEXPR size_type find_first_of(const CharT *s, size_type pos = 0) const { 346 | return find_first_of(basic_string_view(s), pos); 347 | } 348 | 349 | CONSTEXPR size_type find_last_of(basic_string_view v, 350 | size_type pos = npos) const { 351 | return pos == 0 ? npos 352 | : pos >= size() ? find_last_of(v, size() - 1) 353 | : v.find(*(start_ + pos)) != npos 354 | ? pos 355 | : find_last_of(v, pos - 1); 356 | } 357 | CONSTEXPR size_type find_last_of(CharT c, size_type pos = npos) const { 358 | return find_last_of(basic_string_view(&c, 1), pos); 359 | } 360 | CONSTEXPR size_type find_last_of(const CharT *s, size_type pos, 361 | size_type count) const { 362 | return find_last_of(basic_string_view(s, count), pos); 363 | } 364 | CONSTEXPR size_type find_last_of(const CharT *s, size_type pos = npos) const { 365 | return find_last_of(basic_string_view(s), pos); 366 | } 367 | 368 | CONSTEXPR size_type find_first_not_of(basic_string_view v, 369 | size_type pos = 0) const { 370 | return pos >= size() 371 | ? npos 372 | : v.find(*(start_ + pos)) == npos ? pos 373 | : find_first_of(v, pos + 1); 374 | } 375 | CONSTEXPR size_type find_first_not_of(CharT c, size_type pos = 0) const { 376 | return find_first_not_of(basic_string_view(&c, 1), pos); 377 | } 378 | CONSTEXPR size_type find_first_not_of(const CharT *s, size_type pos, 379 | size_type count) const { 380 | return find_first_not_of(basic_string_view(s, count), pos); 381 | } 382 | CONSTEXPR size_type find_first_not_of(const CharT *s, 383 | size_type pos = 0) const { 384 | return find_first_not_of(basic_string_view(s), pos); 385 | } 386 | 387 | CONSTEXPR size_type find_last_not_of(basic_string_view v, 388 | size_type pos = npos) const { 389 | return pos == 0 ? npos 390 | : pos >= size() ? find_last_not_of(v, size() - 1) 391 | : v.find(*(start_ + pos)) == npos 392 | ? pos 393 | : find_last_of(v, pos - 1); 394 | } 395 | CONSTEXPR size_type find_last_not_of(CharT c, size_type pos = npos) const { 396 | return find_last_not_of(basic_string_view(&c, 1), pos); 397 | } 398 | CONSTEXPR size_type find_last_not_of(const CharT *s, size_type pos, 399 | size_type count) const { 400 | return find_last_not_of(basic_string_view(s, count), pos); 401 | } 402 | CONSTEXPR size_type find_last_not_of(const CharT *s, 403 | size_type pos = npos) const { 404 | return find_last_not_of(basic_string_view(s), pos); 405 | } 406 | 407 | CONSTEXPR_CPP14 bool operator==(const basic_string_view &rhs) const { 408 | return compare(rhs) == 0; 409 | } 410 | CONSTEXPR_CPP14 bool operator!=(const basic_string_view &rhs) const { 411 | return compare(rhs) != 0; 412 | } 413 | CONSTEXPR_CPP14 bool operator<(const basic_string_view &rhs) const { 414 | return compare(rhs) < 0; 415 | } 416 | CONSTEXPR_CPP14 bool operator>(const basic_string_view &rhs) const { 417 | return rhs < *this; 418 | } 419 | CONSTEXPR_CPP14 bool operator<=(const basic_string_view &rhs) const { 420 | return !(*this > rhs); 421 | } 422 | CONSTEXPR_CPP14 bool operator>=(const basic_string_view &rhs) const { 423 | return !(*this < rhs); 424 | } 425 | 426 | private: 427 | CONSTEXPR basic_string_view(const iterator &s, const iterator &e) 428 | : start_(s), length_(e - s) {} 429 | iterator start_; 430 | size_type length_; 431 | 432 | CONSTEXPR size_type find_to_pos(const_iterator it) const { 433 | return it == end() ? npos : size_type(it - begin()); 434 | } 435 | CONSTEXPR size_type rfind_to_pos(const_reverse_iterator it, 436 | size_type search_size) const { 437 | return it == rend() ? npos : size_type(it.base() - begin() - search_size); 438 | } 439 | 440 | CONSTEXPR static const_pointer strlen_nullpos(const_pointer str) { 441 | return *str == '\0' ? str : strlen_nullpos(str + 1); 442 | } 443 | CONSTEXPR static size_type strlen(const_pointer str) { 444 | return strlen_nullpos(str) - str; 445 | } 446 | }; 447 | 448 | #undef CONSTEXPR 449 | #define CONSTEXPR CONSTEXPR_BACKUP 450 | #undef CONSTEXPR_BACKUP 451 | 452 | #undef CONSTEXPR_CPP14 453 | #define CONSTEXPR_CPP14 CONSTEXPR_CPP14_BACKUP 454 | #undef CONSTEXPR_CPP14_BACKUP 455 | 456 | typedef basic_string_view string_view; 457 | typedef basic_string_view wstring_view; 458 | 459 | #if defined(_HAS_CONSTEXPR) || __cplusplus >= 201103L || \ 460 | (defined(_MSC_VER) && _MSC_VER >= 1800) 461 | typedef basic_string_view u16string_view; 462 | typedef basic_string_view u32string_view; 463 | #endif 464 | }; // namespace std_backport 465 | -------------------------------------------------------------------------------- /string_view_test.cpp: -------------------------------------------------------------------------------- 1 | #include "string_view.hpp" 2 | #include 3 | #include 4 | #include 5 | 6 | void compare_with_std_string_test() { 7 | std::string s = "This is a string"; 8 | std_backport::string_view v(s); 9 | 10 | assert(v.substr(0) == s.substr(0)); 11 | assert(v.substr(0, 5) == s.substr(0, 5)); 12 | assert(v.substr(1, 5) == s.substr(1, 5)); 13 | assert(v.substr(4, 5) == s.substr(4, 5)); 14 | assert(v.substr(0, 322) == s.substr(0, 322)); 15 | 16 | #define FIND_TEST_FUNCTION(FNAME) \ 17 | assert(s.FNAME("is") == v.FNAME("is")); \ 18 | assert(s.FNAME("is", 4) == v.FNAME("is", 4)); \ 19 | assert(s.FNAME("s", 4) == v.FNAME("s", 4)); \ 20 | assert(s.FNAME("s", 4, 1) == v.FNAME("s", 4, 1)); \ 21 | assert(s.FNAME("s") == v.FNAME("s")); \ 22 | assert(s.FNAME('q') == v.FNAME('q')); \ 23 | assert(s.FNAME('q') == v.FNAME('q')); \ 24 | assert(s.FNAME('q', s.size()) == v.FNAME('q', v.size())); \ 25 | assert(s.FNAME('q', s.size() + 1) == v.FNAME('q', v.size() + 1)); 26 | 27 | FIND_TEST_FUNCTION(find); 28 | FIND_TEST_FUNCTION(rfind); 29 | FIND_TEST_FUNCTION(find_first_of); 30 | FIND_TEST_FUNCTION(find_last_of); 31 | FIND_TEST_FUNCTION(find_first_not_of); 32 | FIND_TEST_FUNCTION(find_last_not_of); 33 | 34 | #undef FIND_TEST_FUNCTION 35 | 36 | assert(v.find('q') == std_backport::string_view::npos); 37 | assert(v.rfind('q') == std_backport::string_view::npos); 38 | assert(v.rfind("is", 4) == 2); 39 | assert(v.rfind("s") == 10); 40 | 41 | assert(v.find_first_of('q') == std_backport::string_view::npos); 42 | assert(v.find_last_of('q') == std_backport::string_view::npos); 43 | assert(v.find_first_not_of('q') == 0); 44 | assert(v.find_last_not_of('q') == v.size() - 1); 45 | 46 | { 47 | std_backport::string_view view; 48 | assert((view = "test") == std::string("test")); 49 | assert((view = "") == std::string("")); 50 | assert((view = "") == std::string()); 51 | } 52 | 53 | { 54 | std_backport::string_view view = "test"; 55 | char buffer[5] = {}; 56 | ; 57 | assert(view.copy(buffer, 5) == 4); 58 | assert(strcmp(buffer, "test") == 0); 59 | } 60 | { 61 | std_backport::string_view view = "test"; 62 | assert(view.to_string() == "test"); 63 | } 64 | 65 | assert((v == s)); 66 | assert((v <= s)); 67 | assert((v >= s)); 68 | assert(!(v != s)); 69 | assert(!(v < s)); 70 | assert(!(v > s)); 71 | 72 | assert(!(v == "")); 73 | assert(!(v <= "")); 74 | assert((v >= "")); 75 | assert((v != "")); 76 | assert(!(v < "")); 77 | assert((v > "")); 78 | 79 | assert(!(v == "a")); 80 | assert((v <= "a")); 81 | assert(!(v >= "a")); 82 | assert((v != "a")); 83 | assert((v < "a")); 84 | assert(!(v > "a")); 85 | 86 | bool catch_except = false; 87 | try { 88 | v.substr(v.size() + 1, 1); 89 | } catch (std::exception &) { 90 | catch_except = true; 91 | } 92 | assert(catch_except); 93 | 94 | assert(v.substr(v.size(), 0) == ""); 95 | } 96 | 97 | int main() { 98 | 99 | #ifdef STD_BACKPORT_USE_CONSTEXPR 100 | constexpr std_backport::string_view constexpr_view; 101 | constexpr std_backport::string_view constexpr_view2 = constexpr_view; 102 | assert(constexpr_view2 == constexpr_view); 103 | assert(constexpr_view2 == ""); 104 | constexpr std_backport::string_view constexpr_view3("test"); 105 | constexpr std_backport::string_view constexpr_view4 = constexpr_view3; 106 | assert(constexpr_view4 == constexpr_view3); 107 | assert(constexpr_view4 == "test"); 108 | #endif 109 | 110 | std_backport::string_view view("test"); 111 | 112 | std::string str("test2"); 113 | std_backport::string_view view2(str); 114 | 115 | { 116 | assert(view.substr(1) == "est"); 117 | assert(view.substr(1, 1) == "e"); 118 | assert(view2.substr(1) == "est2"); 119 | 120 | assert(view.compare(view2) < 0); 121 | assert(view2.compare(view) > 0); 122 | assert(view.compare(view2.substr(0, 4)) == 0); 123 | 124 | assert(view2.substr(1, 3) == "est"); 125 | } 126 | compare_with_std_string_test(); 127 | 128 | std::string empty_str; 129 | std_backport::string_view empty_view(empty_str); 130 | assert(empty_view == empty_str); 131 | 132 | std_backport::string_view editview("test"); 133 | editview.remove_prefix(2); 134 | assert(editview == "st"); 135 | editview = "test"; 136 | editview.remove_suffix(2); 137 | assert(editview == "te"); 138 | return 0; 139 | } 140 | -------------------------------------------------------------------------------- /test_runner.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import shlex,subprocess 3 | import os 4 | import urllib 5 | import tarfile 6 | 7 | test_msvc_vers = [("msvc2015","Visual Studio 14 2015","",True) 8 | ,("msvc2015win64","Visual Studio 14 2015 Win64","",True) 9 | ,("msvc2013","Visual Studio 12 2013","",False) 10 | ,("msvc2013win64","Visual Studio 12 2013 Win64","",False) 11 | ,("msvc2012","Visual Studio 11 2012","",False) 12 | ,("msvc2010","Visual Studio 10 2010","",False) 13 | ,("msvc2008","Visual Studio 9 2008","",True) 14 | ] 15 | 16 | test_compilers = [ 17 | ('gcc-3.3','g++-3.3','',False) 18 | ,('gcc-4.4','g++-4.4','',False) 19 | ,('gcc-4.5','g++-4.5','',False) 20 | ,('gcc-4.6','g++-4.6','-DCMAKE_CXX_FLAGS=-std=c++03',False) 21 | ,('gcc-4.7','g++-4.7','-DCMAKE_CXX_FLAGS=-std=c++03',False) 22 | ,('gcc-4.7','g++-4.7','-DCMAKE_CXX_FLAGS=-std=c++11',False) 23 | ,('gcc-4.8','g++-4.8','-DCMAKE_CXX_FLAGS=-std=c++03',False) 24 | ,('gcc-4.8','g++-4.8','-DCMAKE_CXX_FLAGS=-std=c++11',False) 25 | ,('gcc-4.9','g++-4.9','-DCMAKE_CXX_FLAGS=-std=c++03',False) 26 | ,('gcc-4.9','g++-4.9','-DCMAKE_CXX_FLAGS=-std=c++11',False) 27 | ,('gcc-5','g++-5','-DCMAKE_CXX_FLAGS=-std=c++03',False) 28 | ,('gcc-5','g++-5','-DCMAKE_CXX_FLAGS=-std=c++11',False) 29 | ,('gcc-6','g++-6','-DCMAKE_CXX_FLAGS=-std=c++03',False) 30 | ,('gcc-6','g++-6','-DCMAKE_CXX_FLAGS=-std=c++11',False) 31 | ,('gcc-6','g++-6','-DCMAKE_CXX_FLAGS=-std=c++14',False) 32 | ,('gcc','g++','-DCMAKE_CXX_FLAGS=-std=c++03',True) 33 | ,('gcc','g++','-DCMAKE_CXX_FLAGS=-std=c++11',True) 34 | ,('clang','clang++','-DCMAKE_CXX_FLAGS=-std=c++03',True) 35 | ,('clang','clang++','-DCMAKE_CXX_FLAGS=-std=c++11',True) 36 | ,('clang-3.5','clang++-3.5','-DCMAKE_CXX_FLAGS=-std=c++03',False) 37 | ,('clang-3.6','clang++-3.6','-DCMAKE_CXX_FLAGS=-std=c++03',False) 38 | ,('clang-3.7','clang++-3.7','-DCMAKE_CXX_FLAGS=-std=c++03',False) 39 | ,('clang-3.8','clang++-3.8','-DCMAKE_CXX_FLAGS=-std=c++03',False) 40 | ,('clang-3.9','clang++-3.9','-DCMAKE_CXX_FLAGS=-std=c++03',False) 41 | ,('clang-4.0','clang++-4.0','-DCMAKE_CXX_FLAGS=-std=c++03',False) 42 | ,('clang-3.5','clang++-3.5','-DCMAKE_CXX_FLAGS=-std=c++11',False) 43 | ,('clang-3.6','clang++-3.6','-DCMAKE_CXX_FLAGS=-std=c++11',False) 44 | ,('clang-3.7','clang++-3.7','-DCMAKE_CXX_FLAGS=-std=c++11',False) 45 | ,('clang-3.8','clang++-3.8','-DCMAKE_CXX_FLAGS=-std=c++11',False) 46 | ,('clang-3.9','clang++-3.9','-DCMAKE_CXX_FLAGS=-std=c++11',False) 47 | ,('clang-4.0','clang++-4.0','-DCMAKE_CXX_FLAGS=-std=c++11',False) 48 | ,('clang-3.8','clang++-3.8','-DCMAKE_CXX_FLAGS=-std=c++14',False) 49 | ,('clang-3.9','clang++-3.9','-DCMAKE_CXX_FLAGS=-std=c++14',False) 50 | ,('clang-4.0','clang++-4.0','-DCMAKE_CXX_FLAGS=-std=c++14',False) 51 | ] 52 | 53 | def build_and_exec_test(compiler,build_type,dir_opt): 54 | ccompiler = compiler[0] 55 | cxxcompiler = compiler[1] 56 | addopt = compiler[2] 57 | if os.system(cxxcompiler+' -v 2> /dev/null')!=0: return 58 | 59 | buildpath = "_build/"+compiler[0]+"_"+build_type+"_"+dir_opt 60 | if not os.path.exists(buildpath): 61 | os.makedirs(buildpath) 62 | os.chdir(buildpath) 63 | ret = os.system('CC='+ccompiler+' CXX='+cxxcompiler+' cmake ../../ '+addopt+' -DCMAKE_BUILD_TYPE='+build_type) 64 | if ret != 0:#pass through cmake failed. 65 | os.chdir("../../") 66 | return 67 | ret = os.system('make -j 2') 68 | if ret != 0: raise Exception("build error at"+buildpath) 69 | ret = os.system('ctest --output-on-failure') 70 | if ret != 0: raise Exception("test error at"+buildpath) 71 | os.chdir("../../") 72 | 73 | def build_with_target_compiler(): 74 | for i,compiler in enumerate(test_compilers): 75 | build_and_exec_test(compiler,"Debug",str(i)) 76 | build_and_exec_test(compiler,"Release",str(i)) 77 | 78 | def build_msvc_and_exec_test(msvcver,build_type): 79 | buildpath = '_build/'+msvcver[0] 80 | if not os.path.exists(buildpath): 81 | os.makedirs(buildpath) 82 | os.chdir(buildpath) 83 | ret = os.system('cmake ../../ -G "'+msvcver[1]+'" '+msvcver[2]) 84 | if ret != 0: 85 | os.chdir("../../") 86 | return 87 | ret = os.system('cmake --build . --config '+build_type) 88 | if ret != 0: raise Exception("build error at"+buildpath) 89 | ret = os.system('ctest --output-on-failure -C '+build_type) 90 | if ret != 0: raise Exception("test error at"+buildpath) 91 | os.chdir("../../") 92 | 93 | def build_with_msvc_ver(): 94 | for msvcver in test_msvc_vers: 95 | build_msvc_and_exec_test(msvcver,'Debug') 96 | build_msvc_and_exec_test(msvcver,'Release') 97 | 98 | 99 | 100 | if os.name == 'nt': 101 | build_with_msvc_ver() 102 | else: 103 | build_with_target_compiler() 104 | --------------------------------------------------------------------------------