#include "astring.hpp" // strings/astring.cpp - Functions for astring.hpp // // Copyright © 2013-2014 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 #include #include #include #include "mstring.hpp" #include "tstring.hpp" #include "sstring.hpp" #include "zstring.hpp" #include "xstring.hpp" #include "literal.hpp" // doing sneaky tricks here //#include "../poison.hpp" namespace tmwa { namespace strings { static_assert(sizeof(AString) == 256, "AString"); static void acpy(char (&dst)[255], const char (&src)[255]) { std::copy(src + 0, src + 255, dst); } AString::AString() : data{}, special() { new(r_ptr()) RString(); special = 255; } AString::AString(const AString& a) : data(), special(a.special) { acpy(data, a.data); if (special == 255) new(r_ptr()) RString(*a.r_ptr()); } AString::AString(AString&& a) : data(), special(a.special) { acpy(data, a.data); if (special == 255) new(r_ptr()) RString(std::move(*a.r_ptr())); } AString& AString::operator = (const AString& a) { if (this == &a) return *this; if (special == 255) r_ptr()->~RString(); acpy(data, a.data); special = a.special; if (special == 255) new(r_ptr()) RString(*a.r_ptr()); return *this; } AString& AString::operator = (AString&& a) { std::swap(data, a.data); std::swap(special, a.special); return *this; } AString::AString(RString r) : data{}, special() { new(r_ptr()) RString(std::move(r)); special = 255; } AString::~AString() { if (special == 255) r_ptr()->~RString(); } AString::AString(const MString& s) : AString(s.begin(), s.end()) { } AString::AString(XPair p) : AString(p.begin(), p.end()) { } AString::AString(const TString& t) : AString(XString(t)) { } AString::AString(const SString& s) : AString(XString(s)) { } AString::AString(ZString z) : AString(XString(z)) { } AString::AString(XString x) : AString() { if (const RString *r = x.base()) { if (&*r->begin() == &*x.begin() && &*r->end() == &*x.end()) { *this = *r; return; } } *this = AString(x.begin(), x.end()); } AString::AString(LString l) : AString(RString(l)) { } AString::iterator AString::begin() const { if (special == 255) return &*r_ptr()->begin(); else return data + 0; } AString::iterator AString::end() const { if (special == 255) return &*r_ptr()->end(); else return data + (255 - special); } const RString *AString::base() const { if (special == 255) return r_ptr(); else return nullptr; } const char *AString::c_str() const { return &*begin(); } const char *decay_for_printf(const AString& as) { return as.c_str(); } int do_vprint(AString& out, const char *fmt, va_list ap) { // TODO try with a fixed-size buffer first, then write // directory into the allocated output? int len; { va_list ap2; va_copy(ap2, ap); len = vsnprintf(nullptr, 0, fmt, ap2); va_end(ap2); } char buffer[len + 1]; vsnprintf(buffer, len + 1, fmt, ap); out = AString(buffer, buffer + len); return len; } } // namespace strings } // namespace tmwa