datahash.cpp

Go to the documentation of this file.
00001 /*
00002  * datahash.cpp
00003  *
00004  * Copyright (C) 2003, 2008, 2010 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  * Implementation of the recursive data hash.
00032  */
00033 
00034 // includes --------------------------------------------------------------------
00035 #include "datahash.h"           // always include our own header first
00036 
00037 #include "common/wave_ex.h"
00038 #include "util/parsing.h"
00039 
00040 
00041 static const int s_maxHashKeyLength             = 32;
00042 
00043 
00044 ////////////////////////////////////////////////////////////////////////////////
00045 //
00046 //      static helper methods
00047 //
00048 ////////////////////////////////////////////////////////////////////////////////
00049 
00050 static bool
00051 isValidHashKeyCharacter
00052 (
00053 IN char a,
00054 IN bool isFirstCharacter
00055 )
00056 throw()
00057 {
00058         // must be single byte character!
00059         if (!isSingleByteUTF8Character(a))
00060                 return false;
00061 
00062         // any alphabetic character a-zA-Z is fine
00063         if (a >= 'a' && a <= 'z')
00064                 return true;
00065         if (a >= 'A' && a <= 'Z')
00066                 return true;
00067 
00068         // first character must be alphabetic
00069         if (isFirstCharacter)
00070                 return false;
00071 
00072         // later characters can also be numeric
00073         if (a >= '0' && a <= '9')
00074                 return true;
00075 
00076         // not alphanumeric!
00077         return false;
00078 }
00079 
00080 
00081 
00082 ////////////////////////////////////////////////////////////////////////////////
00083 //
00084 //      hash_value_t methods
00085 //
00086 ////////////////////////////////////////////////////////////////////////////////
00087 
00088 hash_value_t::hash_value_t
00089 (
00090 IN const char * txt
00091 )
00092 {
00093         // ASSERT(txt) -- we don't care
00094         type = eHashDataType_String;
00095         text = (txt) ? txt : "";
00096 }
00097 
00098 
00099 
00100 hash_value_t::hash_value_t
00101 (
00102 IN const std::string& s
00103 )
00104 {
00105         type = eHashDataType_String;
00106         text = s;
00107 }
00108 
00109 
00110 
00111 hash_value_t::hash_value_t
00112 (
00113 IN smart_ptr<Datahash>& h
00114 )
00115 {
00116         // ASSERT(h) -- we don't care
00117         type = eHashDataType_Hash;
00118         hash = h;
00119 }
00120 
00121 
00122 
00123 void
00124 hash_value_t::clear
00125 (
00126 void
00127 )
00128 throw()
00129 {
00130         type = eHashDataType_Invalid;
00131         text.clear();
00132         hash = NULL;
00133 }
00134 
00135 
00136 
00137 ////////////////////////////////////////////////////////////////////////////////
00138 //
00139 //      public API
00140 //
00141 ////////////////////////////////////////////////////////////////////////////////
00142 
00143 bool
00144 isValidHashKeyName
00145 (
00146 IN const char * key_name
00147 )
00148 throw()
00149 {
00150         ASSERT(key_name, "null");
00151 
00152         // Why so restrictive?  Mainly because it is best to ensure that
00153         //   key names can easily be put into URLs, etc. without encoding.
00154         //   Also, keys could potentially be used to generate code (variables
00155         //   that have the same name).
00156         // This imposes a lot of restrictions on the key names but being
00157         //   very restrictive at first and perhaps relaxing the restrictions
00158         //   later is much better (more feasible) than the reverse.
00159 
00160         // Why enforce length?  Partly to catch garbage, but mainly because
00161         //   very long names are probably an indication that someone is
00162         //   encoding structure into the key names instead of using the hash.
00163 
00164         const char * p = key_name;
00165         for (; *p; ++p) {
00166                 if (!isValidHashKeyCharacter(*p, p == key_name))
00167                         return false;
00168 
00169                 // too long?
00170                 if (p - key_name > s_maxHashKeyLength) {
00171                         return false;
00172                 }
00173         }
00174 
00175         return true;
00176 }
00177 
00178 
00179 
00180 void
00181 validateHashKeyName
00182 (
00183 IN const char * key_name
00184 )
00185 {
00186         ASSERT(key_name, "null");
00187         if (!isValidHashKeyName(key_name)) {
00188                 WAVE_EX(wex);
00189                 wex << "Invalid data hash key name: '" << key_name << "'\n";
00190                 wex << "Only ASCII alphanumeric characters are allowed.\n";
00191                 wex << "The first character must be alphabetic.\n";
00192                 wex << "The full key must be less than ";
00193                 wex << s_maxHashKeyLength << " characters in length.";
00194         }
00195 }
00196