StringBuffer.cc

Go to the documentation of this file.
00001 /*
00002  * IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. By
00003  * downloading, copying, installing or using the software you agree to
00004  * this license. If you do not agree to this license, do not download,
00005  * install, copy or use the software.
00006  * 
00007  * Intel Open Source License 
00008  * 
00009  * Copyright (c) 2004 Intel Corporation. All rights reserved. 
00010  * 
00011  * Redistribution and use in source and binary forms, with or without
00012  * modification, are permitted provided that the following conditions are
00013  * met:
00014  * 
00015  *   Redistributions of source code must retain the above copyright
00016  *   notice, this list of conditions and the following disclaimer.
00017  * 
00018  *   Redistributions in binary form must reproduce the above copyright
00019  *   notice, this list of conditions and the following disclaimer in the
00020  *   documentation and/or other materials provided with the distribution.
00021  * 
00022  *   Neither the name of the Intel Corporation nor the names of its
00023  *   contributors may be used to endorse or promote products derived from
00024  *   this software without specific prior written permission.
00025  *  
00026  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00027  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00028  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00029  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE INTEL OR
00030  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00031  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00032  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00033  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00034  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00035  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00036  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00037  */
00038 
00039 #include <stdlib.h>
00040 
00041 #include "StringBuffer.h"
00042 #include "StringUtils.h"
00043 
00044 #include "ExpandableBuffer.h"
00045 #include "io/IOClient.h"
00046 
00047 namespace oasys {
00048 
00049 StringBuffer::StringBuffer(size_t initsz, const char* initstr)
00050     : buf_(0), own_buf_(true)
00051 {
00052     buf_ = new ExpandableBuffer();
00053     ASSERT(buf_ != 0);
00054 
00055     ASSERT(initsz != 0);
00056     buf_->reserve(initsz);
00057 
00058     if (initstr) {
00059         append(initstr);
00060     }
00061 }
00062     
00063 StringBuffer::StringBuffer(const char* fmt, ...)
00064     : buf_(0), own_buf_(true)
00065 {
00066     buf_ = new ExpandableBuffer();
00067     ASSERT(buf_);
00068     buf_->reserve(256);
00069 
00070     if (fmt != 0) 
00071     {
00072         va_list ap;
00073         va_start(ap, fmt);
00074         vappendf(fmt, ap);
00075         va_end(ap);
00076     }
00077 }
00078 
00079 StringBuffer::StringBuffer(ExpandableBuffer* buffer, bool own_buf)
00080     : buf_(buffer), own_buf_(own_buf)
00081 {
00082     ASSERT(buf_ != 0);
00083     buf_->reserve(256);
00084 }
00085 
00086 StringBuffer::~StringBuffer()
00087 {
00088     if (own_buf_)
00089         delete_z(buf_);
00090 }
00091 
00092 const char*
00093 StringBuffer::c_str() const
00094 {
00095     // we make sure there's a null terminator but don't bump up len_
00096     // to count it, just like std::string
00097     if (buf_->len() == 0 || (*buf_->at(buf_->len() - 1) != '\0'))
00098     {
00099         if (buf_->nfree() == 0) {
00100             buf_->reserve(buf_->len() + 1);
00101         }
00102         
00103         *buf_->end() = '\0';
00104     }
00105     
00106     return data();
00107 }
00108 
00109 size_t
00110 StringBuffer::append(const char* str, size_t len)
00111 {
00112     if (len == 0) {
00113         len = strlen(str);
00114     }
00115     
00116     // len is not past the end of str
00117     ASSERT(len <= strlen(str));
00118 
00119     buf_->reserve(buf_->len() + len);
00120     memcpy(buf_->end(), str, len);
00121     buf_->set_len(buf_->len() + len);
00122     
00123     return len;
00124 }
00125 
00126 size_t
00127 StringBuffer::append(char c)
00128 {
00129     buf_->reserve(buf_->len() + 1);
00130     *buf_->end() = c;
00131     buf_->set_len(buf_->len() + 1);
00132 
00133     return 1;
00134 }
00135 
00136 size_t
00137 StringBuffer::append_int(u_int32_t val, int base)
00138 {
00139     char tmp[16];
00140     size_t len = fast_ultoa(val, base, &tmp[15]);
00141 
00142     ASSERT(len < 16);
00143     
00144     buf_->reserve(buf_->len() + len);
00145     memcpy(buf_->end(), &tmp[16 - len], len);
00146     buf_->set_len(buf_->len() + len);
00147 
00148     return len;
00149 }
00150 
00151 size_t
00152 StringBuffer::vappendf(const char* fmt, va_list ap)
00153 {
00154     if (buf_->nfree() == 0) {
00155         ASSERT(buf_->buf_len() != 0);
00156         buf_->reserve(buf_->buf_len() * 2);
00157     }
00158     
00159     int ret = vsnprintf(buf_->end(), buf_->nfree(), fmt, ap);
00160     
00161     if (ret == -1)
00162     {
00163         // Retarded glibc implementation in Fedora Core 1. From the
00164         // man pages:
00165         //
00166         // The glibc implementation of the functions snprintf and
00167         // vsnprintf conforms to the C99 standard, i.e., behaves as
00168         // described above, since glibc version 2.1. Until glibc 2.0.6
00169         // they would return -1 when the output was truncated.
00170         do {
00171             buf_->reserve(buf_->buf_len() * 2);
00172             ret = vsnprintf(buf_->end(), buf_->nfree(), fmt, ap);
00173         } while(ret == -1);
00174         
00175         // we should be safe now, either the string has been written
00176         // or we write it again below
00177     }
00178 
00179     if (ret >= buf_->nfree())
00180     {
00181         buf_->reserve(std::max(buf_->len() + ret + 1,
00182                                buf_->buf_len() * 2));
00183         buf_->reserve(buf_->len() + ret + 1);
00184         ret = vsnprintf(buf_->end(), buf_->nfree(), fmt, ap);
00185         ASSERT(ret > 0);
00186         ASSERT(ret < buf_->nfree()); // ret doesn't include null char
00187     }
00188     
00189     ASSERT(ret >= 0);
00190     buf_->set_len(buf_->len() + ret);
00191     ASSERT(*buf_->end() == '\0');
00192         
00193     return ret;
00194 }
00195 
00196 size_t
00197 StringBuffer::appendf(const char* fmt, ...)
00198 {
00199     va_list ap;
00200     va_start(ap, fmt);
00201     size_t ret = vappendf(fmt, ap);
00202     va_end(ap);
00203     return ret;
00204 }
00205 
00206 } // namespace oasys

Generated on Fri Dec 22 14:48:00 2006 for DTN Reference Implementation by  doxygen 1.5.1