fixed-buffer.h

Go to the documentation of this file.
00001 /*
00002  * fixed-buffer.h
00003  *
00004  * Copyright (C) 2009  Thomas A. Vaughan
00005  * All rights reserved.
00006  *
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted provided that the following conditions are met:
00010  *     * Redistributions of source code must retain the above copyright
00011  *       notice, this list of conditions and the following disclaimer.
00012  *     * Redistributions in binary form must reproduce the above copyright
00013  *       notice, this list of conditions and the following disclaimer in the
00014  *       documentation and/or other materials provided with the distribution.
00015  *     * Neither the name of the <organization> nor the
00016  *       names of its contributors may be used to endorse or promote products
00017  *       derived from this software without specific prior written permission.
00018  *
00019  * THIS SOFTWARE IS PROVIDED BY THOMAS A. VAUGHAN ''AS IS'' AND ANY
00020  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00021  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00022  * DISCLAIMED. IN NO EVENT SHALL THOMAS A. VAUGHAN BE LIABLE FOR ANY
00023  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00024  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00025  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00026  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00027  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00028  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029  *
00030  *
00031  * Templates to support fixed-size string buffers.
00032  */
00033 
00034 #ifndef WAVEPACKET_UTIL_FIXED_BUFFER_H__
00035 #define WAVEPACKET_UTIL_FIXED_BUFFER_H__
00036 
00037 // includes --------------------------------------------------------------------
00038 #include "common/common.h"
00039 #include "common/wave_ex.h"
00040 
00041 
00042 /// \ingroup util
00043 /*@{*/
00044 
00045 
00046 
00047 /// Template that supports strings of a fixed buffer size.
00048 /// This class is most useful when you want to add a string to a struct or
00049 /// class with a set size, and don't want to deal with memory allocations
00050 /// using std::string.
00051 ///
00052 /// You have to provide two classes to use a FixedBuffer template:
00053 ///  - \b Sizer This class contains the actual buffer, and a static
00054 ///             method named getBufferSize() which returns the full
00055 ///             buffer size (including null terminator).
00056 ///  - \b Validator This class contains a single static method, isValid().
00057 ///             This is used to validate each character during string
00058 ///             assignments.
00059 ///
00060 /// Some example Sizers and Validators are included in this file.
00061 template <class Sizer, class Validator>
00062 class FixedBuffer {
00063 public:
00064         // typedef
00065         typedef FixedBuffer<Sizer, Validator> buff_type_t;
00066 
00067         // constructors
00068         FixedBuffer(void) throw() { this->clear(); }
00069         FixedBuffer(IN const buff_type_t& inbuf) throw() { m_t = inbuf.m_t; }
00070         FixedBuffer(IN const char * input) {
00071                         this->clear();
00072                         this->set(input); 
00073                 }
00074 
00075         // manipulators and accessors
00076         void clear(void) throw() {
00077                         m_t.buffer[0] = 0; 
00078                         int Nmax = Sizer::getBufferSize() - 1;
00079                         m_t.buffer[Nmax] = 0;   // also put zero at end!
00080                 }
00081         bool isEmpty(void) const throw() { return !m_t.buffer[0]; }
00082         bool operator ! () const throw() { return this->isEmpty(); }
00083         operator const char * () const throw() { return m_t.buffer; }
00084         operator bool () const throw() { return !this->isEmpty(); }
00085 
00086         /// set() will take an arbitrary string, and assign it to the fixed
00087         ///  buffer.
00088         /// There are two passes over the input string: once to validate, and
00089         ///  once to copy.  This is slightly inefficient, but guarantees that
00090         ///  the fixed buffer string is never corrupted by bad input.
00091         /// An input string is considered invalid if it is longer than the
00092         ///  fixed buffer can hold, or if it contains invalid characters.
00093         /// If the input is invalid, this routine will throw an exception.
00094         void set(IN const char * val) {
00095                         ASSERT(val, "null");
00096 
00097                         const char * q = val;   // source
00098                         int Nmax = Sizer::getBufferSize() - 1;
00099 
00100                         // first pass: check validity of input
00101                         for (int i = 0; i < Nmax; ++i, ++q) {
00102                                 if (!*q)
00103                                         break;          // end of input
00104                                 if (!Validator::isValid(*q)) {
00105                                         WAVE_EX(wex);
00106                                         wex << "input string contains ";
00107                                         wex << "invalid characters: '";
00108                                         wex << val << "'";
00109                                 }
00110                         }
00111                         if (*q) {
00112                                 WAVE_EX(wex);
00113                                 wex << "input string too long! '" << val << "'";
00114                         }
00115 
00116                         // second pass: input is valid, so copy
00117                         char * p = m_t.buffer;  // destination
00118                         q = val;                // source (reset)
00119                         for (; *q; ++p, ++q) {
00120                                 *p = *q;
00121                         }
00122                         *p = 0;         // force null-termination
00123                 }
00124  
00125 private:
00126         Sizer   m_t;
00127 };
00128 
00129 
00130 
00131 /// a validator that allows anything
00132 class NullValidator {
00133 public:
00134         static bool isValid(IN char a) throw() { return true; }
00135 };
00136 
00137 
00138 
00139 /// a validator that allows alphanumerics only
00140 class AlphanumericValidator {
00141 public:
00142         static bool isValid(IN char a) throw() {
00143                         return ((a >= 'a' && a <= 'z') ||
00144                                 (a >= 'A' && a <= 'Z') ||
00145                                 (a >= '0' && a <= '9'));
00146                 }
00147 };
00148 
00149 
00150 
00151 /// a validator that allows a subset of characters thought
00152 /// to be useful in filepaths.  Note that this is somewhat
00153 /// restrictive.
00154 class CommonFileValidator {
00155 public:
00156         static bool isValid(IN char a) throw() {
00157                         return ((a >= 'a' && a <= 'z') ||
00158                                 (a >= 'A' && a <= 'Z') ||
00159                                 (a >= '0' && a <= '9') ||
00160                                 '/' == a || '.' == a ||
00161                                 '-' == a || '_' == a);
00162                 }
00163 };
00164 
00165 
00166 
00167 /// an example sizer that allows strings of up to 31 characters
00168 /// (so the buffer itself is 32 characters)
00169 class ThirtyTwoCharacterSizer {
00170 public:
00171         static int getBufferSize(void) throw() { return 32; }
00172         char buffer[32];
00173 };
00174 
00175 
00176 
00177 #endif  // WAVEPACKET_UTIL_FIXED_BUFFER_H__
00178