/////////////////////////////////////////////////////////////////////////////// // // Copyright (c) 2015 Microsoft Corporation. All rights reserved. // // This code is licensed under the MIT License (MIT). // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // /////////////////////////////////////////////////////////////////////////////// #pragma once #ifndef GSL_STRING_VIEW_H #define GSL_STRING_VIEW_H #include "array_view.h" #include namespace gsl { // // czstring and wzstring // // These are "tag" typedef's for C-style strings (i.e. null-terminated character arrays) // that allow static analysis to help find bugs. // // There are no additional features/semantics that we can find a way to add inside the // type system for these types that will not either incur significant runtime costs or // (sometimes needlessly) break existing programs when introduced. // template using czstring = const char*; template using cwzstring = const wchar_t*; template using zstring = char*; template using wzstring = wchar_t*; // // string_view and relatives // // Note that Extent is always single-dimension only // Note that SizeType is defaulted to be smaller than size_t which is the array_view default // // TODO (neilmac) once array_view regains configurable size_type, update these typedef's // template using basic_string_view = array_view; template using string_view = basic_string_view; template using cstring_view = basic_string_view; template using wstring_view = basic_string_view; template using cwstring_view = basic_string_view; // // ensure_sentinel() // // Provides a way to obtain an array_view from a contiguous sequence // that ends with a (non-inclusive) sentinel value. // // Will fail-fast if sentinel cannot be found before max elements are examined. // template array_view ensure_sentinel(const T* seq, SizeType max = std::numeric_limits::max()) { auto cur = seq; while (SizeType(cur - seq) < max && *cur != Sentinel) ++cur; fail_fast_assert(*cur == Sentinel); return{ seq, SizeType(cur - seq) }; } // // ensure_z - creates a string_view for a czstring or cwzstring. // Will fail fast if a null-terminator cannot be found before // the limit of size_type. // template inline basic_string_view ensure_z(T* const & sz, std::ptrdiff_t max = PTRDIFF_MAX) { return ensure_sentinel(sz, max); } // TODO (neilmac) there is probably a better template-magic way to get the const and non-const overloads to share an implementation inline basic_string_view ensure_z(char* const& sz, std::ptrdiff_t max) { auto len = strnlen(sz, max); fail_fast_assert(sz[len] == 0); return{ sz, static_cast(len) }; } inline basic_string_view ensure_z(const char* const& sz, std::ptrdiff_t max) { auto len = strnlen(sz, max); fail_fast_assert(sz[len] == 0); return{ sz, static_cast(len) }; } inline basic_string_view ensure_z(wchar_t* const& sz, std::ptrdiff_t max) { auto len = wcsnlen(sz, max); fail_fast_assert(sz[len] == 0); return{ sz, static_cast(len) }; } inline basic_string_view ensure_z(const wchar_t* const& sz, std::ptrdiff_t max) { auto len = wcsnlen(sz, max); fail_fast_assert(sz[len] == 0); return{ sz, static_cast(len) }; } template basic_string_view ensure_z(T(&sz)[N]) { return ensure_z(&sz[0], static_cast(N)); } template basic_string_view::type, dynamic_range> ensure_z(Cont& cont) { return ensure_z(cont.data(), cont.length()); } // // to_string() allow (explicit) conversions from string_view to string // template std::basic_string::type> to_string(basic_string_view view) { return{ view.data(), view.length() }; } template class basic_zstring_builder { public: using string_view_type = basic_string_view; using value_type = CharT; using pointer = CharT*; using size_type = typename string_view_type::size_type; using iterator = typename string_view_type::iterator; basic_zstring_builder(CharT* data, size_type length) : sv_(data, length) {} template basic_zstring_builder(CharT(&arr)[Size]) : sv_(arr) {} pointer data() const { return sv_.data(); } string_view_type view() const { return sv_; } size_type length() const { return sv_.length(); } pointer assume0() const { return data(); } string_view_type ensure_z() const { return gsl::ensure_z(sv_); } iterator begin() const { return sv_.begin(); } iterator end() const { return sv_.end(); } private: string_view_type sv_; }; template using zstring_builder = basic_zstring_builder; template using wzstring_builder = basic_zstring_builder; } #endif // GSL_STRING_VIEW_H