// rak - Rakshasa's toolbox // Copyright (C) 2005-2007, Jari Sundell // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // In addition, as a special exception, the copyright holders give // permission to link the code of portions of this program with the // OpenSSL library under certain conditions as described in each // individual source file, and distribute linked combinations // including the two. // // You must obey the GNU General Public License in all respects for // all of the code used other than OpenSSL. If you modify file(s) // with this exception, you may extend this exception to your version // of the file(s), but you are not obligated to do so. If you do not // wish to do so, delete this exception statement from your version. // If you delete this exception statement from all source files in the // program, then also delete it here. // // Contact: Jari Sundell // // Skomakerveien 33 // 3185 Skoppum, NORWAY #ifndef RAK_STRING_MANIP_H #define RAK_STRING_MANIP_H #include #include #include #include #include namespace rak { // Use these trim functions until n1872 is widely supported. template Sequence trim_begin(const Sequence& seq) { if (seq.empty() || !std::isspace(*seq.begin())) return seq; typename Sequence::size_type pos = 0; while (pos != seq.length() && std::isspace(seq[pos])) pos++; return seq.substr(pos, seq.length() - pos); } template Sequence trim_end(const Sequence& seq) { if (seq.empty() || !std::isspace(*(--seq.end()))) return seq; typename Sequence::size_type pos = seq.size(); while (pos != 0 && std::isspace(seq[pos - 1])) pos--; return seq.substr(0, pos); } template Sequence trim(const Sequence& seq) { return trim_begin(trim_end(seq)); } template Sequence trim_begin_classic(const Sequence& seq) { if (seq.empty() || !std::isspace(*seq.begin(), std::locale::classic())) return seq; typename Sequence::size_type pos = 0; while (pos != seq.length() && std::isspace(seq[pos], std::locale::classic())) pos++; return seq.substr(pos, seq.length() - pos); } template Sequence trim_end_classic(const Sequence& seq) { if (seq.empty() || !std::isspace(*(--seq.end()), std::locale::classic())) return seq; typename Sequence::size_type pos = seq.size(); while (pos != 0 && std::isspace(seq[pos - 1], std::locale::classic())) pos--; return seq.substr(0, pos); } template Sequence trim_classic(const Sequence& seq) { return trim_begin_classic(trim_end_classic(seq)); } // Consider rewritting such that m_seq is replaced by first/last. template class split_iterator_t { public: typedef typename Sequence::const_iterator const_iterator; typedef typename Sequence::value_type value_type; split_iterator_t() {} split_iterator_t(const Sequence& seq, value_type delim) : m_seq(&seq), m_delim(delim), m_pos(seq.begin()), m_next(std::find(seq.begin(), seq.end(), delim)) { } Sequence operator * () { return Sequence(m_pos, m_next); } split_iterator_t& operator ++ () { m_pos = m_next; if (m_pos == m_seq->end()) return *this; m_pos++; m_next = std::find(m_pos, m_seq->end(), m_delim); return *this; } bool operator == (__UNUSED const split_iterator_t& itr) const { return m_pos == m_seq->end(); } bool operator != (__UNUSED const split_iterator_t& itr) const { return m_pos != m_seq->end(); } private: const Sequence* m_seq; value_type m_delim; const_iterator m_pos; const_iterator m_next; }; template inline split_iterator_t split_iterator(const Sequence& seq, typename Sequence::value_type delim) { return split_iterator_t(seq, delim); } template inline split_iterator_t split_iterator(__UNUSED const Sequence& seq) { return split_iterator_t(); } // Could optimize this abit. inline char hexchar_to_value(char c) { if (c >= '0' && c <= '9') return c - '0'; else if (c >= 'A' && c <= 'F') return 10 + c - 'A'; else return 10 + c - 'a'; } template inline char value_to_hexchar(Value v) { v >>= pos * 4; v &= 0xf; if (v < 0xA) return '0' + v; else return 'A' + v - 0xA; } template OutputIterator copy_escape_html(InputIterator first, InputIterator last, OutputIterator dest) { while (first != last) { if (std::isalpha(*first, std::locale::classic()) || std::isdigit(*first, std::locale::classic()) || *first == '-') { *(dest++) = *first; } else { *(dest++) = '%'; *(dest++) = value_to_hexchar<1>(*first); *(dest++) = value_to_hexchar<0>(*first); } ++first; } return dest; } template OutputIterator copy_escape_html(InputIterator first1, InputIterator last1, OutputIterator first2, OutputIterator last2) { while (first1 != last1) { if (std::isalpha(*first1, std::locale::classic()) || std::isdigit(*first1, std::locale::classic()) || *first1 == '-') { if (first2 == last2) break; else *(first2++) = *first1; } else { if (first2 == last2) break; else *(first2++) = '%'; if (first2 == last2) break; else *(first2++) = value_to_hexchar<1>(*first1); if (first2 == last2) break; else *(first2++) = value_to_hexchar<0>(*first1); } ++first1; } return first2; } template inline std::string copy_escape_html(Iterator first, Iterator last) { std::string dest; copy_escape_html(first, last, std::back_inserter(dest)); return dest; } template inline Sequence copy_escape_html(const Sequence& src) { Sequence dest; copy_escape_html(src.begin(), src.end(), std::back_inserter(dest)); return dest; } template inline std::string copy_escape_html_str(const Sequence& src) { std::string dest; copy_escape_html(src.begin(), src.end(), std::back_inserter(dest)); return dest; } // Consider support for larger than char type. template OutputIterator transform_hex(InputIterator first, InputIterator last, OutputIterator dest) { while (first != last) { *(dest++) = value_to_hexchar<1>(*first); *(dest++) = value_to_hexchar<0>(*first); ++first; } return dest; } template OutputIterator transform_hex(InputIterator first1, InputIterator last1, OutputIterator first2, OutputIterator last2) { while (first1 != last1) { if (first2 == last2) break; else *(first2++) = value_to_hexchar<1>(*first1); if (first2 == last2) break; else *(first2++) = value_to_hexchar<0>(*first1); ++first1; } return first2; } template inline Sequence transform_hex(const Sequence& src) { Sequence dest; transform_hex(src.begin(), src.end(), std::back_inserter(dest)); return dest; } template inline std::string transform_hex(Iterator first, Iterator last) { std::string dest; transform_hex(first, last, std::back_inserter(dest)); return dest; } template inline std::string transform_hex_str(const Sequence& seq) { std::string dest; transform_hex(seq.begin(), seq.end(), std::back_inserter(dest)); return dest; } template Sequence generate_random(size_t length) { Sequence s; s.reserve(length); std::generate_n(std::back_inserter(s), length, &::random); return s; } template inline bool is_all_alpha(Iterator first, Iterator last) { while (first != last) if (!std::isalpha(*first++, std::locale::classic())) return false; return true; } template inline bool is_all_alpha(const Sequence& src) { return is_all_alpha(src.begin(), src.end()); } template inline bool is_all_alnum(Iterator first, Iterator last) { while (first != last) if (!std::isalnum(*first++, std::locale::classic())) return false; return true; } template inline bool is_all_alnum(const Sequence& src) { return is_all_alnum(src.begin(), src.end()); } template inline bool is_all_name(Iterator first, Iterator last) { while (first != last) { if (!std::isalnum(*first, std::locale::classic()) && *first != '_') return false; first++; } return true; } template inline bool is_all_name(const Sequence& src) { return is_all_name(src.begin(), src.end()); } } #endif