#pragma once // extract.hpp - a simple, hierarchical, tokenizer // // Copyright © 2012-2013 Ben Longbons // // This file is part of The Mana World (Athena server) // // 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 3 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, see . #include "fwd.hpp" #include #include #include #include #include #include "../ints/wrap.hpp" #include "../strings/xstring.hpp" #include "../compat/time_t.hpp" #include "../generic/enum.hpp" namespace tmwa { template bool extract(XString str, T t); template::value && !std::is_same::value && !std::is_same::value>::type> bool impl_extract(XString str, T *iv) { if (!str || str.size() > 20) return false; if (!((str.front() == '-' && std::is_signed::value) || ('0' <= str.front() && str.front() <= '9'))) return false; // needs a NUL, but can't always be given one. TODO VString? char buf[20 + 1]; std::copy(str.begin(), str.end(), buf); buf[str.size()] = '\0'; char *end; errno = 0; if (std::is_signed::value) { long long v = strtoll(buf, &end, 10); if (errno || *end) return false; *iv = v; return *iv == v; } else { unsigned long long v = strtoull(buf, &end, 10); if (errno || *end) return false; *iv = v; return *iv == v; } } inline bool impl_extract(XString str, TimeT *tv) { return extract(str, &tv->value); } template::value>::type> bool extract_as_int(XString str, T *iv) { typedef typename underlying_type::type U; U v; // defer to integer version if (!extract(str, &v)) return false; // TODO check bounds using enum min/max as in SSCANF *iv = static_cast(v); return true; } bool impl_extract(XString str, XString *rv); bool impl_extract(XString str, RString *rv); bool impl_extract(XString str, AString *rv); template bool impl_extract(XString str, VString *out) { if (str.size() > N) return false; *out = str; return true; } inline bool impl_extract(XString str, LString exact) { return str == exact; } template class LStripper { public: T impl; }; template LStripper lstripping(T v) { return {v}; } template bool impl_extract(XString str, LStripper out) { return extract(str.lstrip(), out.impl); } // basically just a std::tuple // but it provides its data members publically template class Record; template class Record { }; template class Record { public: F frist; Record rest; public: Record(F f, R... r) : frist(f), rest(r...) {} }; template Record record(T... t) { return Record(t...); } template Record record(T... t) { static_assert(0 < n && n < sizeof...(T), "don't be silly"); return Record(t...); } template bool impl_extract(XString str, Record) { return !str; } template bool impl_extract(XString str, Record rec) { XString::iterator s = std::find(str.begin(), str.end(), split); XString::iterator s2 = s; if (s2 != str.end()) ++s2; XString head = str.xislice_h(s); XString tail = str.xislice_t(s2); if (s == str.end()) return (extract(head, rec.frist) && n <= 1) || (!head && n <= 0); return (extract(head, rec.frist) || n <= 0) && extract(tail, rec.rest); } template struct VRecord { std::vector *arr; }; template VRecord vrec(std::vector *arr) { return {arr}; } template bool impl_extract(XString str, VRecord rec) { if (!str) return true; XString::iterator s = std::find(str.begin(), str.end(), split); rec.arr->emplace_back(); if (s == str.end()) return extract(str, &rec.arr->back()); return extract(str.xislice_h(s), &rec.arr->back()) && extract(str.xislice_t(s + 1), rec); } template bool impl_extract(XString str, Wrapped *w) { return extract(str, &w->_value); } bool impl_extract(XString str, std::chrono::nanoseconds *ns); bool impl_extract(XString str, std::chrono::microseconds *us); bool impl_extract(XString str, std::chrono::milliseconds *ms); bool impl_extract(XString str, std::chrono::seconds *s); bool impl_extract(XString str, std::chrono::minutes *min); bool impl_extract(XString str, std::chrono::hours *h); bool impl_extract(XString str, std::chrono::duration> *d); // this must come after all non-`namespace tmwa` `impl_extract`s. // In particular, the ones for `*int*` and `std::chrono::*` template bool extract(XString str, T t) { return impl_extract(str, t); } } // namespace tmwa