// // aegis - project change supervisor // Copyright (C) 2004-2006, 2008, 2014 Peter Miller // // 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 nstring::~nstring() { ref->validate(); str_free(ref); ref = NULL; } string_ty * nstring::get_empty_ref(void) { return str_from_c(""); } nstring::nstring() : ref(get_empty_ref()) { assert(ref->valid()); } static string_ty * quarantine(string_ty *s) { if (!s) return str_from_c(""); assert(s->str_references >= 1); return str_copy(s); } nstring::nstring(string_ty *a_ref) : ref(quarantine(a_ref)) { assert(ref->valid()); } static string_ty * quarantine(const char *text) { if (!text) text = ""; return str_from_c(text); } nstring::nstring(const char *text) : ref(quarantine(text)) { assert(ref->valid()); } static string_ty * quarantine(const char *text, size_t text_size) { if (!text) text_size = 0; return str_n_from_c(text, text_size); } nstring::nstring(const char *data, size_t data_size) : ref(quarantine(data, data_size)) { assert(ref->valid()); } nstring & nstring::operator=(const nstring &rhs) { if (this != &rhs) { // In case you haven't seen the swap() technique to // implement copy assignment before, here's what it does: // // 1) Create a temporary aegis_shared_ptr<> instance via the // copy constructor, thereby increasing the reference // count of the source object. // // 2) Swap the internal object pointers of *this and the // temporary aegis_shared_ptr<>. After this step, *this // already contains the new pointer, and the old pointer // is now managed by temp. // // 3) The destructor of temp is executed, thereby // unreferencing the old object pointer. // // This technique is described in Herb Sutter's "Exceptional // C++", and has a number of advantages over conventional // approaches: // // - Code reuse by calling the copy constructor. // - Strong exception safety for free. // - Self assignment is handled implicitly. // - Simplicity. // - It just works and is hard to get wrong; i.e. you can // use it without even thinking about it to implement // copy assignment where ever the object data is managed // indirectly via a pointer, which is very common. // nstring temp(rhs); swap(temp); assert(valid()); assert(rhs.valid()); } return *this; } nstring nstring::format(const char *fmt, ...) { va_list ap; va_start(ap, fmt); string_ty *tmp = str_vformat(fmt, ap); nstring result(tmp); va_end(ap); str_free(tmp); return result; } nstring nstring::vformat(const char *fmt, va_list ap) { string_ty *tmp = str_vformat(fmt, ap); nstring result(tmp); str_free(tmp); return result; } void nstring::swap(nstring &rhs) { string_ty *old = ref; ref = rhs.ref; rhs.ref = old; } nstring::nstring(const nstring &rhs) : ref(str_copy(rhs.ref)) { assert(ref->valid()); assert(rhs.ref->valid()); } // vim: set ts=8 sw=4 et :