/* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright 2011-2016 Danny Robson */ #ifndef CRUFT_UTIL_STRING_HPP #define CRUFT_UTIL_STRING_HPP #include "debug.hpp" #include "view.hpp" namespace util { std::string to_utf8 (const wchar_t*); std::string to_utf8 (const std::wstring&); } bool strbegins(const char *restrict str, const char *restrict prefix); namespace util { template struct tokeniser { public: using value_type = typename std::iterator_traits::value_type; using range_type = view; tokeniser (util::view _range, value_type _separator): m_range (_range), m_separator (_separator) { ; } tokeniser (const char *_range, char _separator): m_range (_range), m_separator (_separator) { ; } struct iterator : public std::iterator< std::forward_iterator_tag, range_type, std::size_t > { public: iterator operator++ (int) { iterator res(*this); ++*this; return res; } iterator& operator++ (void)& { auto newend = m_range.cend (); if (newend != m_end) { CHECK_EQ (*m_range.cend (), m_separator); newend++; } m_range = { newend, std::find (newend, m_end, m_separator) }; return *this; } iterator operator+ (int count) { auto next = *this; std::advance (next, count); return next; } const range_type& operator* (void) const { return m_range; } const range_type* operator-> (void) const { return &m_range; } bool operator== (const iterator &rhs) const { return m_range == rhs.m_range && m_separator == rhs.m_separator; } bool operator!= (const iterator &rhs) const { return !(*this == rhs); } private: iterator (range_type _range, value_type _separator): m_separator (_separator), m_range (_range.cbegin (), std::find (_range.cbegin (), _range.cend (), _separator) ), m_end (_range.cend ()) { ; } value_type m_separator; range_type m_range; Iterator m_end; friend tokeniser; }; iterator cbegin (void) const { return { m_range, m_separator }; } iterator begin (void) const { return { m_range, m_separator }; } iterator cend (void) const { return { { m_range.cend (), m_range.cend () }, m_separator }; } iterator end (void) const { return { { m_range.cend (), m_range.cend () }, m_separator }; } private: const range_type m_range; const value_type m_separator; }; template tokeniser (ContainerT&, typename ContainerT::value_type) -> tokeniser; tokeniser (const char*,char) -> tokeniser; /////////////////////////////////////////////////////////////////////////// template auto make_tokeniser (CharT (&data)[LengthV], CharT separator) { return tokeniser { std::begin (data), std::end (data), separator }; } } #endif // __UTIL_STRING_HPP