/* * charybdis: an advanced ircd. * inline/stringops.h: inlined string operations used in a few places * * Copyright (C) 2005-2016 Charybdis Development Team * * 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 */ #include ; const delim d(sep); const boost::tokenizer view(str, d); size_t i(0); auto it(begin(view)); for(; it != end(view); ++it, i++) if(i == at) return *it; if(str.empty()) return str; // Moving the iterator may cause a parse, so there is no pre-check on the bounds; // the valid token is returned in the loop, and exiting the loop is an error. throw std::out_of_range("token out of range"); } std::string ircd::token_last(const std::string &str, const char *const &sep) { using delim = boost::char_separator; const delim d(sep); const boost::tokenizer view(str, d); auto it(begin(view)); if(it == end(view)) return str.empty()? str : throw std::out_of_range("token out of range"); auto ret(it); while(it != end(view)) ret = it++; return *ret; } size_t ircd::token_count(const std::string &str, const char *const &sep) { using delim = boost::char_separator; const delim d(sep); const boost::tokenizer view(str, d); return std::distance(begin(view), end(view)); } std::vector ircd::tokens(const std::string &str, const char *const &sep, const size_t &reserve) { using delim = boost::char_separator; std::vector ret; ret.reserve(reserve); const delim d(sep); const boost::tokenizer view(str, d); std::copy(begin(view), end(view), std::back_inserter(ret)); return ret; } void ircd::tokens(const std::string &str, const char *const &sep, const token_closure_string &closure) { using delim = boost::char_separator; const delim d(sep); const boost::tokenizer view(str, d); std::for_each(begin(view), end(view), closure); } std::vector ircd::tokens(const char *const &str, const char *const &sep, char *const &buf, const size_t &max, const size_t &reserve) { std::vector ret; ret.reserve(reserve); rb_strlcpy(buf, str, max); tokens(buf, sep, [&ret] (char *const &token) { ret.emplace_back(token); }); return ret; } void ircd::tokensa(const char *const &str, const char *const &sep, const token_closure_cstr &closure) { custom_ptr cpy(strdup(str), std::free); tokens(cpy.get(), sep, closure); } void ircd::tokens(const char *const &str, const char *const &sep, const token_closure_cstr &closure) { const auto len(strlen(str)); char buf[strlen(str) + 1]; tokens(str, sep, buf, sizeof(buf), closure); } void ircd::tokens(const char *const &str, const char *const &sep, char *const &buf, const size_t &max, const token_closure_cstr &closure) { rb_strlcpy(buf, str, max); tokens(buf, sep, closure); } void ircd::tokens(char *const &str, const char *const &sep, const token_closure_cstr &closure) { char *ctx; char *tok(strtok_r(str, sep, &ctx)); do { closure(tok); } while((tok = strtok_r(NULL, sep, &ctx)) != NULL); }