vbase.cc

00001 //
00002 // \file        vbase.cc
00003 //              vformat support routines in base class
00004 //
00005 
00006 /*
00007     Copyright (C) 2006-2011, Net Direct Inc. (http://www.netdirect.ca/)
00008 
00009     This program is free software; you can redistribute it and/or modify
00010     it under the terms of the GNU General Public License as published by
00011     the Free Software Foundation; either version 2 of the License, or
00012     (at your option) any later version.
00013 
00014     This program is distributed in the hope that it will be useful,
00015     but WITHOUT ANY WARRANTY; without even the implied warranty of
00016     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00017 
00018     See the GNU General Public License in the COPYING file at the
00019     root directory of this project for more details.
00020 */
00021 
00022 #include "vbase.h"
00023 //#include "trace.h"
00024 #include "vformat.h"            // comes from opensync, but not a public header yet
00025 #include "tzwrapper.h"
00026 #include <stdio.h>
00027 #include <stdarg.h>
00028 #include <stdint.h>
00029 #include <string.h>
00030 #include <glib.h>
00031 #include <sstream>
00032 
00033 using namespace std;
00034 
00035 namespace Barry { namespace Sync {
00036 
00037 //////////////////////////////////////////////////////////////////////////////
00038 // vTimeConverter
00039 
00040 std::string vTimeConverter::unix2vtime(const time_t *timestamp)
00041 {
00042         struct tm split;
00043         if( !gmtime_r(timestamp, &split) ) {
00044                 ostringstream oss;
00045                 oss << "gmtime_r() failed on time_t of ";
00046                 if( timestamp )
00047                         oss << *timestamp;
00048                 else
00049                         oss << "(null pointer)";
00050                 throw Barry::ConvertError(oss.str());
00051         }
00052 
00053         return tm_to_iso(&split, true);
00054 }
00055 
00056 time_t vTimeConverter::vtime2unix(const char *vtime)
00057 {
00058         return TzWrapper::iso_mktime(vtime);
00059 }
00060 
00061 //
00062 // The following implementation is taken from opensync's
00063 // opensync_time.c implementation with the following copyright
00064 // notices at the top as of July 2010:
00065 //
00066 //  * Copyright (C) 2004-2005  Armin Bauer <armin.bauer@opensync.org>
00067 //  * Copyright (C) 2006-2008 Daniel Gollub <gollub@b1-systems.de>
00068 //  * Copyright (C) 2007 Chris Frey <cdfrey@netdirect.ca>
00069 //
00070 // License: LGPL 2.1 or later
00071 //
00072 int vTimeConverter::alarmduration2sec(const char *alarm)
00073 {
00074         int i, secs, digits = 0;
00075         int is_digit = 0;
00076         int sign = 1;   // when ical stamp doesn't start with '-' => seconds after event
00077         int days = 0, weeks = 0, hours = 0, minutes = 0, seconds = 0;
00078         int len = strlen(alarm);
00079 
00080         for (i=0; i < len; i++) {
00081 
00082                 switch (alarm[i]) {
00083                 case '-':
00084                         sign = -1; // seconds before event - change the sign
00085                 case 'P':
00086                 case 'T':
00087                         is_digit = 0;
00088                         break;
00089                 case 'W':
00090                         is_digit = 0;
00091                         weeks = digits;
00092                         break;
00093                 case 'D':
00094                         is_digit = 0;
00095                         days = digits;
00096                         break;
00097                 case 'H':
00098                         is_digit = 0;
00099                         hours = digits;
00100                         break;
00101                 case 'M':
00102                         is_digit = 0;
00103                         minutes = digits;
00104                         break;
00105                 case 'S':
00106                         is_digit = 0;
00107                         seconds = digits;
00108                         break;
00109                 case '0':
00110                 case '1':
00111                 case '2':
00112                 case '3':
00113                 case '4':
00114                 case '5':
00115                 case '6':
00116                 case '7':
00117                 case '8':
00118                 case '9':
00119                         if (is_digit)
00120                                 break;
00121 
00122                         if (sscanf((char*)(alarm+i),"%d",&digits) == EOF)
00123                                 return -1;
00124 
00125                         is_digit = 1;
00126                         break;
00127                 }
00128         }
00129 
00130         secs = (weeks * 7 * 24 * 3600) + (days * 24 * 3600) + (hours * 3600) + (minutes * 60) + seconds;
00131 
00132         secs = secs * sign;     // change sign if the alarm is in seconds before event (leading '-')
00133 
00134         return secs;
00135 
00136 }
00137 
00138 
00139 //////////////////////////////////////////////////////////////////////////////
00140 // vAttr
00141 
00142 std::string vAttr::GetName()
00143 {
00144         std::string ret;
00145 
00146         if( !m_attr )
00147                 return ret;
00148 
00149         const char *name = b_vformat_attribute_get_name(m_attr);
00150         if( name )
00151                 ret = name;
00152         return ret;
00153 }
00154 
00155 std::string vAttr::GetValue(int nth)
00156 {
00157         std::string ret;
00158         const char *value = 0;
00159 
00160         if( m_attr ) {
00161                 if( b_vformat_attribute_is_single_valued(m_attr) ) {
00162                         if( nth == 0 )
00163                                 value = b_vformat_attribute_get_value(m_attr);
00164                 }
00165                 else {
00166                         value = b_vformat_attribute_get_nth_value(m_attr, nth);
00167                 }
00168         }
00169 
00170         if( value )
00171                 ret = value;
00172 
00173         return ret;
00174 }
00175 
00176 std::string vAttr::GetDecodedValue()
00177 {
00178         std::string ret;
00179         GString *value = NULL;
00180 
00181         if( m_attr ) {
00182                 if( b_vformat_attribute_is_single_valued(m_attr) ) {
00183                         value = b_vformat_attribute_get_value_decoded(m_attr);
00184                 }
00185         }
00186 
00187         if( value )
00188                 ret.assign(value->str, value->len);
00189 
00190         return ret;
00191 }
00192 
00193 std::string vAttr::GetParam(const char *name, int nth)
00194 {
00195         std::string ret;
00196 
00197         if( !m_attr )
00198                 return ret;
00199 
00200         b_VFormatParam *param = b_vformat_attribute_find_param(m_attr, name, 0);
00201         if( !param )
00202                 return ret;
00203 
00204         const char *value = b_vformat_attribute_param_get_nth_value(param, nth);
00205         if( value )
00206                 ret = value;
00207 
00208         return ret;
00209 }
00210 
00211 /// Does an exhaustive search through the attribute, searching for all
00212 /// param values that exist for the given name, and returns all values
00213 /// in a comma delimited string.
00214 std::string vAttr::GetAllParams(const char *name)
00215 {
00216         std::string ret;
00217 
00218         if( !m_attr )
00219                 return ret;
00220 
00221         b_VFormatParam *param = 0;
00222         for( int level = 0;
00223              (param = b_vformat_attribute_find_param(m_attr, name, level));
00224              level++ )
00225         {
00226                 const char *value = 0;
00227                 for( int nth = 0;
00228                      (value = b_vformat_attribute_param_get_nth_value(param, nth));
00229                      nth++ )
00230                 {
00231                         if( ret.size() )
00232                                 ret += ",";
00233                         ret += value;
00234                 }
00235         }
00236 
00237         return ret;
00238 }
00239 
00240 
00241 //////////////////////////////////////////////////////////////////////////////
00242 // vCalendar
00243 
00244 vBase::vBase()
00245         : m_format(b_vformat_new())
00246 {
00247 }
00248 
00249 vBase::vBase(b_VFormat *format)
00250         : m_format(format)
00251 {
00252         if( !format )
00253                 throw Barry::Error("Cannot construct vBase with null format");
00254 }
00255 
00256 vBase::~vBase()
00257 {
00258         if( m_format ) {
00259                 b_vformat_free(m_format);
00260                 m_format = 0;
00261         }
00262 }
00263 
00264 void vBase::SetFormat(b_VFormat *format)
00265 {
00266         if( !format )
00267                 throw Barry::Error("Cannot set vBase with null format");
00268 
00269         if( m_format ) {
00270                 b_vformat_free(m_format);
00271                 m_format = 0;
00272         }
00273         m_format = format;
00274 }
00275 
00276 void vBase::Clear()
00277 {
00278         if( m_format ) {
00279                 b_vformat_free(m_format);
00280                 m_format = b_vformat_new();
00281         }
00282 }
00283 
00284 vAttrPtr vBase::NewAttr(const char *name)
00285 {
00286 //      Trace trace("vBase::NewAttr");
00287 
00288 //      trace.logf("creating valueless attr: %s", name);
00289 
00290         vAttrPtr attr(b_vformat_attribute_new(NULL, name));
00291         if( !attr.Get() )
00292                 throw Barry::ConvertError("resource error allocating vformat attribute");
00293         return attr;
00294 }
00295 
00296 vAttrPtr vBase::NewAttr(const char *name, const char *value)
00297 {
00298 //      Trace trace("vBase::NewAttr");
00299 
00300 /*
00301 some vCard values are positional (like name), so blank should be allowed...
00302 
00303         if( strlen(value) == 0 ) {
00304                 trace.logf("attribute '%s' contains no data, skipping", name);
00305                 return vAttrPtr();
00306         }
00307 */
00308 
00309 //      trace.logf("creating attr: %s, %s", name, value);
00310 
00311         vAttrPtr attr(b_vformat_attribute_new(NULL, name));
00312         if( !attr.Get() )
00313                 throw ConvertError("resource error allocating vformat attribute");
00314 
00315         b_vformat_attribute_add_value(attr.Get(), value);
00316         return attr;
00317 }
00318 
00319 void vBase::AddAttr(vAttrPtr attr)
00320 {
00321 //      Trace trace("vBase::AddAttr");
00322 
00323         if( !attr.Get() ) {
00324 //              trace.log("attribute contains no data, skipping");
00325                 return;
00326         }
00327 
00328         b_vformat_add_attribute(m_format, attr.Extract());
00329 }
00330 
00331 void vBase::AddValue(vAttrPtr &attr, const char *value)
00332 {
00333 //      Trace trace("vBase::AddValue");
00334         if( !attr.Get() ) {
00335 //              trace.log("attribute pointer contains no data, skipping");
00336                 return;
00337         }
00338 /*
00339         if( strlen(value) == 0 ) {
00340                 trace.log("attribute value is empty, skipping");
00341                 return;
00342         }
00343 */
00344         b_vformat_attribute_add_value(attr.Get(), value);
00345 }
00346 
00347 void vBase::AddEncodedValue(vAttrPtr &attr, b_VFormatEncoding encoding, const char *value, int len)
00348 {
00349 //      Trace trace("vBase::AddValue");
00350         if( !attr.Get() ) {
00351 //              trace.log("attribute pointer contains no data, skipping");
00352                 return;
00353         }
00354 
00355         attr.Get()->encoding = encoding;
00356         attr.Get()->encoding_set = TRUE;
00357 
00358         b_vformat_attribute_add_value_decoded(attr.Get(), value, len);
00359 }
00360 
00361 void vBase::AddParam(vAttrPtr &attr, const char *name, const char *value)
00362 {
00363 //      Trace trace("vBase::AddParam");
00364 
00365         if( !attr.Get() ) {
00366 //              trace.log("attribute pointer contains no data, skipping");
00367                 return;
00368         }
00369 /*
00370         if( strlen(value) == 0 ) {
00371                 trace.log("parameter value is empty, skipping");
00372                 return;
00373         }
00374 */
00375 
00376         b_VFormatParam *pParam = b_vformat_attribute_param_new(name);
00377         b_vformat_attribute_param_add_value(pParam, value);
00378         b_vformat_attribute_add_param(attr.Get(), pParam);
00379 }
00380 
00381 std::string vBase::GetAttr(const char *attrname, const char *block)
00382 {
00383 //      Trace trace("vBase::GetAttr");
00384 //      trace.logf("getting attr: %s", attrname);
00385 
00386         std::string ret;
00387         const char *value = 0;
00388 
00389         bool needs_freeing = false;
00390 
00391         b_VFormatAttribute *attr = b_vformat_find_attribute(m_format, attrname, 0, block);
00392         if( attr ) {
00393                 if( b_vformat_attribute_is_single_valued(attr) ) {
00394                         value = b_vformat_attribute_get_value(attr);
00395                         needs_freeing = true;
00396                 }
00397                 else {
00398                         // FIXME, this is hardcoded
00399                         value = b_vformat_attribute_get_nth_value(attr, 0);
00400                 }
00401         }
00402 
00403         if( value )
00404                 ret = value;
00405 
00406         if( needs_freeing )
00407                 g_free((char *)value);
00408 
00409 //      trace.logf("attr value: %s", ret.c_str());
00410         return ret;
00411 }
00412 
00413 std::vector<std::string> vBase::GetValueVector(const char *attrname, const char *block)
00414 {
00415 //      Trace trace("vBase::GetValueVector");
00416 //      trace.logf("getting value vector for: %s", attrname);
00417 
00418         std::vector<std::string> ret;
00419         const char *value = 0;
00420         bool needs_freeing = false;
00421 
00422         b_VFormatAttribute *attr = b_vformat_find_attribute(m_format, attrname, 0, block);
00423         if( attr ) {
00424                 if( b_vformat_attribute_is_single_valued(attr) ) {
00425                         value = b_vformat_attribute_get_value(attr);
00426                         needs_freeing = true;
00427                 } else {
00428                         // nasty, but avoids tweaking vformat.
00429                         int idx = 0;
00430                         do {
00431                                 value = b_vformat_attribute_get_nth_value(attr, idx++);
00432                                 if( value ) {
00433                                         ret.push_back(value);
00434                                 }
00435                         } while( value );
00436                 }
00437         }
00438 
00439         if( needs_freeing )
00440                 g_free((char *)value);
00441 
00442         return ret;
00443 }
00444 
00445 vAttr vBase::GetAttrObj(const char *attrname, int nth, const char *block)
00446 {
00447 //      Trace trace("vBase::GetAttrObj");
00448 //      trace.logf("getting attr: %s", attrname);
00449 
00450         return vAttr(b_vformat_find_attribute(m_format, attrname, nth, block));
00451 }
00452 
00453 std::vector<std::string> vBase::Tokenize(const std::string& str, const char delim)
00454 {
00455         std::vector<std::string> tokens;
00456         std::string::size_type delimPos = 0, tokenPos = 0, pos = 0;
00457 
00458         if( str.length() < 1 ) {
00459                 return tokens;
00460         }
00461 
00462         while( 1 ) {
00463                 delimPos = str.find_first_of(delim, pos);
00464                 tokenPos = str.find_first_not_of(delim, pos);
00465 
00466                 if( std::string::npos != delimPos ) {
00467                         if( std::string::npos != tokenPos ) {
00468                                 if( tokenPos < delimPos ) {
00469                                         tokens.push_back(str.substr(pos, delimPos-pos));
00470                                 } else {
00471                                         tokens.push_back("");
00472                                 }
00473                         } else {
00474                                 tokens.push_back("");
00475                         }
00476                         pos = delimPos + 1;
00477                 } else {
00478                         if( std::string::npos != tokenPos ){
00479                                 tokens.push_back(str.substr(pos));
00480                         } else {
00481                                 tokens.push_back("");
00482                         }
00483                         break;
00484                 }
00485         }
00486         return tokens;
00487 }
00488 
00489 std::string vBase::ToStringList(const std::vector<std::string> &list, const char delim)
00490 {
00491         std::string str;
00492         for( unsigned int idx = 0; idx < list.size(); idx++ ) {
00493                 if( idx ) {
00494                         str += delim;
00495                 }
00496                 str += list[idx];
00497         }
00498         return str;
00499 }
00500 
00501 }} // namespace Barry::Sync
00502 

Generated on Tue Mar 1 17:50:16 2011 for Barry by  doxygen 1.5.6