//
// 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 :