doc: updated ReleaseChecklist.txt
[barry.git] / src / vbase.cc
blob65949e2fbc857ee21735b61c3047a9fef82960e6
1 ///
2 /// \file vbase.cc
3 /// vformat support routines in base class
4 ///
6 /*
7 Copyright (C) 2006-2012, 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 "r_contact.h" // for CategoryList
27 #include <stdio.h>
28 #include <stdarg.h>
29 #include <stdint.h>
30 #include <string.h>
31 #include <glib.h>
32 #include <sstream>
34 using namespace std;
36 namespace Barry { namespace Sync {
38 //////////////////////////////////////////////////////////////////////////////
39 // vTimeConverter
41 std::string vTimeConverter::unix2vtime(const time_t *timestamp)
43 struct tm split;
44 if( !gmtime_r(timestamp, &split) ) {
45 ostringstream oss;
46 oss << "gmtime_r() failed on time_t of ";
47 if( timestamp )
48 oss << *timestamp;
49 else
50 oss << "(null pointer)";
51 throw Barry::ConvertError(oss.str());
54 return tm_to_iso(&split, true);
57 time_t vTimeConverter::vtime2unix(const char *vtime)
59 return TzWrapper::iso_mktime(vtime);
63 // The following implementation is taken from opensync's
64 // opensync_time.c implementation with the following copyright
65 // notices at the top as of July 2010:
67 // * Copyright (C) 2004-2005 Armin Bauer <armin.bauer@opensync.org>
68 // * Copyright (C) 2006-2008 Daniel Gollub <gollub@b1-systems.de>
69 // * Copyright (C) 2007 Chris Frey <cdfrey@netdirect.ca>
71 // License: LGPL 2.1 or later
73 int vTimeConverter::alarmduration2sec(const char *alarm)
75 int i, secs, digits = 0;
76 int is_digit = 0;
77 int sign = 1; // when ical stamp doesn't start with '-' => seconds after event
78 int days = 0, weeks = 0, hours = 0, minutes = 0, seconds = 0;
79 int len = strlen(alarm);
81 for (i=0; i < len; i++) {
83 switch (alarm[i]) {
84 case '-':
85 sign = -1; // seconds before event - change the sign
86 case 'P':
87 case 'T':
88 is_digit = 0;
89 break;
90 case 'W':
91 is_digit = 0;
92 weeks = digits;
93 break;
94 case 'D':
95 is_digit = 0;
96 days = digits;
97 break;
98 case 'H':
99 is_digit = 0;
100 hours = digits;
101 break;
102 case 'M':
103 is_digit = 0;
104 minutes = digits;
105 break;
106 case 'S':
107 is_digit = 0;
108 seconds = digits;
109 break;
110 case '0':
111 case '1':
112 case '2':
113 case '3':
114 case '4':
115 case '5':
116 case '6':
117 case '7':
118 case '8':
119 case '9':
120 if (is_digit)
121 break;
123 if (sscanf((char*)(alarm+i),"%d",&digits) == EOF)
124 return -1;
126 is_digit = 1;
127 break;
131 secs = (weeks * 7 * 24 * 3600) + (days * 24 * 3600) + (hours * 3600) + (minutes * 60) + seconds;
133 secs = secs * sign; // change sign if the alarm is in seconds before event (leading '-')
135 return secs;
140 //////////////////////////////////////////////////////////////////////////////
141 // vAttr
143 std::string vAttr::GetName()
145 std::string ret;
147 if( !m_attr )
148 return ret;
150 const char *name = b_vformat_attribute_get_name(m_attr);
151 if( name )
152 ret = name;
153 return ret;
156 std::string vAttr::GetValue(int nth)
158 std::string ret;
159 const char *value = 0;
161 if( m_attr ) {
162 if( b_vformat_attribute_is_single_valued(m_attr) ) {
163 if( nth == 0 )
164 value = b_vformat_attribute_get_value(m_attr);
166 else {
167 value = b_vformat_attribute_get_nth_value(m_attr, nth);
171 if( value )
172 ret = value;
174 return ret;
177 std::string vAttr::GetDecodedValue()
179 std::string ret;
180 GString *value = NULL;
182 if( m_attr ) {
183 if( b_vformat_attribute_is_single_valued(m_attr) ) {
184 value = b_vformat_attribute_get_value_decoded(m_attr);
188 if( value )
189 ret.assign(value->str, value->len);
191 return ret;
194 std::string vAttr::GetParam(const char *name, int nth)
196 std::string ret;
198 if( !m_attr )
199 return ret;
201 b_VFormatParam *param = b_vformat_attribute_find_param(m_attr, name, 0);
202 if( !param )
203 return ret;
205 const char *value = b_vformat_attribute_param_get_nth_value(param, nth);
206 if( value )
207 ret = value;
209 return ret;
212 /// Does an exhaustive search through the attribute, searching for all
213 /// param values that exist for the given name, and returns all values
214 /// in a comma delimited string.
215 std::string vAttr::GetAllParams(const char *name)
217 std::string ret;
219 if( !m_attr )
220 return ret;
222 b_VFormatParam *param = 0;
223 for( int level = 0;
224 (param = b_vformat_attribute_find_param(m_attr, name, level));
225 level++ )
227 const char *value = 0;
228 for( int nth = 0;
229 (value = b_vformat_attribute_param_get_nth_value(param, nth));
230 nth++ )
232 if( ret.size() )
233 ret += ",";
234 ret += value;
238 return ret;
242 //////////////////////////////////////////////////////////////////////////////
243 // vCalendar
245 vBase::vBase()
246 : m_format(b_vformat_new())
250 vBase::vBase(b_VFormat *format)
251 : m_format(format)
253 if( !format )
254 throw Barry::Error("Cannot construct vBase with null format");
257 vBase::~vBase()
259 if( m_format ) {
260 b_vformat_free(m_format);
261 m_format = 0;
265 void vBase::SetFormat(b_VFormat *format)
267 if( !format )
268 throw Barry::Error("Cannot set vBase with null format");
270 if( m_format ) {
271 b_vformat_free(m_format);
272 m_format = 0;
274 m_format = format;
277 void vBase::Clear()
279 if( m_format ) {
280 b_vformat_free(m_format);
281 m_format = b_vformat_new();
285 vAttrPtr vBase::NewAttr(const char *name)
287 // Trace trace("vBase::NewAttr");
289 // trace.logf("creating valueless attr: %s", name);
291 vAttrPtr attr(b_vformat_attribute_new(NULL, name));
292 if( !attr.Get() )
293 throw Barry::ConvertError("resource error allocating vformat attribute");
294 return attr;
297 vAttrPtr vBase::NewAttr(const char *name, const char *value)
299 // Trace trace("vBase::NewAttr");
302 some vCard values are positional (like name), so blank should be allowed...
304 if( strlen(value) == 0 ) {
305 trace.logf("attribute '%s' contains no data, skipping", name);
306 return vAttrPtr();
310 // trace.logf("creating attr: %s, %s", name, value);
312 vAttrPtr attr(b_vformat_attribute_new(NULL, name));
313 if( !attr.Get() )
314 throw ConvertError("resource error allocating vformat attribute");
316 b_vformat_attribute_add_value(attr.Get(), value);
317 return attr;
320 void vBase::AddAttr(vAttrPtr attr)
322 // Trace trace("vBase::AddAttr");
324 if( !attr.Get() ) {
325 // trace.log("attribute contains no data, skipping");
326 return;
329 b_vformat_add_attribute(m_format, attr.Extract());
332 void vBase::AddValue(vAttrPtr &attr, const char *value)
334 // Trace trace("vBase::AddValue");
335 if( !attr.Get() ) {
336 // trace.log("attribute pointer contains no data, skipping");
337 return;
340 if( strlen(value) == 0 ) {
341 trace.log("attribute value is empty, skipping");
342 return;
345 b_vformat_attribute_add_value(attr.Get(), value);
348 void vBase::AddEncodedValue(vAttrPtr &attr, b_VFormatEncoding encoding, const char *value, int len)
350 // Trace trace("vBase::AddValue");
351 if( !attr.Get() ) {
352 // trace.log("attribute pointer contains no data, skipping");
353 return;
356 attr.Get()->encoding = encoding;
357 attr.Get()->encoding_set = TRUE;
359 b_vformat_attribute_add_value_decoded(attr.Get(), value, len);
362 void vBase::AddParam(vAttrPtr &attr, const char *name, const char *value)
364 // Trace trace("vBase::AddParam");
366 if( !attr.Get() ) {
367 // trace.log("attribute pointer contains no data, skipping");
368 return;
371 if( strlen(value) == 0 ) {
372 trace.log("parameter value is empty, skipping");
373 return;
377 b_VFormatParam *pParam = b_vformat_attribute_param_new(name);
378 b_vformat_attribute_param_add_value(pParam, value);
379 b_vformat_attribute_add_param(attr.Get(), pParam);
382 void vBase::AddCategories(const Barry::CategoryList &categories)
384 if( !categories.size() )
385 return;
387 vAttrPtr cat = NewAttr("CATEGORIES"); // RFC 2426, 3.6.1
388 Barry::CategoryList::const_iterator i = categories.begin();
389 for( ; i < categories.end(); ++i ) {
390 AddValue(cat, i->c_str());
392 AddAttr(cat);
395 std::string vBase::GetAttr(const char *attrname, const char *block)
397 // Trace trace("vBase::GetAttr");
398 // trace.logf("getting attr: %s", attrname);
400 std::string ret;
401 const char *value = 0;
403 bool needs_freeing = false;
405 b_VFormatAttribute *attr = b_vformat_find_attribute(m_format, attrname, 0, block);
406 if( attr ) {
407 if( b_vformat_attribute_is_single_valued(attr) ) {
408 value = b_vformat_attribute_get_value(attr);
409 needs_freeing = true;
411 else {
412 // FIXME, this is hardcoded
413 value = b_vformat_attribute_get_nth_value(attr, 0);
417 if( value )
418 ret = value;
420 if( needs_freeing )
421 g_free((char *)value);
423 // trace.logf("attr value: %s", ret.c_str());
424 return ret;
427 std::vector<std::string> vBase::GetValueVector(const char *attrname, const char *block)
429 // Trace trace("vBase::GetValueVector");
430 // trace.logf("getting value vector for: %s", attrname);
432 std::vector<std::string> ret;
433 const char *value = 0;
434 bool needs_freeing = false;
436 b_VFormatAttribute *attr = b_vformat_find_attribute(m_format, attrname, 0, block);
437 if( attr ) {
438 if( b_vformat_attribute_is_single_valued(attr) ) {
439 value = b_vformat_attribute_get_value(attr);
440 needs_freeing = true;
441 } else {
442 // nasty, but avoids tweaking vformat.
443 int idx = 0;
444 do {
445 value = b_vformat_attribute_get_nth_value(attr, idx++);
446 if( value ) {
447 ret.push_back(value);
449 } while( value );
453 if( needs_freeing )
454 g_free((char *)value);
456 return ret;
459 vAttr vBase::GetAttrObj(const char *attrname, int nth, const char *block)
461 // Trace trace("vBase::GetAttrObj");
462 // trace.logf("getting attr: %s", attrname);
464 return vAttr(b_vformat_find_attribute(m_format, attrname, nth, block));
467 std::vector<std::string> vBase::Tokenize(const std::string& str, const char delim)
469 std::vector<std::string> tokens;
470 std::string::size_type delimPos = 0, tokenPos = 0, pos = 0;
472 if( str.length() < 1 ) {
473 return tokens;
476 while( 1 ) {
477 delimPos = str.find_first_of(delim, pos);
478 tokenPos = str.find_first_not_of(delim, pos);
480 if( std::string::npos != delimPos ) {
481 if( std::string::npos != tokenPos ) {
482 if( tokenPos < delimPos ) {
483 tokens.push_back(str.substr(pos, delimPos-pos));
484 } else {
485 tokens.push_back("");
487 } else {
488 tokens.push_back("");
490 pos = delimPos + 1;
491 } else {
492 if( std::string::npos != tokenPos ){
493 tokens.push_back(str.substr(pos));
494 } else {
495 tokens.push_back("");
497 break;
500 return tokens;
503 std::string vBase::ToStringList(const std::vector<std::string> &list, const char delim)
505 std::string str;
506 for( unsigned int idx = 0; idx < list.size(); idx++ ) {
507 if( idx ) {
508 str += delim;
510 str += list[idx];
512 return str;
515 }} // namespace Barry::Sync