vbase.cc

00001 //
00002 // \file        vbase.cc
00003 //              vformat support routines in base class
00004 //
00005 
00006 /*
00007     Copyright (C) 2006-2010, 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(0)
00246 {
00247 }
00248 
00249 vBase::~vBase()
00250 {
00251         if( m_format ) {
00252                 b_vformat_free(m_format);
00253                 m_format = 0;
00254         }
00255 }
00256 
00257 void vBase::SetFormat(b_VFormat *format)
00258 {
00259         if( m_format ) {
00260                 b_vformat_free(m_format);
00261                 m_format = 0;
00262         }
00263         m_format = format;
00264 }
00265 
00266 void vBase::Clear()
00267 {
00268         if( m_format ) {
00269                 b_vformat_free(m_format);
00270                 m_format = 0;
00271         }
00272 }
00273 
00274 vAttrPtr vBase::NewAttr(const char *name)
00275 {
00276 //      Trace trace("vBase::NewAttr");
00277 
00278 //      trace.logf("creating valueless attr: %s", name);
00279 
00280         vAttrPtr attr(b_vformat_attribute_new(NULL, name));
00281         if( !attr.Get() )
00282                 throw Barry::ConvertError("resource error allocating vformat attribute");
00283         return attr;
00284 }
00285 
00286 vAttrPtr vBase::NewAttr(const char *name, const char *value)
00287 {
00288 //      Trace trace("vBase::NewAttr");
00289 
00290 /*
00291 some vCard values are positional (like name), so blank should be allowed...
00292 
00293         if( strlen(value) == 0 ) {
00294                 trace.logf("attribute '%s' contains no data, skipping", name);
00295                 return vAttrPtr();
00296         }
00297 */
00298 
00299 //      trace.logf("creating attr: %s, %s", name, value);
00300 
00301         vAttrPtr attr(b_vformat_attribute_new(NULL, name));
00302         if( !attr.Get() )
00303                 throw ConvertError("resource error allocating vformat attribute");
00304 
00305         b_vformat_attribute_add_value(attr.Get(), value);
00306         return attr;
00307 }
00308 
00309 void vBase::AddAttr(vAttrPtr attr)
00310 {
00311 //      Trace trace("vBase::AddAttr");
00312 
00313         if( !attr.Get() ) {
00314 //              trace.log("attribute contains no data, skipping");
00315                 return;
00316         }
00317 
00318         b_vformat_add_attribute(m_format, attr.Extract());
00319 }
00320 
00321 void vBase::AddValue(vAttrPtr &attr, const char *value)
00322 {
00323 //      Trace trace("vBase::AddValue");
00324         if( !attr.Get() ) {
00325 //              trace.log("attribute pointer contains no data, skipping");
00326                 return;
00327         }
00328 /*
00329         if( strlen(value) == 0 ) {
00330                 trace.log("attribute value is empty, skipping");
00331                 return;
00332         }
00333 */
00334         b_vformat_attribute_add_value(attr.Get(), value);
00335 }
00336 
00337 void vBase::AddEncodedValue(vAttrPtr &attr, b_VFormatEncoding encoding, const char *value, int len)
00338 {
00339 //      Trace trace("vBase::AddValue");
00340         if( !attr.Get() ) {
00341 //              trace.log("attribute pointer contains no data, skipping");
00342                 return;
00343         }
00344 
00345         attr.Get()->encoding = encoding;
00346         attr.Get()->encoding_set = TRUE;
00347 
00348         b_vformat_attribute_add_value_decoded(attr.Get(), value, len);
00349 }
00350 
00351 void vBase::AddParam(vAttrPtr &attr, const char *name, const char *value)
00352 {
00353 //      Trace trace("vBase::AddParam");
00354 
00355         if( !attr.Get() ) {
00356 //              trace.log("attribute pointer contains no data, skipping");
00357                 return;
00358         }
00359 /*
00360         if( strlen(value) == 0 ) {
00361                 trace.log("parameter value is empty, skipping");
00362                 return;
00363         }
00364 */
00365 
00366         b_VFormatParam *pParam = b_vformat_attribute_param_new(name);
00367         b_vformat_attribute_param_add_value(pParam, value);
00368         b_vformat_attribute_add_param(attr.Get(), pParam);
00369 }
00370 
00371 std::string vBase::GetAttr(const char *attrname, const char *block)
00372 {
00373 //      Trace trace("vBase::GetAttr");
00374 //      trace.logf("getting attr: %s", attrname);
00375 
00376         std::string ret;
00377         const char *value = 0;
00378 
00379         bool needs_freeing = false;
00380 
00381         b_VFormatAttribute *attr = b_vformat_find_attribute(m_format, attrname, 0, block);
00382         if( attr ) {
00383                 if( b_vformat_attribute_is_single_valued(attr) ) {
00384                         value = b_vformat_attribute_get_value(attr);
00385                         needs_freeing = true;
00386                 }
00387                 else {
00388                         // FIXME, this is hardcoded
00389                         value = b_vformat_attribute_get_nth_value(attr, 0);
00390                 }
00391         }
00392 
00393         if( value )
00394                 ret = value;
00395 
00396         if( needs_freeing )
00397                 g_free((char *)value);
00398 
00399 //      trace.logf("attr value: %s", ret.c_str());
00400         return ret;
00401 }
00402 
00403 std::vector<std::string> vBase::GetValueVector(const char *attrname, const char *block)
00404 {
00405 //      Trace trace("vBase::GetValueVector");
00406 //      trace.logf("getting value vector for: %s", attrname);
00407 
00408         std::vector<std::string> ret;
00409         const char *value = 0;
00410         bool needs_freeing = false;
00411 
00412         b_VFormatAttribute *attr = b_vformat_find_attribute(m_format, attrname, 0, block);
00413         if( attr ) {
00414                 if( b_vformat_attribute_is_single_valued(attr) ) {
00415                         value = b_vformat_attribute_get_value(attr);
00416                         needs_freeing = true;
00417                 } else {
00418                         // nasty, but avoids tweaking vformat.
00419                         int idx = 0;
00420                         do {
00421                                 value = b_vformat_attribute_get_nth_value(attr, idx++);
00422                                 if( value ) {
00423                                         ret.push_back(value);
00424                                 }
00425                         } while( value );
00426                 }
00427         }
00428 
00429         if( needs_freeing )
00430                 g_free((char *)value);
00431 
00432         return ret;
00433 }
00434 
00435 vAttr vBase::GetAttrObj(const char *attrname, int nth, const char *block)
00436 {
00437 //      Trace trace("vBase::GetAttrObj");
00438 //      trace.logf("getting attr: %s", attrname);
00439 
00440         return vAttr(b_vformat_find_attribute(m_format, attrname, nth, block));
00441 }
00442 
00443 std::vector<std::string> vBase::Tokenize(const std::string& str, const char delim)
00444 {
00445         std::vector<std::string> tokens;
00446         std::string::size_type delimPos = 0, tokenPos = 0, pos = 0;
00447 
00448         if( str.length() < 1 ) {
00449                 return tokens;
00450         }
00451 
00452         while( 1 ) {
00453                 delimPos = str.find_first_of(delim, pos);
00454                 tokenPos = str.find_first_not_of(delim, pos);
00455 
00456                 if( std::string::npos != delimPos ) {
00457                         if( std::string::npos != tokenPos ) {
00458                                 if( tokenPos < delimPos ) {
00459                                         tokens.push_back(str.substr(pos, delimPos-pos));
00460                                 } else {
00461                                         tokens.push_back("");
00462                                 }
00463                         } else {
00464                                 tokens.push_back("");
00465                         }
00466                         pos = delimPos + 1;
00467                 } else {
00468                         if( std::string::npos != tokenPos ){
00469                                 tokens.push_back(str.substr(pos));
00470                         } else {
00471                                 tokens.push_back("");
00472                         }
00473                         break;
00474                 }
00475         }
00476         return tokens;
00477 }
00478 
00479 std::string vBase::ToStringList(const std::vector<std::string> &list, const char delim)
00480 {
00481         std::string str;
00482         for( unsigned int idx = 0; idx < list.size(); idx++ ) {
00483                 if( idx ) {
00484                         str += delim;
00485                 }
00486                 str += list[idx];
00487         }
00488         return str;
00489 }
00490 
00491 }} // namespace Barry::Sync
00492 
Generated by  doxygen 1.6.2-20100208