00001
00008 #include "csv_reader.h"
00009
00010 CLASS *csv_reader::oclass = 0;
00011
00012 EXPORT int create_csv_reader(OBJECT **obj, OBJECT *parent){
00013 *obj = gl_create_object(csv_reader::oclass);
00014 if(*obj != NULL){
00015
00016 return 1;
00017 }
00018
00019 return 0;
00020 }
00021
00022 EXPORT int init_csv_reader(OBJECT **obj, OBJECT *parent){
00023 csv_reader *my = OBJECTDATA(obj,csv_reader);
00024 return 1;
00025 }
00026
00028 EXPORT TIMESTAMP sync_csv_reader(OBJECT *obj, TIMESTAMP t0){
00029 return TS_NEVER;
00030 }
00031
00032 csv_reader::csv_reader(){
00033 ;
00034 }
00035
00036 csv_reader::csv_reader(MODULE *module){
00037 memset(this, 0, sizeof(csv_reader));
00038 if (oclass==NULL)
00039 {
00040 oclass = gl_register_class(module,"csv_reader",sizeof(csv_reader),NULL);
00041 if (gl_publish_variable(oclass,
00042 PT_int32,"index",PADDR(index),PT_ACCESS,PA_REFERENCE,
00043 PT_char32,"city_name",PADDR(city_name),
00044 PT_char32,"state_name",PADDR(state_name),
00045 PT_double,"lat_deg",PADDR(lat_deg),
00046 PT_double,"lat_min",PADDR(lat_min),
00047 PT_double,"long_deg", PADDR(long_deg),
00048 PT_double,"long_min",PADDR(long_min),
00049 PT_double,"low_temp",PADDR(low_temp),PT_ACCESS,PA_REFERENCE,
00050 PT_double,"high_temp",PADDR(high_temp),PT_ACCESS,PA_REFERENCE,
00051 PT_double,"peak_solar",PADDR(peak_solar),PT_ACCESS,PA_REFERENCE,
00052 PT_enumeration,"status",PADDR(status),PT_ACCESS,PA_REFERENCE,
00053 PT_KEYWORD,"INIT",CR_INIT,
00054 PT_KEYWORD,"OPEN",CR_OPEN,
00055 PT_KEYWORD,"ERROR",CR_ERROR,
00056 PT_char32,"timefmt",PADDR(timefmt),
00057 PT_char32,"timezone",PADDR(timezone),
00058 PT_char256,"columns",PADDR(columns_str),
00059 PT_char256,"filename",PADDR(filename),
00060 NULL)<1) GL_THROW("unable to publish properties in %s",__FILE__);
00061 memset(this,0,sizeof(csv_reader));
00062 }
00063 }
00064
00068 int csv_reader::open(const char *file){
00069 char line[1024];
00070 char filename[128];
00071 int has_cols = 0;
00072 int linenum = 0;
00073 int i = 0;
00074 weather *wtr = 0;
00075
00076 if(file == 0){
00077 gl_error("csv_reader has no input file name!");
00078
00079
00080
00081
00082 return 0;
00083 }
00084
00085 strncpy(filename, file, 127);
00086 infile = fopen(filename, "r");
00087 if(infile == 0){
00088 gl_error("csv_reader could not open \'%s\' for input!", file);
00089
00090
00091
00092
00093
00094 return 0;
00095 }
00096
00097 if(columns_str[0] != 0){
00098 if(0 == read_header(columns_str)){
00099 gl_error("csv_reader::open ~ column header read failure from explicit headers");
00100 return 0;
00101 } else {
00102 has_cols = 1;
00103 }
00104 }
00105 while(fgets(line, 1024, infile) > 0){
00106 ++linenum;
00107
00108
00109 size_t _len = strlen(line);
00110 if(line[0] == '#'){
00111 continue;
00112 }
00113 else if(strlen(line) < 1){
00114 continue;
00115 }
00116 else if(line[0] == '$'){
00117 if(0 == read_prop(line+1)){
00118 gl_error("csv_reader::open ~ property read failure on line %i", linenum);
00119 return 0;
00120 } else {
00121 continue;
00122 }
00123 }
00124 else if(has_cols == 0){
00125 if(0 == read_header(line)){
00126 gl_error("csv_reader::open ~ column header read failure on line %i", linenum);
00127 return 0;
00128 } else {
00129 has_cols = 1;
00130 }
00131 } else {
00132 if(0 == read_line(line)){
00133 gl_error("csv_reader::open ~ data line read failure on line %i", linenum);
00134 return 0;
00135 } else {
00136 ++sample_ct;
00137 }
00138 }
00139 }
00140
00141
00142 samples = (weather**)malloc(sizeof(weather *) * (size_t) sample_ct);
00143 for(i = 0, wtr = weather_root; i < sample_ct && wtr != NULL; ++i, wtr=wtr->next){
00144 samples[i] = wtr;
00145 }
00146 sample_ct = i;
00147
00148
00149
00150 return 1;
00151 }
00152
00153 int csv_reader::read_prop(char *line){
00154 OBJECT *my = OBJECTHDR(this);
00155 char *split = strchr(line, '=');
00156 char propstr[256], valstr[256];
00157 PROPERTY *prop = 0;
00158
00159 if(split == NULL){
00160 gl_error("csv_reader::read_prop ~ missing \'=\' seperator");
00161
00162
00163
00164
00165 return 0;
00166 }
00167
00168 if(2 != sscanf(line, "%[^=]=%[^\n#]", propstr, valstr)){
00169 gl_error("csv_reader::read_prop ~ error reading property & value");
00170
00171
00172
00173
00174 return 0;
00175 }
00176
00177 prop = gl_find_property(oclass, propstr);
00178 if(prop == 0){
00179 gl_error("csv_reader::read_prop ~ unrecognized csv_reader property \'%s\'", propstr);
00180
00181
00182
00183
00184
00185 return 0;
00186 }
00187
00188
00189
00190
00191
00192
00193
00194 void *addr = (void *)((unsigned long long int)this + (unsigned long long int)prop->addr);
00195 if(prop->ptype == PT_double){
00196 if(1 != sscanf(valstr, "%lg", addr)){
00197 gl_error("csv_reader::read_prop ~ unable to set property \'%s\' to \'%s\'", propstr, valstr);
00198
00199
00200
00201
00202 return 0;
00203 }
00204 } else if(prop->ptype == PT_char32){
00205 strncpy((char *)addr, valstr, 32);
00206 } else {
00207 gl_error("csv_reader::read_prop ~ unable to convert property \'%s\' due to type restrictions", propstr);
00208
00209
00210
00211
00212
00213 return 0;
00214 }
00215 return 1;
00216 }
00217
00218 int csv_reader::read_header(char *line){
00219 struct cmnlist {
00220 char *name;
00221 PROPERTY *column;
00222 struct cmnlist *next;
00223 };
00224 char buffer[1024];
00225 int index = 0, start_idx = 0;
00226 int done = 0;
00227 int i = 0;
00228 PROPERTY *prop = 0;
00229 struct cmnlist *first = 0, *last = 0, *temp = 0;
00230
00231
00232
00233 memset(buffer, 0, 1024);
00234 strncpy(buffer, line, 1023);
00235
00236
00237 while(index < 1024 && 0 == done){
00238 while(buffer[index] != 0 && buffer[index] != ',' && buffer[index] != '\n' && buffer[index] != '\r' && buffer[index] != '#'){
00239 ++index;
00240 }
00241 if(buffer[index] == ','){
00242 buffer[index] = 0;
00243 ++index;
00244 }
00245 if(buffer[index] == '\n' || buffer[index] == '\r' || buffer[index] == '#'){
00246 buffer[index] = 0;
00247 }
00248
00249 temp = (struct cmnlist *)malloc(sizeof(struct cmnlist));
00250 temp->name = buffer+start_idx;
00251 temp->column = prop;
00252 temp->next = 0;
00253
00254 start_idx = index;
00255 ++column_ct;
00256
00257 if(first == 0){
00258 first = last = temp;
00259 } else {
00260 last->next = temp;
00261 last = temp;
00262 }
00263
00264 if(buffer[index] == 0 || buffer[index] == '\n' || buffer[index] == '\r'){
00265 done = 1;
00266 break;
00267 }
00268 }
00269
00270
00271 temp = first;
00272 columns = (PROPERTY **)malloc(sizeof(PROPERTY *) * (size_t)column_ct);
00273 while(temp != 0 && i < column_ct){
00274 temp->column = gl_find_property(weather::oclass, temp->name);
00275 if(temp->column == 0){
00276 gl_error("csv_reader::read_header ~ unable to find column property \'%s\''", temp->name);
00277
00278
00279
00280
00281 return 0;
00282 }
00283 columns[i] = temp->column;
00284 temp = temp->next;
00285 ++i;
00286 }
00287 return 1;
00288 }
00289
00290 int csv_reader::read_line(char *line){
00291 int done = 0;
00292 int col = 0;
00293 char buffer[1024];
00294 char *token = 0;
00295 weather *sample = new weather();
00296
00297
00298 strncpy(buffer, line, 1023);
00299 token = strtok(buffer, " ,\t\n\r");
00300
00301 if(token == 0){
00302 return 1;
00303 }
00304
00305 if(weather_root == 0){
00306 weather_root = sample;
00307 } else {
00308 weather_last->next = sample;
00309 }
00310 weather_last = sample;
00311
00312 if(timefmt[0] == 0){
00313 if(sscanf(token, "%d:%d:%d:%d:%d", &sample->month, &sample->day, &sample->hour, &sample->minute, &sample->second) < 1){
00314 gl_error("csv_reader::read_line ~ unable to read time string \'%s\' with default format", token);
00315
00316
00317
00318
00319 return 0;
00320 }
00321 } else {
00322 if(sscanf(token, timefmt, &sample->month, &sample->day, &sample->hour, &sample->minute, &sample->second) < 1){
00323 gl_error("csv_reader::read_line ~ unable to read time string \'%s\' with format \'%s\'", token, timefmt);
00324
00325
00326
00327
00328 return 0;
00329 }
00330 }
00331
00332
00333
00334 while((token=strtok(NULL, ",\n\r")) != 0 && col < column_ct){
00335 if(columns[col]->ptype == PT_double){
00336 double *dptr = (double *)((unsigned long long int)(columns[col]->addr) + (unsigned long long int)(sample));
00337 if(sscanf(token, "%lg", dptr) != 1){
00338 gl_error("csv_reader::read_line ~ unable to set value \'%s\' to double property \'%s\'", token, columns[col]->name);
00339
00340
00341
00342
00343 return 0;
00344 }
00345 }
00346 ++col;
00347 }
00348 return 1;
00349 }
00350
00351 TIMESTAMP csv_reader::get_data(TIMESTAMP t0, double *temp, double *humid, double *direct, double *diffuse, double *global, double *wind, double *rain, double *snow){
00352 DATETIME now, then;
00353
00354 int next_year = 0;
00355 int i = 0;
00356 int idx = index;
00357 int start = index;
00358
00359 int localres;
00360
00361 if(t0 < next_ts){
00362 return -next_ts;
00363 }
00364
00365 localres = gl_localtime(t0, &now);
00366
00367 if(next_ts == 0){
00368
00369 DATETIME guess_dt;
00370 TIMESTAMP guess_ts;
00371 int i;
00372 for(i = 0; i < sample_ct; ++i){
00373 guess_dt.year = now.year;
00374 guess_dt.month = samples[sample_ct-i-1]->month;
00375 guess_dt.day = samples[sample_ct-i-1]->day;
00376 guess_dt.hour = samples[sample_ct-i-1]->hour;
00377 guess_dt.minute = samples[sample_ct-i-1]->minute;
00378 guess_dt.second = samples[sample_ct-i-1]->second;
00379 strcpy(guess_dt.tz, now.tz);
00380
00381 guess_ts = (TIMESTAMP)gl_mktime(&guess_dt);
00382
00383 if(guess_ts <= t0){
00384 break;
00385 }
00386 }
00387 index = sample_ct - i - 1;
00388
00389 if(index > -1){
00390 *temp = samples[index]->temperature;
00391 *humid = samples[index]->humidity;
00392 *direct = samples[index]->solar_dir;
00393 *diffuse = samples[index]->solar_diff;
00394 *global = samples[index]->solar_global;
00395 *wind = samples[index]->wind_speed;
00396 *rain = samples[index]->rainfall;
00397 *snow = samples[index]->snowdepth;
00398 } else {
00399 *temp = samples[sample_ct - 1]->temperature;
00400 *humid = samples[sample_ct - 1]->humidity;
00401 *direct = samples[sample_ct - 1]->solar_dir;
00402 *diffuse = samples[sample_ct - 1]->solar_diff;
00403 *global = samples[sample_ct - 1]->solar_global;
00404 *wind = samples[sample_ct - 1]->wind_speed;
00405 *rain = samples[sample_ct - 1]->rainfall;
00406 *snow = samples[sample_ct - 1]->snowdepth;
00407 }
00408
00409 then.year = now.year + (index+1 == sample_ct ? 1 : 0);
00410 then.month = samples[(index+1)%sample_ct]->month;
00411 then.day = samples[(index+1)%sample_ct]->day;
00412 then.hour = samples[(index+1)%sample_ct]->hour;
00413 then.minute = samples[(index+1)%sample_ct]->minute;
00414 then.second = samples[(index+1)%sample_ct]->second;
00415 strcpy(then.tz, now.tz);
00416
00417 next_ts = (TIMESTAMP)gl_mktime(&then);
00418
00419
00420 return -next_ts;
00421 }
00422
00423 if(sample_ct == 1){
00424 next_ts += 365 * 24 * 3600;
00425 return -next_ts;
00426 }
00427
00428 do{
00429
00430 if(index+1 >= sample_ct){
00431 index = 0;
00432 } else {
00433 ++index;
00434 }
00435
00436 if(index+1 == sample_ct){
00437 next_year = 1;
00438 } else {
00439 next_year = 0;
00440 }
00441
00442 then.year = now.year + next_year;
00443 then.month = samples[(index+1)%sample_ct]->month;
00444 then.day = samples[(index+1)%sample_ct]->day;
00445 then.hour = samples[(index+1)%sample_ct]->hour;
00446 then.minute = samples[(index+1)%sample_ct]->minute;
00447 then.second = samples[(index+1)%sample_ct]->second;
00448 strcpy(then.tz, now.tz);
00449
00450
00451 next_ts = (TIMESTAMP)gl_mktime(&then);
00452 } while (next_ts < t0 && index != start);
00453
00454 *temp = samples[index]->temperature;
00455 *humid = samples[index]->humidity;
00456 *direct = samples[index]->solar_dir;
00457 *diffuse = samples[index]->solar_diff;
00458 *global = samples[index]->solar_global;
00459 *wind = samples[index]->wind_speed;
00460 *rain = samples[index]->rainfall;
00461 *snow = samples[index]->snowdepth;
00462
00463
00464 if(index == start){
00465 GL_THROW("something strange happened with the schedule in csv_reader");
00466
00467
00468
00469
00470
00471 }
00472
00473 return -next_ts;
00474 }
00475
00476