datahash_util.cpp

Go to the documentation of this file.
00001 /*
00002  * datahash_util.cpp
00003  *
00004  * Copyright (C) 2003, 2008  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 datahash utilities.
00032  */
00033 
00034 // includes --------------------------------------------------------------------
00035 #include "datahash_util.h"      // always include our own header first
00036 
00037 #include "util/date.h"          // date utilities
00038 #include "util/parsing.h"       // parsing utilities
00039 
00040 #include "common/wave_ex.h"
00041 
00042 
00043 ////////////////////////////////////////////////////////////////////////////////
00044 //
00045 //      static helper methods
00046 //
00047 ////////////////////////////////////////////////////////////////////////////////
00048 
00049 static const hash_value_t *
00050 getSingleValue
00051 (
00052 IN const Datahash * h,
00053 IN const char * key,
00054 IN eDatahash_Flag flag,
00055 IN eHashDataType type
00056 )
00057 {
00058         ASSERT(h, "null");
00059         ASSERT(key, "null");
00060         ASSERT(eHashDataType_Invalid != type, "Bad type");
00061 
00062         int nValues = h->count(key);
00063         if (!nValues && (eDatahash_Optional & flag))
00064                 return NULL;    // not found
00065         ASSERT_THROW(1 == nValues,
00066             "Expected exactly 1 value for key='" << key << "', found " <<
00067             nValues << " instead");
00068 
00069         Datahash::iterator_t i;
00070         h->getIterator(key, i);
00071         const hash_value_t * phv = h->getNextElementUnsafe(i);
00072         ASSERT_THROW(phv, "No value found for key='" << key << "'");
00073         ASSERT_THROW(type == phv->type,
00074             "value at key='" << key << "' is not the proper type "
00075             << "(string vs hash)");
00076         return phv;
00077 }
00078 
00079 
00080 
00081 ////////////////////////////////////////////////////////////////////////////////
00082 //
00083 //      Datahash Utilities -- Public API
00084 //
00085 ////////////////////////////////////////////////////////////////////////////////
00086 
00087 const char *
00088 getString
00089 (
00090 IN const Datahash * h,
00091 IN const char * key,
00092 IN eDatahash_Flag flag
00093 )
00094 {
00095         ASSERT(h, "null");
00096         ASSERT(key, "null");
00097 
00098         const hash_value_t * phv =
00099             getSingleValue(h, key, flag, eHashDataType_String);
00100         if (!phv) {
00101                 return NULL;    // not there (only returns null if optional)
00102         }
00103         return phv->text.c_str();
00104 }
00105 
00106 
00107 
00108 const char *
00109 getOptionalString
00110 (
00111 IN const Datahash * h,
00112 IN const char * key,
00113 IN const char * default_value
00114 )
00115 {
00116         ASSERT(h, "null");
00117         ASSERT(key, "null");
00118         // ASSERT(default) -- we don't care!
00119 
00120         const char * val = getString(h, key, eDatahash_Optional);
00121         return val ? val : default_value;
00122 }
00123 
00124 
00125 
00126 long
00127 getLong
00128 (
00129 IN const Datahash * h,
00130 IN const char * key
00131 )
00132 {
00133         ASSERT(h, "null");
00134         ASSERT(key, "null");
00135 
00136         return atol(getString(h, key));
00137 }
00138 
00139 
00140 
00141 long
00142 getOptionalLong
00143 (
00144 IN const Datahash * h,
00145 IN const char * key,
00146 IN long default_value
00147 )
00148 {
00149         ASSERT(h, "null");
00150         ASSERT(key, "null");
00151 
00152         const char * val = getString(h, key, eDatahash_Optional);
00153         if (!val)
00154                 return default_value;
00155         return atol(val);
00156 }
00157 
00158 
00159 
00160 double
00161 getDouble
00162 (
00163 IN const Datahash * h,
00164 IN const char * key
00165 )
00166 {
00167         ASSERT(h, "null");
00168         ASSERT(key, "null");
00169 
00170         return atof(getString(h, key));
00171 }
00172 
00173 
00174 
00175 bool
00176 getBooleanValueFromString
00177 (
00178 IN const char * v
00179 )
00180 {
00181         ASSERT(v, "null");
00182 
00183         if (!strcasecmp(v, "true") ||
00184                 !strcasecmp(v, "t") ||
00185                 !strcasecmp(v, "1") ||
00186                 !strcasecmp(v, "yes")) {
00187                 // true or 1 or yes == true
00188                 return true;
00189         }
00190         if (!strcasecmp(v, "false") ||
00191                 !strcasecmp(v, "f") ||
00192                 !strcasecmp(v, "0") ||
00193                 !strcasecmp(v, "no")) {
00194                 return false;
00195         }
00196 
00197         // if we got here, we can't figure it out.  Throw
00198         {
00199                 WAVE_EX(wex);
00200                 wex << "Cannot determine true or false from value: " << v;
00201         }
00202 
00203         return false;
00204 }
00205 
00206 
00207 
00208 bool
00209 getBoolean
00210 (
00211 IN const Datahash * h,
00212 IN const char * key
00213 )
00214 {
00215         ASSERT(h, "null");
00216         ASSERT(key, "null");
00217 
00218         return getBooleanValueFromString(getString(h, key));
00219 }
00220 
00221 
00222 
00223 smart_ptr<Datahash>
00224 getSubhash
00225 (
00226 IN const Datahash * h,
00227 IN const char * key,
00228 IN eDatahash_Flag flag
00229 )
00230 {
00231         ASSERT(h, "null");
00232         ASSERT(key, "null");
00233 
00234         const hash_value_t * phv =
00235             getSingleValue(h, key, flag, eHashDataType_Hash);
00236         if (!phv) {
00237                 return NULL;    // not there (only returns NULL if optional)
00238         }
00239         return phv->hash;
00240 }
00241 
00242 
00243 
00244 void
00245 setTimestampAsDateString
00246 (
00247 IN Datahash * h,
00248 IN const char * key_name,
00249 IN long timestamp
00250 )
00251 {
00252         ASSERT(h, "null");
00253         ASSERT(key_name, "null");
00254 
00255         std::string display;
00256         getDateStringFromNetTime(timestamp, display);
00257 
00258         setValue(h, key_name, display);
00259 }
00260 
00261 
00262 
00263 long
00264 getTimestampFromDateString
00265 (
00266 IN const Datahash * h,
00267 IN const char * key
00268 )
00269 {
00270         ASSERT(h, "null");
00271         ASSERT(key, "null");
00272 
00273         std::string display = getString(h, key);
00274         return getNetTimeFromDateString(display.c_str());
00275 }
00276 
00277 
00278 
00279 smart_ptr<Datahash>
00280 getHashFromColonString
00281 (
00282 IN const char * s
00283 )
00284 {
00285         ASSERT(s, "null");
00286 
00287         smart_ptr<Datahash> hash = new Datahash;
00288         ASSERT(hash, "Failed to create empty datahash");
00289 
00290         // we assume the string is a whitespace-separated list of
00291         //  tokens, each token of the form <key>:<value>
00292 
00293         eParseBehavior behavior = (eParseBehavior)
00294             (eParse_RespectQuotes);
00295 
00296         while (*s) {
00297                 std::string token;
00298                 s = getNextTokenFromString(s, token, behavior);
00299                 if ("" == token) {
00300                         break;
00301                 }
00302 
00303                 int i = token.find(':', 0);
00304                 if ((int) std::string::npos == i) {
00305                         // no colon in this token?
00306                         DPRINTF("Warning: malformed token: '%s'",
00307                             token.c_str());
00308                         continue;
00309                 }
00310 
00311                 std::string key = token.substr(0, i);
00312                 std::string value = token.substr(i + 1);
00313 
00314 //              DPRINTF("'%s' ==> '%s' = '%s'",
00315 //                  token.c_str(), key.c_str(), value.c_str());
00316 
00317                 hash->insert(key, value);
00318         }
00319 
00320         return hash;
00321 }
00322 
00323 
00324 
00325 void
00326 getStringValues
00327 (
00328 IN const Datahash * hash,
00329 IN const char * key,
00330 OUT VecString& vec
00331 )
00332 {
00333         ASSERT(hash, "null");
00334         ASSERT(key, "null");
00335         vec.clear();
00336 
00337         Datahash::iterator_t i;
00338         hash->getIterator(key, i);
00339         while (const hash_value_t * phv = hash->getNextElementUnsafe(i)) {
00340                 if (eHashDataType_String != phv->type)
00341                         continue;
00342 
00343                 vec.push_back(phv->text);
00344         }
00345 }
00346 
00347