lib: starting to pull in the os4x specific parts of the vbase code
[barry.git] / src / vbase.cc
blob5cc850c7b322f69ef5fbe7ee565ac7df9267e6af
1 //
2 // \file vbase.cc
3 // vformat support routines in base class
4 //
6 /*
7 Copyright (C) 2006-2010, Net Direct Inc. (http://www.netdirect.ca/)
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18 See the GNU General Public License in the COPYING file at the
19 root directory of this project for more details.
22 #include "vbase.h"
23 //#include "trace.h"
24 #include "vformat.h" // comes from opensync, but not a public header yet
25 #include "tzwrapper.h"
26 #include <stdint.h>
27 #include <string.h>
28 #include <glib.h>
29 #include <sstream>
31 using namespace std;
33 namespace Barry { namespace Sync {
35 //////////////////////////////////////////////////////////////////////////////
36 // vTimeConverter
38 std::string vTimeConverter::unix2vtime(const time_t *timestamp)
40 struct tm split;
41 if( !gmtime_r(timestamp, &split) ) {
42 ostringstream oss;
43 oss << "gmtime_r() failed on time_t of ";
44 if( timestamp )
45 oss << *timestamp;
46 else
47 oss << "(null pointer)";
48 throw Barry::ConvertError(oss.str());
51 return tm_to_iso(&split, true);
54 time_t vTimeConverter::vtime2unix(const char *vtime)
56 return TzWrapper::iso_mktime(vtime);
60 // The following implementation is taken from opensync's
61 // opensync_time.c implementation with the following copyright
62 // notices at the top as of July 2010:
64 // * Copyright (C) 2004-2005 Armin Bauer <armin.bauer@opensync.org>
65 // * Copyright (C) 2006-2008 Daniel Gollub <gollub@b1-systems.de>
66 // * Copyright (C) 2007 Chris Frey <cdfrey@netdirect.ca>
68 // License: LGPL 2.1 or later
70 int vTimeConverter::alarmduration2sec(const char *alarm)
72 int i, secs, digits = 0;
73 int is_digit = 0;
74 int sign = 1; // when ical stamp doesn't start with '-' => seconds after event
75 int days = 0, weeks = 0, hours = 0, minutes = 0, seconds = 0;
76 int len = strlen(alarm);
78 for (i=0; i < len; i++) {
80 switch (alarm[i]) {
81 case '-':
82 sign = -1; // seconds before event - change the sign
83 case 'P':
84 case 'T':
85 is_digit = 0;
86 break;
87 case 'W':
88 is_digit = 0;
89 weeks = digits;
90 break;
91 case 'D':
92 is_digit = 0;
93 days = digits;
94 break;
95 case 'H':
96 is_digit = 0;
97 hours = digits;
98 break;
99 case 'M':
100 is_digit = 0;
101 minutes = digits;
102 break;
103 case 'S':
104 is_digit = 0;
105 seconds = digits;
106 break;
107 case '0':
108 case '1':
109 case '2':
110 case '3':
111 case '4':
112 case '5':
113 case '6':
114 case '7':
115 case '8':
116 case '9':
117 if (is_digit)
118 break;
120 if (sscanf((char*)(alarm+i),"%d",&digits) == EOF)
121 return -1;
123 is_digit = 1;
124 break;
128 secs = (weeks * 7 * 24 * 3600) + (days * 24 * 3600) + (hours * 3600) + (minutes * 60) + seconds;
130 secs = secs * sign; // change sign if the alarm is in seconds before event (leading '-')
132 return secs;
137 //////////////////////////////////////////////////////////////////////////////
138 // vAttr
140 std::string vAttr::GetName()
142 std::string ret;
144 if( !m_attr )
145 return ret;
147 const char *name = b_vformat_attribute_get_name(m_attr);
148 if( name )
149 ret = name;
150 return ret;
153 std::string vAttr::GetValue(int nth)
155 std::string ret;
156 const char *value = 0;
158 if( m_attr ) {
159 if( b_vformat_attribute_is_single_valued(m_attr) ) {
160 if( nth == 0 )
161 value = b_vformat_attribute_get_value(m_attr);
163 else {
164 value = b_vformat_attribute_get_nth_value(m_attr, nth);
168 if( value )
169 ret = value;
171 return ret;
174 std::string vAttr::GetDecodedValue()
176 std::string ret;
177 GString *value = NULL;
179 if( m_attr ) {
180 if( b_vformat_attribute_is_single_valued(m_attr) ) {
181 value = b_vformat_attribute_get_value_decoded(m_attr);
185 if( value )
186 ret.assign(value->str, value->len);
188 return ret;
191 std::string vAttr::GetParam(const char *name, int nth)
193 std::string ret;
195 if( !m_attr )
196 return ret;
198 b_VFormatParam *param = b_vformat_attribute_find_param(m_attr, name, 0);
199 if( !param )
200 return ret;
202 const char *value = b_vformat_attribute_param_get_nth_value(param, nth);
203 if( value )
204 ret = value;
206 return ret;
209 /// Does an exhaustive search through the attribute, searching for all
210 /// param values that exist for the given name, and returns all values
211 /// in a comma delimited string.
212 std::string vAttr::GetAllParams(const char *name)
214 std::string ret;
216 if( !m_attr )
217 return ret;
219 b_VFormatParam *param = 0;
220 for( int level = 0;
221 (param = b_vformat_attribute_find_param(m_attr, name, level));
222 level++ )
224 const char *value = 0;
225 for( int nth = 0;
226 (value = b_vformat_attribute_param_get_nth_value(param, nth));
227 nth++ )
229 if( ret.size() )
230 ret += ",";
231 ret += value;
235 return ret;
239 //////////////////////////////////////////////////////////////////////////////
240 // vCalendar
242 vBase::vBase()
243 : m_format(0)
247 vBase::~vBase()
249 if( m_format ) {
250 b_vformat_free(m_format);
251 m_format = 0;
255 void vBase::SetFormat(b_VFormat *format)
257 if( m_format ) {
258 b_vformat_free(m_format);
259 m_format = 0;
261 m_format = format;
264 void vBase::Clear()
266 if( m_format ) {
267 b_vformat_free(m_format);
268 m_format = 0;
272 vAttrPtr vBase::NewAttr(const char *name)
274 // Trace trace("vBase::NewAttr");
276 // trace.logf("creating valueless attr: %s", name);
278 vAttrPtr attr(b_vformat_attribute_new(NULL, name));
279 if( !attr.Get() )
280 throw Barry::ConvertError("resource error allocating vformat attribute");
281 return attr;
284 vAttrPtr vBase::NewAttr(const char *name, const char *value)
286 // Trace trace("vBase::NewAttr");
289 some vCard values are positional (like name), so blank should be allowed...
291 if( strlen(value) == 0 ) {
292 trace.logf("attribute '%s' contains no data, skipping", name);
293 return vAttrPtr();
297 // trace.logf("creating attr: %s, %s", name, value);
299 vAttrPtr attr(b_vformat_attribute_new(NULL, name));
300 if( !attr.Get() )
301 throw ConvertError("resource error allocating vformat attribute");
303 b_vformat_attribute_add_value(attr.Get(), value);
304 return attr;
307 void vBase::AddAttr(vAttrPtr attr)
309 // Trace trace("vBase::AddAttr");
311 if( !attr.Get() ) {
312 // trace.log("attribute contains no data, skipping");
313 return;
316 b_vformat_add_attribute(m_format, attr.Extract());
319 void vBase::AddValue(vAttrPtr &attr, const char *value)
321 // Trace trace("vBase::AddValue");
322 if( !attr.Get() ) {
323 // trace.log("attribute pointer contains no data, skipping");
324 return;
327 if( strlen(value) == 0 ) {
328 trace.log("attribute value is empty, skipping");
329 return;
332 b_vformat_attribute_add_value(attr.Get(), value);
335 void vBase::AddEncodedValue(vAttrPtr &attr, b_VFormatEncoding encoding, const char *value, int len)
337 // Trace trace("vBase::AddValue");
338 if( !attr.Get() ) {
339 // trace.log("attribute pointer contains no data, skipping");
340 return;
343 attr.Get()->encoding = encoding;
344 attr.Get()->encoding_set = TRUE;
346 b_vformat_attribute_add_value_decoded(attr.Get(), value, len);
349 void vBase::AddParam(vAttrPtr &attr, const char *name, const char *value)
351 // Trace trace("vBase::AddParam");
353 if( !attr.Get() ) {
354 // trace.log("attribute pointer contains no data, skipping");
355 return;
358 if( strlen(value) == 0 ) {
359 trace.log("parameter value is empty, skipping");
360 return;
364 b_VFormatParam *pParam = b_vformat_attribute_param_new(name);
365 b_vformat_attribute_param_add_value(pParam, value);
366 b_vformat_attribute_add_param(attr.Get(), pParam);
369 std::string vBase::GetAttr(const char *attrname, const char *block)
371 // Trace trace("vBase::GetAttr");
372 // trace.logf("getting attr: %s", attrname);
374 std::string ret;
375 const char *value = 0;
377 bool needs_freeing = false;
379 b_VFormatAttribute *attr = b_vformat_find_attribute(m_format, attrname, 0, block);
380 if( attr ) {
381 if( b_vformat_attribute_is_single_valued(attr) ) {
382 value = b_vformat_attribute_get_value(attr);
383 needs_freeing = true;
385 else {
386 // FIXME, this is hardcoded
387 value = b_vformat_attribute_get_nth_value(attr, 0);
391 if( value )
392 ret = value;
394 if( needs_freeing )
395 g_free((char *)value);
397 // trace.logf("attr value: %s", ret.c_str());
398 return ret;
401 std::vector<std::string> vBase::GetValueVector(const char *attrname, const char *block)
403 // Trace trace("vBase::GetValueVector");
404 // trace.logf("getting value vector for: %s", attrname);
406 std::vector<std::string> ret;
407 const char *value = 0;
408 bool needs_freeing = false;
410 b_VFormatAttribute *attr = b_vformat_find_attribute(m_format, attrname, 0, block);
411 if( attr ) {
412 if( b_vformat_attribute_is_single_valued(attr) ) {
413 value = b_vformat_attribute_get_value(attr);
414 needs_freeing = true;
415 } else {
416 // nasty, but avoids tweaking vformat.
417 int idx = 0;
418 do {
419 value = b_vformat_attribute_get_nth_value(attr, idx++);
420 if( value ) {
421 ret.push_back(value);
423 } while( value );
427 if( needs_freeing )
428 g_free((char *)value);
430 return ret;
433 vAttr vBase::GetAttrObj(const char *attrname, int nth, const char *block)
435 // Trace trace("vBase::GetAttrObj");
436 // trace.logf("getting attr: %s", attrname);
438 return vAttr(b_vformat_find_attribute(m_format, attrname, nth, block));
441 std::vector<std::string> vBase::Tokenize(const std::string& str, const char delim)
443 std::vector<std::string> tokens;
444 std::string::size_type delimPos = 0, tokenPos = 0, pos = 0;
446 if( str.length() < 1 ) {
447 return tokens;
450 while( 1 ) {
451 delimPos = str.find_first_of(delim, pos);
452 tokenPos = str.find_first_not_of(delim, pos);
454 if( std::string::npos != delimPos ) {
455 if( std::string::npos != tokenPos ) {
456 if( tokenPos < delimPos ) {
457 tokens.push_back(str.substr(pos, delimPos-pos));
458 } else {
459 tokens.push_back("");
461 } else {
462 tokens.push_back("");
464 pos = delimPos + 1;
465 } else {
466 if( std::string::npos != tokenPos ){
467 tokens.push_back(str.substr(pos));
468 } else {
469 tokens.push_back("");
471 break;
474 return tokens;
477 std::string vBase::ToStringList(const std::vector<std::string> &list, const char delim)
479 std::string str;
480 for( unsigned int idx = 0; idx < list.size(); idx++ ) {
481 if( idx ) {
482 str += delim;
484 str += list[idx];
486 return str;
489 }} // namespace Barry::Sync