#ifndef EXTRACT_HPP #define EXTRACT_HPP // 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 "sanity.hpp" #include #include "const_array.hpp" #include "mmo.hpp" #include "utils.hpp" template::value && !std::is_same::value && !std::is_same::value>::type> bool 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 extract(XString str, TimeT *tv) { return extract(str, &tv->value); } // extra typename=void to workaround some duplicate overload rule template::value>::type, typename=void> bool extract(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 extract(XString str, XString *rv); bool extract(XString str, FString *rv); template bool extract(XString str, VString *out) { if (str.size() > N) return false; *out = str; return true; } template class LStripper { public: T impl; }; template LStripper lstripping(T v) { return {v}; } template bool 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 extract(XString str, Record) { return !str; } template bool 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 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); } bool extract(XString str, struct global_reg *var); bool extract(XString str, struct item *it); inline bool extract(XString str, MapName *m) { XString::iterator it = std::find(str.begin(), str.end(), '.'); str = str.xislice_h(it); VString<15> tmp; bool rv = extract(str, &tmp); *m = tmp; return rv; } inline bool extract(XString str, CharName *out) { VString<23> tmp; if (extract(str, &tmp)) { *out = CharName(tmp); return true; } return false; } #endif // EXTRACT_HPP