// -*- c-basic-offset: 4; related-file-name: "../include/click/straccum.hh" -*-
/*
* straccum.{cc,hh} -- build up strings with operator<<
* Eddie Kohler
*
* Copyright (c) 1999-2000 Massachusetts Institute of Technology
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, subject to the conditions
* listed in the Click LICENSE file. These conditions include: you must
* preserve this copyright notice, and you cannot mention the copyright
* holders in advertising related to the Software without their permission.
* The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This
* notice is a summary of the Click LICENSE file; the license in that file is
* legally binding.
*/
#include <click/config.h>
#include <click/straccum.hh>
#include <click/string.hh>
#include <click/glue.hh>
#include <click/confparse.hh>
#include <click/timestamp.hh>
#include <stdarg.h>
CLICK_DECLS
void
StringAccum::make_out_of_memory()
{
assert(_cap >= 0);
delete[] _s;
_s = reinterpret_cast<unsigned char *>(const_cast<char *>(String::out_of_memory_data()));
_cap = -1;
_len = 0;
}
bool
StringAccum::grow(int want)
{
// can't append to out-of-memory strings
if (_cap < 0)
return false;
int ncap = (_cap ? _cap * 2 : 128);
while (ncap <= want)
ncap *= 2;
unsigned char *n = new unsigned char[ncap];
if (!n) {
make_out_of_memory();
return false;
}
if (_s)
memcpy(n, _s, _cap);
delete[] _s;
_s = n;
_cap = ncap;
return true;
}
const char *
StringAccum::c_str()
{
if (_len < _cap || grow(_len))
_s[_len] = '\0';
return reinterpret_cast<char *>(_s);
}
String
StringAccum::take_string()
{
int len = length();
if (len) {
int capacity = _cap;
return String::claim_string(reinterpret_cast<char *>(take_bytes()), len, capacity);
} else if (out_of_memory())
return String::out_of_memory_string();
else
return String();
}
void
StringAccum::append_fill(int c, int len)
{
if (char *s = extend(len))
memset(s, c, len);
}
void
StringAccum::swap(StringAccum &o)
{
unsigned char *os = o._s;
int olen = o._len, ocap = o._cap;
o._s = _s;
o._len = _len, o._cap = _cap;
_s = os;
_len = olen, _cap = ocap;
}
StringAccum &
operator<<(StringAccum &sa, long i)
{
if (char *x = sa.reserve(24)) {
int len = sprintf(x, "%ld", i);
sa.forward(len);
}
return sa;
}
StringAccum &
operator<<(StringAccum &sa, unsigned long u)
{
if (char *x = sa.reserve(24)) {
int len = sprintf(x, "%lu", u);
sa.forward(len);
}
return sa;
}
#if HAVE_INT64_TYPES && !HAVE_INT64_IS_LONG
StringAccum &
operator<<(StringAccum &sa, int64_t q)
{
String qstr = cp_unparse_integer64(q, 10, false);
return sa << qstr;
}
StringAccum &
operator<<(StringAccum &sa, uint64_t q)
{
String qstr = cp_unparse_unsigned64(q, 10, false);
return sa << qstr;
}
#endif
#if defined(CLICK_USERLEVEL) || defined(CLICK_TOOL)
StringAccum &
operator<<(StringAccum &sa, double d)
{
if (char *x = sa.reserve(256)) {
int len = sprintf(x, "%.12g", d);
sa.forward(len);
}
return sa;
}
#endif
StringAccum &
operator<<(StringAccum &sa, void *v)
{
if (char *x = sa.reserve(30)) {
int len = sprintf(x, "%p", v);
sa.forward(len);
}
return sa;
}
StringAccum &
StringAccum::snprintf(int n, const char *format, ...)
{
va_list val;
va_start(val, format);
if (char *x = reserve(n + 1)) {
#if CLICK_LINUXMODULE || HAVE_VSNPRINTF
int len = vsnprintf(x, n + 1, format, val);
#else
int len = vsprintf(x, format, val);
assert(len <= n);
#endif
forward(len);
}
va_end(val);
return *this;
}
CLICK_ENDDECLS
syntax highlighted by Code2HTML, v. 0.9.1