lib: show offset and rectype in HexDumpParser
[barry.git] / src / vbase.cc
blob6d6ffd07b28a9d9a4eeebd806a4da690e80e2943
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 <stdio.h>
27 #include <stdarg.h>
28 #include <stdint.h>
29 #include <string.h>
30 #include <glib.h>
31 #include <sstream>
33 using namespace std;
35 namespace Barry { namespace Sync {
37 //////////////////////////////////////////////////////////////////////////////
38 // vTimeConverter
40 std::string vTimeConverter::unix2vtime(const time_t *timestamp)
42 struct tm split;
43 if( !gmtime_r(timestamp, &split) ) {
44 ostringstream oss;
45 oss << "gmtime_r() failed on time_t of ";
46 if( timestamp )
47 oss << *timestamp;
48 else
49 oss << "(null pointer)";
50 throw Barry::ConvertError(oss.str());
53 return tm_to_iso(&split, true);
56 time_t vTimeConverter::vtime2unix(const char *vtime)
58 return TzWrapper::iso_mktime(vtime);
62 // The following implementation is taken from opensync's
63 // opensync_time.c implementation with the following copyright
64 // notices at the top as of July 2010:
66 // * Copyright (C) 2004-2005 Armin Bauer <armin.bauer@opensync.org>
67 // * Copyright (C) 2006-2008 Daniel Gollub <gollub@b1-systems.de>
68 // * Copyright (C) 2007 Chris Frey <cdfrey@netdirect.ca>
70 // License: LGPL 2.1 or later
72 int vTimeConverter::alarmduration2sec(const char *alarm)
74 int i, secs, digits = 0;
75 int is_digit = 0;
76 int sign = 1; // when ical stamp doesn't start with '-' => seconds after event
77 int days = 0, weeks = 0, hours = 0, minutes = 0, seconds = 0;
78 int len = strlen(alarm);
80 for (i=0; i < len; i++) {
82 switch (alarm[i]) {
83 case '-':
84 sign = -1; // seconds before event - change the sign
85 case 'P':
86 case 'T':
87 is_digit = 0;
88 break;
89 case 'W':
90 is_digit = 0;
91 weeks = digits;
92 break;
93 case 'D':
94 is_digit = 0;
95 days = digits;
96 break;
97 case 'H':
98 is_digit = 0;
99 hours = digits;
100 break;
101 case 'M':
102 is_digit = 0;
103 minutes = digits;
104 break;
105 case 'S':
106 is_digit = 0;
107 seconds = digits;
108 break;
109 case '0':
110 case '1':
111 case '2':
112 case '3':
113 case '4':
114 case '5':
115 case '6':
116 case '7':
117 case '8':
118 case '9':
119 if (is_digit)
120 break;
122 if (sscanf((char*)(alarm+i),"%d",&digits) == EOF)
123 return -1;
125 is_digit = 1;
126 break;
130 secs = (weeks * 7 * 24 * 3600) + (days * 24 * 3600) + (hours * 3600) + (minutes * 60) + seconds;
132 secs = secs * sign; // change sign if the alarm is in seconds before event (leading '-')
134 return secs;
139 //////////////////////////////////////////////////////////////////////////////
140 // vAttr
142 std::string vAttr::GetName()
144 std::string ret;
146 if( !m_attr )
147 return ret;
149 const char *name = b_vformat_attribute_get_name(m_attr);
150 if( name )
151 ret = name;
152 return ret;
155 std::string vAttr::GetValue(int nth)
157 std::string ret;
158 const char *value = 0;
160 if( m_attr ) {
161 if( b_vformat_attribute_is_single_valued(m_attr) ) {
162 if( nth == 0 )
163 value = b_vformat_attribute_get_value(m_attr);
165 else {
166 value = b_vformat_attribute_get_nth_value(m_attr, nth);
170 if( value )
171 ret = value;
173 return ret;
176 std::string vAttr::GetDecodedValue()
178 std::string ret;
179 GString *value = NULL;
181 if( m_attr ) {
182 if( b_vformat_attribute_is_single_valued(m_attr) ) {
183 value = b_vformat_attribute_get_value_decoded(m_attr);
187 if( value )
188 ret.assign(value->str, value->len);
190 return ret;
193 std::string vAttr::GetParam(const char *name, int nth)
195 std::string ret;
197 if( !m_attr )
198 return ret;
200 b_VFormatParam *param = b_vformat_attribute_find_param(m_attr, name, 0);
201 if( !param )
202 return ret;
204 const char *value = b_vformat_attribute_param_get_nth_value(param, nth);
205 if( value )
206 ret = value;
208 return ret;
211 /// Does an exhaustive search through the attribute, searching for all
212 /// param values that exist for the given name, and returns all values
213 /// in a comma delimited string.
214 std::string vAttr::GetAllParams(const char *name)
216 std::string ret;
218 if( !m_attr )
219 return ret;
221 b_VFormatParam *param = 0;
222 for( int level = 0;
223 (param = b_vformat_attribute_find_param(m_attr, name, level));
224 level++ )
226 const char *value = 0;
227 for( int nth = 0;
228 (value = b_vformat_attribute_param_get_nth_value(param, nth));
229 nth++ )
231 if( ret.size() )
232 ret += ",";
233 ret += value;
237 return ret;
241 //////////////////////////////////////////////////////////////////////////////
242 // vCalendar
244 vBase::vBase()
245 : m_format(b_vformat_new())
249 vBase::vBase(b_VFormat *format)
250 : m_format(format)
252 if( !format )
253 throw Barry::Error("Cannot construct vBase with null format");
256 vBase::~vBase()
258 if( m_format ) {
259 b_vformat_free(m_format);
260 m_format = 0;
264 void vBase::SetFormat(b_VFormat *format)
266 if( !format )
267 throw Barry::Error("Cannot set vBase with null format");
269 if( m_format ) {
270 b_vformat_free(m_format);
271 m_format = 0;
273 m_format = format;
276 void vBase::Clear()
278 if( m_format ) {
279 b_vformat_free(m_format);
280 m_format = b_vformat_new();
284 vAttrPtr vBase::NewAttr(const char *name)
286 // Trace trace("vBase::NewAttr");
288 // trace.logf("creating valueless attr: %s", name);
290 vAttrPtr attr(b_vformat_attribute_new(NULL, name));
291 if( !attr.Get() )
292 throw Barry::ConvertError("resource error allocating vformat attribute");
293 return attr;
296 vAttrPtr vBase::NewAttr(const char *name, const char *value)
298 // Trace trace("vBase::NewAttr");
301 some vCard values are positional (like name), so blank should be allowed...
303 if( strlen(value) == 0 ) {
304 trace.logf("attribute '%s' contains no data, skipping", name);
305 return vAttrPtr();
309 // trace.logf("creating attr: %s, %s", name, value);
311 vAttrPtr attr(b_vformat_attribute_new(NULL, name));
312 if( !attr.Get() )
313 throw ConvertError("resource error allocating vformat attribute");
315 b_vformat_attribute_add_value(attr.Get(), value);
316 return attr;
319 void vBase::AddAttr(vAttrPtr attr)
321 // Trace trace("vBase::AddAttr");
323 if( !attr.Get() ) {
324 // trace.log("attribute contains no data, skipping");
325 return;
328 b_vformat_add_attribute(m_format, attr.Extract());
331 void vBase::AddValue(vAttrPtr &attr, const char *value)
333 // Trace trace("vBase::AddValue");
334 if( !attr.Get() ) {
335 // trace.log("attribute pointer contains no data, skipping");
336 return;
339 if( strlen(value) == 0 ) {
340 trace.log("attribute value is empty, skipping");
341 return;
344 b_vformat_attribute_add_value(attr.Get(), value);
347 void vBase::AddEncodedValue(vAttrPtr &attr, b_VFormatEncoding encoding, const char *value, int len)
349 // Trace trace("vBase::AddValue");
350 if( !attr.Get() ) {
351 // trace.log("attribute pointer contains no data, skipping");
352 return;
355 attr.Get()->encoding = encoding;
356 attr.Get()->encoding_set = TRUE;
358 b_vformat_attribute_add_value_decoded(attr.Get(), value, len);
361 void vBase::AddParam(vAttrPtr &attr, const char *name, const char *value)
363 // Trace trace("vBase::AddParam");
365 if( !attr.Get() ) {
366 // trace.log("attribute pointer contains no data, skipping");
367 return;
370 if( strlen(value) == 0 ) {
371 trace.log("parameter value is empty, skipping");
372 return;
376 b_VFormatParam *pParam = b_vformat_attribute_param_new(name);
377 b_vformat_attribute_param_add_value(pParam, value);
378 b_vformat_attribute_add_param(attr.Get(), pParam);
381 std::string vBase::GetAttr(const char *attrname, const char *block)
383 // Trace trace("vBase::GetAttr");
384 // trace.logf("getting attr: %s", attrname);
386 std::string ret;
387 const char *value = 0;
389 bool needs_freeing = false;
391 b_VFormatAttribute *attr = b_vformat_find_attribute(m_format, attrname, 0, block);
392 if( attr ) {
393 if( b_vformat_attribute_is_single_valued(attr) ) {
394 value = b_vformat_attribute_get_value(attr);
395 needs_freeing = true;
397 else {
398 // FIXME, this is hardcoded
399 value = b_vformat_attribute_get_nth_value(attr, 0);
403 if( value )
404 ret = value;
406 if( needs_freeing )
407 g_free((char *)value);
409 // trace.logf("attr value: %s", ret.c_str());
410 return ret;
413 std::vector<std::string> vBase::GetValueVector(const char *attrname, const char *block)
415 // Trace trace("vBase::GetValueVector");
416 // trace.logf("getting value vector for: %s", attrname);
418 std::vector<std::string> ret;
419 const char *value = 0;
420 bool needs_freeing = false;
422 b_VFormatAttribute *attr = b_vformat_find_attribute(m_format, attrname, 0, block);
423 if( attr ) {
424 if( b_vformat_attribute_is_single_valued(attr) ) {
425 value = b_vformat_attribute_get_value(attr);
426 needs_freeing = true;
427 } else {
428 // nasty, but avoids tweaking vformat.
429 int idx = 0;
430 do {
431 value = b_vformat_attribute_get_nth_value(attr, idx++);
432 if( value ) {
433 ret.push_back(value);
435 } while( value );
439 if( needs_freeing )
440 g_free((char *)value);
442 return ret;
445 vAttr vBase::GetAttrObj(const char *attrname, int nth, const char *block)
447 // Trace trace("vBase::GetAttrObj");
448 // trace.logf("getting attr: %s", attrname);
450 return vAttr(b_vformat_find_attribute(m_format, attrname, nth, block));
453 std::vector<std::string> vBase::Tokenize(const std::string& str, const char delim)
455 std::vector<std::string> tokens;
456 std::string::size_type delimPos = 0, tokenPos = 0, pos = 0;
458 if( str.length() < 1 ) {
459 return tokens;
462 while( 1 ) {
463 delimPos = str.find_first_of(delim, pos);
464 tokenPos = str.find_first_not_of(delim, pos);
466 if( std::string::npos != delimPos ) {
467 if( std::string::npos != tokenPos ) {
468 if( tokenPos < delimPos ) {
469 tokens.push_back(str.substr(pos, delimPos-pos));
470 } else {
471 tokens.push_back("");
473 } else {
474 tokens.push_back("");
476 pos = delimPos + 1;
477 } else {
478 if( std::string::npos != tokenPos ){
479 tokens.push_back(str.substr(pos));
480 } else {
481 tokens.push_back("");
483 break;
486 return tokens;
489 std::string vBase::ToStringList(const std::vector<std::string> &list, const char delim)
491 std::string str;
492 for( unsigned int idx = 0; idx < list.size(); idx++ ) {
493 if( idx ) {
494 str += delim;
496 str += list[idx];
498 return str;
501 }} // namespace Barry::Sync