test

Fork of mbed-libxively-6eca970 by Xively Official

Committer:
xively
Date:
Wed Jun 26 10:40:43 2013 +0000
Revision:
0:82702e998d3f
libxively v0.1.1-rc0 (34c8b32)

Who changed what in which revision?

UserRevisionLine numberNew contents of line
xively 0:82702e998d3f 1 // Copyright (c) 2003-2013, LogMeIn, Inc. All rights reserved.
xively 0:82702e998d3f 2 // This is part of Xively C library, it is under the BSD 3-Clause license.
xively 0:82702e998d3f 3
xively 0:82702e998d3f 4 /**
xively 0:82702e998d3f 5 * \file csv_data.c
xively 0:82702e998d3f 6 * \author Olgierd Humenczuk
xively 0:82702e998d3f 7 * \brief Implements CSV _data layer_ encoders and decoders specific to Xively CSV data format [see csv_data.h]
xively 0:82702e998d3f 8 */
xively 0:82702e998d3f 9
xively 0:82702e998d3f 10 #include <assert.h>
xively 0:82702e998d3f 11 #include <stdio.h>
xively 0:82702e998d3f 12 #include <time.h>
xively 0:82702e998d3f 13
xively 0:82702e998d3f 14 #include "csv_data.h"
xively 0:82702e998d3f 15 #include "xi_macros.h"
xively 0:82702e998d3f 16 #include "xi_helpers.h"
xively 0:82702e998d3f 17 #include "xi_err.h"
xively 0:82702e998d3f 18 #include "xi_consts.h"
xively 0:82702e998d3f 19
xively 0:82702e998d3f 20 static char XI_CSV_LOCAL_BUFFER[ XI_CSV_BUFFER_SIZE ];
xively 0:82702e998d3f 21
xively 0:82702e998d3f 22 inline static int csv_encode_value(
xively 0:82702e998d3f 23 char* buffer
xively 0:82702e998d3f 24 , size_t buffer_size
xively 0:82702e998d3f 25 , const xi_datapoint_t* p )
xively 0:82702e998d3f 26 {
xively 0:82702e998d3f 27 // PRECONDITION
xively 0:82702e998d3f 28 assert( buffer != 0 );
xively 0:82702e998d3f 29 assert( buffer_size != 0 );
xively 0:82702e998d3f 30 assert( p != 0 );
xively 0:82702e998d3f 31
xively 0:82702e998d3f 32 switch( p->value_type )
xively 0:82702e998d3f 33 {
xively 0:82702e998d3f 34 case XI_VALUE_TYPE_I32:
xively 0:82702e998d3f 35 return snprintf( buffer, buffer_size, "%d", p->value.i32_value );
xively 0:82702e998d3f 36 case XI_VALUE_TYPE_F32:
xively 0:82702e998d3f 37 return snprintf( buffer, buffer_size, "%f", p->value.f32_value );
xively 0:82702e998d3f 38 case XI_VALUE_TYPE_STR:
xively 0:82702e998d3f 39 return snprintf( buffer, buffer_size, "%s", p->value.str_value );
xively 0:82702e998d3f 40 default:
xively 0:82702e998d3f 41 return -1;
xively 0:82702e998d3f 42 }
xively 0:82702e998d3f 43 }
xively 0:82702e998d3f 44
xively 0:82702e998d3f 45 typedef enum
xively 0:82702e998d3f 46 {
xively 0:82702e998d3f 47 XI_CHAR_UNKNOWN = 0,
xively 0:82702e998d3f 48 XI_CHAR_NUMBER,
xively 0:82702e998d3f 49 XI_CHAR_LETTER,
xively 0:82702e998d3f 50 XI_CHAR_DOT,
xively 0:82702e998d3f 51 XI_CHAR_SPACE,
xively 0:82702e998d3f 52 XI_CHAR_NEWLINE,
xively 0:82702e998d3f 53 XI_CHAR_TAB,
xively 0:82702e998d3f 54 XI_CHAR_MINUS
xively 0:82702e998d3f 55 } xi_char_type_t;
xively 0:82702e998d3f 56
xively 0:82702e998d3f 57 inline static xi_char_type_t csv_classify_char( char c )
xively 0:82702e998d3f 58 {
xively 0:82702e998d3f 59 switch( c )
xively 0:82702e998d3f 60 {
xively 0:82702e998d3f 61 case 13:
xively 0:82702e998d3f 62 case 11:
xively 0:82702e998d3f 63 return XI_CHAR_NEWLINE;
xively 0:82702e998d3f 64 case 9:
xively 0:82702e998d3f 65 return XI_CHAR_TAB;
xively 0:82702e998d3f 66 case 32:
xively 0:82702e998d3f 67 return XI_CHAR_SPACE;
xively 0:82702e998d3f 68 case 33: case 34: case 35: case 36: case 37: case 38: case 39:
xively 0:82702e998d3f 69 case 40: case 41: case 42: case 43: case 44:
xively 0:82702e998d3f 70 return XI_CHAR_UNKNOWN;
xively 0:82702e998d3f 71 case 45:
xively 0:82702e998d3f 72 return XI_CHAR_MINUS;
xively 0:82702e998d3f 73 case 46:
xively 0:82702e998d3f 74 return XI_CHAR_DOT;
xively 0:82702e998d3f 75 case 47:
xively 0:82702e998d3f 76 return XI_CHAR_UNKNOWN;
xively 0:82702e998d3f 77 case 48: case 49: case 50: case 51: case 52: case 53: case 54:
xively 0:82702e998d3f 78 case 55: case 56:
xively 0:82702e998d3f 79 case 57:
xively 0:82702e998d3f 80 return XI_CHAR_NUMBER;
xively 0:82702e998d3f 81 case 58: case 59: case 60: case 61: case 62: case 63:
xively 0:82702e998d3f 82 case 64:
xively 0:82702e998d3f 83 return XI_CHAR_UNKNOWN;
xively 0:82702e998d3f 84 case 65: case 66: case 67: case 68: case 69: case 70: case 71:
xively 0:82702e998d3f 85 case 72: case 73: case 74: case 75: case 76: case 77: case 78:
xively 0:82702e998d3f 86 case 79: case 80: case 81: case 82: case 83: case 84: case 85:
xively 0:82702e998d3f 87 case 86: case 87: case 88: case 89:
xively 0:82702e998d3f 88 case 90:
xively 0:82702e998d3f 89 return XI_CHAR_LETTER;
xively 0:82702e998d3f 90 case 91: case 92: case 93: case 94: case 95:
xively 0:82702e998d3f 91 case 96:
xively 0:82702e998d3f 92 return XI_CHAR_UNKNOWN;
xively 0:82702e998d3f 93 case 97: case 98: case 99: case 100: case 101: case 102: case 103:
xively 0:82702e998d3f 94 case 104: case 105: case 106: case 107: case 108: case 109: case 110:
xively 0:82702e998d3f 95 case 111: case 112: case 113: case 114: case 115: case 116: case 117:
xively 0:82702e998d3f 96 case 118: case 119: case 120: case 121:
xively 0:82702e998d3f 97 case 122:
xively 0:82702e998d3f 98 return XI_CHAR_LETTER;
xively 0:82702e998d3f 99 case 123:
xively 0:82702e998d3f 100 case 124:
xively 0:82702e998d3f 101 case 125:
xively 0:82702e998d3f 102 return XI_CHAR_UNKNOWN;
xively 0:82702e998d3f 103 default:
xively 0:82702e998d3f 104 return XI_CHAR_UNKNOWN;
xively 0:82702e998d3f 105 }
xively 0:82702e998d3f 106 }
xively 0:82702e998d3f 107
xively 0:82702e998d3f 108 typedef enum
xively 0:82702e998d3f 109 {
xively 0:82702e998d3f 110 XI_STATE_INITIAL = 0,
xively 0:82702e998d3f 111 XI_STATE_MINUS,
xively 0:82702e998d3f 112 XI_STATE_NUMBER,
xively 0:82702e998d3f 113 XI_STATE_FLOAT,
xively 0:82702e998d3f 114 XI_STATE_DOT,
xively 0:82702e998d3f 115 XI_STATE_STRING
xively 0:82702e998d3f 116 } xi_dfa_state_t;
xively 0:82702e998d3f 117
xively 0:82702e998d3f 118 xi_datapoint_t* csv_decode_value(
xively 0:82702e998d3f 119 const char* buffer, xi_datapoint_t* p )
xively 0:82702e998d3f 120 {
xively 0:82702e998d3f 121 // PRECONDITION
xively 0:82702e998d3f 122 assert( buffer != 0 );
xively 0:82702e998d3f 123 assert( p != 0 );
xively 0:82702e998d3f 124
xively 0:82702e998d3f 125 // secure the output buffer
xively 0:82702e998d3f 126 XI_GUARD_EOS( p->value.str_value, XI_VALUE_STRING_MAX_SIZE );
xively 0:82702e998d3f 127
xively 0:82702e998d3f 128 // clean the counter
xively 0:82702e998d3f 129 size_t counter = 0;
xively 0:82702e998d3f 130
xively 0:82702e998d3f 131 // the transition function
xively 0:82702e998d3f 132 static const short states[][6][2] =
xively 0:82702e998d3f 133 {
xively 0:82702e998d3f 134 // state initial // state minus // state number // state float // state dot // string
xively 0:82702e998d3f 135 { { XI_CHAR_UNKNOWN , XI_STATE_STRING }, { XI_CHAR_UNKNOWN , XI_STATE_STRING }, { XI_CHAR_UNKNOWN , XI_STATE_STRING }, { XI_CHAR_UNKNOWN , XI_STATE_STRING }, { XI_CHAR_UNKNOWN , XI_STATE_STRING }, { XI_CHAR_UNKNOWN , XI_STATE_STRING } },
xively 0:82702e998d3f 136 { { XI_CHAR_NUMBER , XI_STATE_NUMBER }, { XI_CHAR_NUMBER , XI_STATE_NUMBER }, { XI_CHAR_NUMBER , XI_STATE_NUMBER }, { XI_CHAR_NUMBER , XI_STATE_FLOAT }, { XI_CHAR_NUMBER , XI_STATE_FLOAT }, { XI_CHAR_NUMBER , XI_STATE_STRING } },
xively 0:82702e998d3f 137 { { XI_CHAR_LETTER , XI_STATE_STRING }, { XI_CHAR_LETTER , XI_STATE_STRING }, { XI_CHAR_LETTER , XI_STATE_STRING }, { XI_CHAR_LETTER , XI_STATE_STRING }, { XI_CHAR_LETTER , XI_STATE_STRING }, { XI_CHAR_LETTER , XI_STATE_STRING } },
xively 0:82702e998d3f 138 { { XI_CHAR_DOT , XI_STATE_DOT }, { XI_CHAR_DOT , XI_STATE_DOT }, { XI_CHAR_DOT , XI_STATE_DOT }, { XI_CHAR_DOT , XI_STATE_STRING }, { XI_CHAR_DOT , XI_STATE_STRING }, { XI_CHAR_DOT , XI_STATE_STRING } },
xively 0:82702e998d3f 139 { { XI_CHAR_SPACE , XI_STATE_STRING }, { XI_CHAR_SPACE , XI_STATE_STRING }, { XI_CHAR_SPACE , XI_STATE_STRING }, { XI_CHAR_SPACE , XI_STATE_STRING }, { XI_CHAR_SPACE , XI_STATE_STRING }, { XI_CHAR_SPACE , XI_STATE_STRING } },
xively 0:82702e998d3f 140 { { XI_CHAR_NEWLINE , XI_STATE_INITIAL }, { XI_CHAR_NEWLINE , XI_STATE_INITIAL }, { XI_CHAR_NEWLINE , XI_STATE_INITIAL }, { XI_CHAR_NEWLINE , XI_STATE_INITIAL }, { XI_CHAR_NEWLINE , XI_STATE_INITIAL }, { XI_CHAR_NEWLINE , XI_STATE_INITIAL } },
xively 0:82702e998d3f 141 { { XI_CHAR_TAB , XI_STATE_STRING }, { XI_CHAR_TAB , XI_STATE_STRING }, { XI_CHAR_TAB , XI_STATE_STRING }, { XI_CHAR_TAB , XI_STATE_STRING }, { XI_CHAR_TAB , XI_STATE_STRING }, { XI_CHAR_TAB , XI_STATE_STRING } },
xively 0:82702e998d3f 142 { { XI_CHAR_MINUS , XI_STATE_MINUS }, { XI_CHAR_MINUS , XI_STATE_STRING }, { XI_CHAR_MINUS , XI_STATE_STRING }, { XI_CHAR_MINUS , XI_STATE_STRING }, { XI_CHAR_MINUS , XI_STATE_STRING }, { XI_CHAR_MINUS , XI_STATE_STRING } }
xively 0:82702e998d3f 143 };
xively 0:82702e998d3f 144
xively 0:82702e998d3f 145 char c = *buffer;
xively 0:82702e998d3f 146 short s = XI_STATE_INITIAL;
xively 0:82702e998d3f 147
xively 0:82702e998d3f 148 while( c != '\n' && c !='\0' && c!='\r' )
xively 0:82702e998d3f 149 {
xively 0:82702e998d3f 150 if( counter >= XI_VALUE_STRING_MAX_SIZE - 1 )
xively 0:82702e998d3f 151 {
xively 0:82702e998d3f 152 xi_set_err( XI_DATAPOINT_VALUE_BUFFER_OVERFLOW );
xively 0:82702e998d3f 153 return 0;
xively 0:82702e998d3f 154 }
xively 0:82702e998d3f 155
xively 0:82702e998d3f 156 xi_char_type_t ct = csv_classify_char( c );
xively 0:82702e998d3f 157 s = states[ ct ][ s ][ 1 ];
xively 0:82702e998d3f 158
xively 0:82702e998d3f 159 switch( s )
xively 0:82702e998d3f 160 {
xively 0:82702e998d3f 161 case XI_STATE_MINUS:
xively 0:82702e998d3f 162 case XI_STATE_NUMBER:
xively 0:82702e998d3f 163 case XI_STATE_FLOAT:
xively 0:82702e998d3f 164 case XI_STATE_DOT:
xively 0:82702e998d3f 165 case XI_STATE_STRING:
xively 0:82702e998d3f 166 p->value.str_value[ counter ] = c;
xively 0:82702e998d3f 167 break;
xively 0:82702e998d3f 168 }
xively 0:82702e998d3f 169
xively 0:82702e998d3f 170 c = *( ++buffer );
xively 0:82702e998d3f 171 ++counter;
xively 0:82702e998d3f 172 }
xively 0:82702e998d3f 173
xively 0:82702e998d3f 174 // set the guard
xively 0:82702e998d3f 175 p->value.str_value[ counter ] = '\0';
xively 0:82702e998d3f 176
xively 0:82702e998d3f 177 // update of the state for loose states...
xively 0:82702e998d3f 178 switch( s )
xively 0:82702e998d3f 179 {
xively 0:82702e998d3f 180 case XI_STATE_MINUS:
xively 0:82702e998d3f 181 case XI_STATE_DOT:
xively 0:82702e998d3f 182 case XI_STATE_INITIAL:
xively 0:82702e998d3f 183 s = XI_STATE_STRING;
xively 0:82702e998d3f 184 break;
xively 0:82702e998d3f 185 }
xively 0:82702e998d3f 186
xively 0:82702e998d3f 187 switch( s )
xively 0:82702e998d3f 188 {
xively 0:82702e998d3f 189 case XI_STATE_NUMBER:
xively 0:82702e998d3f 190 p->value.i32_value = atoi( p->value.str_value );
xively 0:82702e998d3f 191 p->value_type = XI_VALUE_TYPE_I32;
xively 0:82702e998d3f 192 break;
xively 0:82702e998d3f 193 case XI_STATE_FLOAT:
xively 0:82702e998d3f 194 p->value.f32_value = atof( p->value.str_value );
xively 0:82702e998d3f 195 p->value_type = XI_VALUE_TYPE_F32;
xively 0:82702e998d3f 196 break;
xively 0:82702e998d3f 197 case XI_STATE_STRING:
xively 0:82702e998d3f 198 default:
xively 0:82702e998d3f 199 p->value_type = XI_VALUE_TYPE_STR;
xively 0:82702e998d3f 200 }
xively 0:82702e998d3f 201
xively 0:82702e998d3f 202 return p;
xively 0:82702e998d3f 203 }
xively 0:82702e998d3f 204
xively 0:82702e998d3f 205 const char* csv_encode_datapoint( const xi_datapoint_t* data )
xively 0:82702e998d3f 206 {
xively 0:82702e998d3f 207
xively 0:82702e998d3f 208 // PRECONDITIONS
xively 0:82702e998d3f 209 assert( data != 0 );
xively 0:82702e998d3f 210
xively 0:82702e998d3f 211 return csv_encode_datapoint_in_place( XI_CSV_LOCAL_BUFFER, sizeof( XI_CSV_LOCAL_BUFFER ), data ) == -1 ? 0 : XI_CSV_LOCAL_BUFFER;
xively 0:82702e998d3f 212 }
xively 0:82702e998d3f 213
xively 0:82702e998d3f 214 int csv_encode_datapoint_in_place(
xively 0:82702e998d3f 215 char* in, size_t in_size
xively 0:82702e998d3f 216 , const xi_datapoint_t* datapoint )
xively 0:82702e998d3f 217 {
xively 0:82702e998d3f 218 // PRECONDITIONS
xively 0:82702e998d3f 219 assert( in != 0 );
xively 0:82702e998d3f 220 assert( datapoint != 0 );
xively 0:82702e998d3f 221
xively 0:82702e998d3f 222 int s = 0;
xively 0:82702e998d3f 223 int size = in_size;
xively 0:82702e998d3f 224 int offset = 0;
xively 0:82702e998d3f 225
xively 0:82702e998d3f 226 if( datapoint->timestamp.timestamp != 0 )
xively 0:82702e998d3f 227 {
xively 0:82702e998d3f 228 time_t stamp = datapoint->timestamp.timestamp;
xively 0:82702e998d3f 229 struct tm* gmtinfo = xi_gmtime( &stamp );
xively 0:82702e998d3f 230
xively 0:82702e998d3f 231 s = snprintf( in, size
xively 0:82702e998d3f 232 , "%04d-%02d-%02dT%02d:%02d:%02d.%06dZ,"
xively 0:82702e998d3f 233 , gmtinfo->tm_year + 1900
xively 0:82702e998d3f 234 , gmtinfo->tm_mon + 1
xively 0:82702e998d3f 235 , gmtinfo->tm_mday
xively 0:82702e998d3f 236 , gmtinfo->tm_hour
xively 0:82702e998d3f 237 , gmtinfo->tm_min
xively 0:82702e998d3f 238 , gmtinfo->tm_sec
xively 0:82702e998d3f 239 , ( int ) datapoint->timestamp.micro );
xively 0:82702e998d3f 240
xively 0:82702e998d3f 241 XI_CHECK_S( s, size, offset, XI_CSV_ENCODE_DATAPOINT_BUFFER_OVERRUN );
xively 0:82702e998d3f 242 }
xively 0:82702e998d3f 243
xively 0:82702e998d3f 244 s = csv_encode_value( in + offset, size - offset, datapoint );
xively 0:82702e998d3f 245 XI_CHECK_S( s, size, offset, XI_CSV_ENCODE_DATAPOINT_BUFFER_OVERRUN );
xively 0:82702e998d3f 246
xively 0:82702e998d3f 247 s = snprintf( in + offset, size - offset, "%s", "\n" );
xively 0:82702e998d3f 248 XI_CHECK_S( s, size, offset, XI_CSV_ENCODE_DATAPOINT_BUFFER_OVERRUN );
xively 0:82702e998d3f 249
xively 0:82702e998d3f 250 return offset;
xively 0:82702e998d3f 251
xively 0:82702e998d3f 252 err_handling:
xively 0:82702e998d3f 253 return -1;
xively 0:82702e998d3f 254 }
xively 0:82702e998d3f 255
xively 0:82702e998d3f 256 const char* csv_encode_create_datastream(
xively 0:82702e998d3f 257 const char* datastream_id
xively 0:82702e998d3f 258 , const xi_datapoint_t* data )
xively 0:82702e998d3f 259 {
xively 0:82702e998d3f 260 // PRECONDITIONS
xively 0:82702e998d3f 261 assert( data != 0 );
xively 0:82702e998d3f 262
xively 0:82702e998d3f 263 int s = 0;
xively 0:82702e998d3f 264 int size = sizeof( XI_CSV_LOCAL_BUFFER );
xively 0:82702e998d3f 265 int offset = 0;
xively 0:82702e998d3f 266
xively 0:82702e998d3f 267 s = snprintf( XI_CSV_LOCAL_BUFFER + offset, size - offset
xively 0:82702e998d3f 268 , "%s,", datastream_id );
xively 0:82702e998d3f 269 XI_CHECK_S( s, size, offset, XI_CSV_ENCODE_DATASTREAM_BUFFER_OVERRUN );
xively 0:82702e998d3f 270
xively 0:82702e998d3f 271 s = csv_encode_value( XI_CSV_LOCAL_BUFFER + offset, size - offset, data );
xively 0:82702e998d3f 272 XI_CHECK_S( s, size, offset, XI_CSV_ENCODE_DATASTREAM_BUFFER_OVERRUN );
xively 0:82702e998d3f 273
xively 0:82702e998d3f 274 s = snprintf( XI_CSV_LOCAL_BUFFER + offset, size - offset, "\n" );
xively 0:82702e998d3f 275 XI_CHECK_S( s, size, offset, XI_CSV_ENCODE_DATASTREAM_BUFFER_OVERRUN );
xively 0:82702e998d3f 276
xively 0:82702e998d3f 277 return XI_CSV_LOCAL_BUFFER;
xively 0:82702e998d3f 278
xively 0:82702e998d3f 279 err_handling:
xively 0:82702e998d3f 280 return 0;
xively 0:82702e998d3f 281 }
xively 0:82702e998d3f 282
xively 0:82702e998d3f 283 xi_feed_t* csv_decode_feed(
xively 0:82702e998d3f 284 const char* buffer
xively 0:82702e998d3f 285 , xi_feed_t* feed )
xively 0:82702e998d3f 286 {
xively 0:82702e998d3f 287 const char* current = buffer;
xively 0:82702e998d3f 288 int32_t counter = 0;
xively 0:82702e998d3f 289
xively 0:82702e998d3f 290 // find occurence of newline
xively 0:82702e998d3f 291 char* end_of_line = ( char* ) 1;
xively 0:82702e998d3f 292
xively 0:82702e998d3f 293 // while we didn't jump out of the buffer
xively 0:82702e998d3f 294 while( end_of_line )
xively 0:82702e998d3f 295 {
xively 0:82702e998d3f 296 // get current datapoint
xively 0:82702e998d3f 297 xi_datastream_t* d = &feed->datastreams[ counter ];
xively 0:82702e998d3f 298 d->datapoint_count = 0;
xively 0:82702e998d3f 299 xi_datapoint_t* p = &d->datapoints[ 0 ];
xively 0:82702e998d3f 300 memset( p, 0, sizeof( xi_datapoint_t ) );
xively 0:82702e998d3f 301
xively 0:82702e998d3f 302 end_of_line = strstr( current, "\n" );
xively 0:82702e998d3f 303
xively 0:82702e998d3f 304 const char* end_of_datastream_id = strstr( current, "," );
xively 0:82702e998d3f 305 const char* beg_of_datapoint = end_of_datastream_id + 1;
xively 0:82702e998d3f 306
xively 0:82702e998d3f 307 XI_CHECK_ZERO( beg_of_datapoint, XI_CSV_DECODE_FEED_PARSER_ERROR );
xively 0:82702e998d3f 308 XI_CHECK_ZERO( end_of_datastream_id, XI_CSV_DECODE_FEED_PARSER_ERROR );
xively 0:82702e998d3f 309
xively 0:82702e998d3f 310 int size = sizeof( d->datastream_id );
xively 0:82702e998d3f 311
xively 0:82702e998d3f 312 int s = xi_str_copy_untiln( d->datastream_id, size
xively 0:82702e998d3f 313 , current, ',' );
xively 0:82702e998d3f 314 XI_CHECK_SIZE( s, size, XI_CSV_DECODE_FEED_PARSER_ERROR );
xively 0:82702e998d3f 315
xively 0:82702e998d3f 316 xi_datapoint_t* ret = csv_decode_datapoint( beg_of_datapoint, p );
xively 0:82702e998d3f 317 XI_CHECK_ZERO( ret, XI_CSV_DECODE_FEED_PARSER_ERROR )
xively 0:82702e998d3f 318
xively 0:82702e998d3f 319 d->datapoint_count = 1;
xively 0:82702e998d3f 320 current = end_of_line + 1;
xively 0:82702e998d3f 321
xively 0:82702e998d3f 322 XI_CHECK_CND( ++counter == XI_MAX_DATASTREAMS
xively 0:82702e998d3f 323 , XI_CSV_DECODE_FEED_PARSER_ERROR );
xively 0:82702e998d3f 324 }
xively 0:82702e998d3f 325
xively 0:82702e998d3f 326 feed->datastream_count = counter;
xively 0:82702e998d3f 327 return feed;
xively 0:82702e998d3f 328
xively 0:82702e998d3f 329 err_handling:
xively 0:82702e998d3f 330 return 0;
xively 0:82702e998d3f 331 }
xively 0:82702e998d3f 332
xively 0:82702e998d3f 333 xi_datapoint_t* csv_decode_datapoint(
xively 0:82702e998d3f 334 const char* buffer
xively 0:82702e998d3f 335 , xi_datapoint_t* datapoint )
xively 0:82702e998d3f 336 {
xively 0:82702e998d3f 337 // PRECONDITIONS
xively 0:82702e998d3f 338 assert( buffer != 0 );
xively 0:82702e998d3f 339 assert( datapoint != 0 );
xively 0:82702e998d3f 340
xively 0:82702e998d3f 341 int ye, mo, da, h, m, s, ms;
xively 0:82702e998d3f 342
xively 0:82702e998d3f 343 const char* beg_of_value = strstr( buffer, "," );
xively 0:82702e998d3f 344
xively 0:82702e998d3f 345 // check continuation condition
xively 0:82702e998d3f 346 XI_CHECK_ZERO( beg_of_value, XI_CSV_DECODE_DATAPOINT_PARSER_ERROR );
xively 0:82702e998d3f 347
xively 0:82702e998d3f 348 // move to pointer to the proper position
xively 0:82702e998d3f 349 beg_of_value += 1;
xively 0:82702e998d3f 350
xively 0:82702e998d3f 351 {
xively 0:82702e998d3f 352 int n = sscanf( buffer
xively 0:82702e998d3f 353 , "%04d-%02d-%02dT%02d:%02d:%02d.%06dZ"
xively 0:82702e998d3f 354 , &ye, &mo, &da, &h, &m, &s, &ms );
xively 0:82702e998d3f 355
xively 0:82702e998d3f 356 // check if the parser worked correctly
xively 0:82702e998d3f 357 XI_CHECK_CND( n != 7, XI_CSV_DECODE_DATAPOINT_PARSER_ERROR );
xively 0:82702e998d3f 358
xively 0:82702e998d3f 359 // copy parsed data
xively 0:82702e998d3f 360 {
xively 0:82702e998d3f 361 struct tm timeinfo;
xively 0:82702e998d3f 362
xively 0:82702e998d3f 363 timeinfo.tm_year = ye - 1900;
xively 0:82702e998d3f 364 timeinfo.tm_mon = mo - 1;
xively 0:82702e998d3f 365 timeinfo.tm_mday = da;
xively 0:82702e998d3f 366 timeinfo.tm_hour = h;
xively 0:82702e998d3f 367 timeinfo.tm_min = m;
xively 0:82702e998d3f 368 timeinfo.tm_sec = s;
xively 0:82702e998d3f 369
xively 0:82702e998d3f 370 time_t timestamp = xi_mktime( &timeinfo );
xively 0:82702e998d3f 371
xively 0:82702e998d3f 372 XI_CHECK_CND( ( int )timestamp == -1, XI_CSV_TIME_CONVERTION_ERROR );
xively 0:82702e998d3f 373
xively 0:82702e998d3f 374 datapoint->timestamp.timestamp = timestamp;
xively 0:82702e998d3f 375 datapoint->timestamp.micro = ms;
xively 0:82702e998d3f 376 }
xively 0:82702e998d3f 377 }
xively 0:82702e998d3f 378
xively 0:82702e998d3f 379 xi_datapoint_t* r = csv_decode_value( beg_of_value
xively 0:82702e998d3f 380 , datapoint );
xively 0:82702e998d3f 381
xively 0:82702e998d3f 382
xively 0:82702e998d3f 383 XI_CHECK_ZERO( r, XI_CSV_DECODE_DATAPOINT_PARSER_ERROR );
xively 0:82702e998d3f 384
xively 0:82702e998d3f 385 return datapoint;
xively 0:82702e998d3f 386
xively 0:82702e998d3f 387 err_handling:
xively 0:82702e998d3f 388 return 0;
xively 0:82702e998d3f 389 }