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