Csv::Csv(char * file_name , char * param_name ) { char * header ; char * next_field ; int len ; fileName_ = file_name ; len = strlen(param_name) ; if ((fp_ = fopen(file_name , "r")) == 0 ) { printf("ERROR: Couldn't open \"%s\"\n" , file_name ) ; exit(-1) ; } line_ = new char[20480] ; header = new char[20480] ; fgets( header , 20480 , fp_ ); // remove trailing newline header[strlen(header)-1] = '\0' ; field_num_ = 0 ; next_field = strtok( header , "," ) ; if ( strncmp(next_field , param_name, len) ) { field_num_++ ; while ((next_field = strtok( NULL , "," ))) { char *space_loc = strchr(next_field, ' '); int actual_name_len = space_loc - next_field; // need to make sure if the length of the parameter and the length // of the parameter found in the next_field are actually the same, // since strncmp(a.b.c_more, a.b.c, 5) results a.b.c_more equals a.b.c. if ( strncmp(next_field , param_name, len) || actual_name_len != len) { field_num_++ ; } else { /* found the parameter, get the units if there are any */ char * start_unit , * end_unit ; if ((start_unit = index( next_field , '{' ))) { end_unit = index( next_field , '}' ) ; end_unit[0] = '\0' ; if ( ! strcmp( param_name , "sys.exec.out.time" )) { unitTimeStr_ = start_unit + 1 ; } else { unitStr_ = map_trick_units_to_udunits(start_unit + 1) ; } } break ; } } } data_offset_ = ftell(fp_) ; delete[]header ; }
int Trick::VariableServerThread::var_units(std::string var_name, std::string units_name) { unsigned int ii ; for ( ii = 0 ; ii < vars.size() ; ii++ ) { if ( ! std::string(vars[ii]->ref->reference).compare(var_name) ) { if (!units_name.compare("xx")) { vars[ii]->ref->units = strdup(vars[ii]->ref->attr->units); } else if (!units_name.compare("--")) { vars[ii]->ref->units = strdup("1"); } else { std::string new_units = map_trick_units_to_udunits(units_name) ; if ( units_name.compare(new_units) ) { std::cout << "\033[33mUnits converted from [" << units_name << "] to [" << new_units << "] in Variable Server for " << var_name << "\033[0m" << std::endl ; } ut_unit * from = ut_parse(Trick::UdUnits::get_u_system(), vars[ii]->ref->attr->units, UT_ASCII) ; if ( !from ) { message_publish(MSG_ERROR, "Variable Server Error: var_units Units conversion error for \"%s\".\n", var_name.c_str()); return -1 ; } ut_unit * to = ut_parse(Trick::UdUnits::get_u_system(), new_units.c_str(), UT_ASCII) ; if ( !to ) { message_publish(MSG_ERROR, "Variable Server Error: var_units Units conversion error for \"%s\".\n", var_name.c_str()); return -1 ; } cv_converter * conversion_factor = ut_get_converter(from,to) ; if ( conversion_factor != NULL ) { // only assign conversion_factor if it is not NULL, otherwise leave previous value. vars[ii]->conversion_factor = conversion_factor ; } vars[ii]->ref->units = strdup(units_name.c_str()); ut_free(from) ; ut_free(to) ; } } } return(0) ; }
/* A private function for parsing log header files. * This is responsible for initialize the Log classes as well */ int LogGroup::parseLogHeaders() { int nVars; int lineNum; char *line; char *str1; char *str2; char *str3; char *str4; char *headerName; int i; int headerSize; int len; LogData *currLogData; Var *currVar; // Foreach log header for (i = 0; i < nHeaders_; i++) { // Allocate headerName len = strlen(pathToBinaryData_) + strlen(headers_[i]) + 2; headerName = new char[len]; // Full path of log header sprintf(headerName, "%s/%s", pathToBinaryData_, headers_[i]); // Open log header if ((fp_ = fopen(headerName, "r")) == NULL) { fprintf(stderr, "\nERROR:\nCouldn't open file \"%s\" \n", headerName); return (-1); } // Allocate strings, we know that buffers can't be // longer than file! // Since headers are typically small, allocate them at ] // the header size fseek(fp_, 0, SEEK_END); headerSize = ftell(fp_); ::rewind(fp_); line = new char[headerSize + 1]; // Not sure about +1 :) str1 = new char[headerSize + 1]; str2 = new char[headerSize + 1]; str3 = new char[headerSize + 1]; str4 = new char[headerSize + 1]; // Parse rest of file lineNum = 0; while (fgets(line, headerSize, fp_) != NULL) { lineNum++; /* <log_file_name> <data_type> <units> <param_name> or <log_file_name> byte_order is [lit|big]_endian */ if ( sscanf(line, "%s %s %s %s", str1, str2, str3, str4) == 4 ) { // Byte order statement and top of a log group? if (!strcmp(str2, "byte_order")) { LogData *ld = new LogData; log.push_back(ld); currLogData = log[nGroups_]; nGroups_++; // New binary file currLogData->setBinaryFileName(str1); // Set byte order if (!strcmp(str4, "big_endian")) { currLogData->dataByteOrder = 1; } else { currLogData->dataByteOrder = 0; } continue; } // Check for binary file name mismatches if (strcmp(str1, currLogData->getBinaryFileName())) { printf("ERROR: Parsing log header \"%s\".\n" " Line %d. Binary file name " "mismatch with \"%s\".\n" " May need little/big endian " "specification.\n\n", headerName, lineNum, currLogData->getBinaryFileName()); return (-1); } // New variable Var *v = new Var; currLogData->vars.push_back(v); nVars = currLogData->getNumVars(); currVar = currLogData->vars[nVars]; nVars++; currLogData->setNumVars(nVars); // Set Type if (currVar->setType(str2) < 0) { printf("ERROR: In log header \"%s\".\n" " Line %d. Type \"%s\" is " "not supported.\n", headerName, lineNum, str2); return (-1); } // For Release-07 we need to convert the old unit specs by // adding explicit asterisk for multiplication. ) { char new_units_spec[100]; new_units_spec[0] = 0; if ( convert_units_spec (str3, new_units_spec) != 0 ) { printf (" ERROR: Attempt to convert old units-spec, \"%s\" failed.\n\n",str3); return (-1); } delete [] str3; len = strlen(new_units_spec); str3 = new char[len + 1] ; strcpy(str3, new_units_spec); } // Initialize Unit class if ( ! strcmp(str3,"--")) { currVar->setUnit(str3); } else { currVar->setUnit(map_trick_units_to_udunits(str3)); } // Set Var Name currVar->setVarName(str4) ; if (currVar->getSize() < 0) { printf("ERROR: In log header \"%s\".\n" " Line %d. Problem with var " "name \"%s\" . \n", headerName, lineNum, str4); return (-1); } } } fclose(fp_); delete[]line; delete[]str1; delete[]str2; delete[]str3; delete[]str4; delete[]headerName; } return 1; }
void FieldDescription::parseComment(std::string comment) { std::string ret_str ; bool units_found = false ; bool io_found = false ; bool chkpnt_io_found = false ; unsigned int chkpnt_io ; if ( comment.empty() ) { // If the comment is empty default all I/O enabled. io = 15 ; return ; } if ( debug_level >= 5 ) { std::cout << "comment before " << comment << std::endl ; } // remove open comment chars comment = get_regex_field(comment , "^(//|/\\*)(.*)" , 2) ; //std::cout << "1. " << comment << std::endl ; // remove optional doxygen comment chars // Note: I had to use [ \t\n\r] for \s because the Mac don't understand! comment = get_regex_field(comment , "^((\\*|!)<)?[ \t\n\r]*(.*)" , 3) ; //std::cout << "2. " << comment << std::endl ; // remove optional doxygen keyword comment = get_regex_field(comment , "(\\\\\\w+[ \t\n\r]*)?(.*)" , 2) ; //std::cout << "3. " << comment << std::endl ; ret_str = get_regex_field(comment , "@?trick_chkpnt_io[\\({]([^\\)}]+)[\\)}]" , 1) ; if ( ! ret_str.empty()) { chkpnt_io = io_map[ret_str] ; //std::cout << "go for trick_chkpnt_io " << io << std::endl ; chkpnt_io_found = true ; comment = get_regex_field(comment , "(.*)@?trick_chkpnt_io[\\({]([^\\)}]+)[\\)}]" , 1) + get_regex_field(comment , "@?trick_chkpnt_io[\\({]([^\\)}]+)[\\)}](.*)" , 2) ; } ret_str = get_regex_field(comment , "@?trick_io[\\({]([^\\)}]+)[\\)}]" , 1) ; if ( ! ret_str.empty()) { io = io_map[ret_str] ; //std::cout << "go for trick_io " << io << std::endl ; io_found = true ; comment = get_regex_field(comment , "(.*)@?trick_io[\\({]([^\\)}]+)[\\)}]" , 1) + get_regex_field(comment , "@?trick_io[\\({]([^\\)}]+)[\\)}](.*)" , 2) ; } /* Units can include parenthesis now. We need to match the parenthesis in trick_units() to get the whole units string. */ std::size_t tu_string = comment.find("trick_units") ; if ( tu_string != std::string::npos ) { std::size_t ustart = tu_string + std::string("trick_units").length() ; std::size_t uend = ustart + 1 ; std::stack<char> parens ; parens.push( comment[ustart]); while ( ! parens.empty() and (uend < comment.length())) { switch ( comment[uend] ) { case '(': parens.push('(') ; break ; case ')': if (parens.top() == '(') { parens.pop() ; } break ; case '}': if (parens.top() == '{') { parens.pop() ; } break ; } uend++ ; } if ( parens.empty() ) { units = comment.substr(ustart + 1 , uend - ustart - 2) ; units_found = true ; // If we have "@trick_units" include the "@" sign for erasure. if ( tu_string > 0 and comment[tu_string-1] == '@' ) { tu_string -= 1 ; } comment.erase(tu_string , uend - tu_string) ; } else { std::cout << "unmatched parenthesis for trick_units" << std::endl ; } } if ( ! io_found ) { // Note: I had to use [ \t\n\r] for \s because the Mac don't understand! ret_str = get_regex_field(comment , "^[ \t\n\r]*(\\*io|\\*oi|\\*i|\\*o|\\*\\*)" , 1) ; //std::cout << "3. " << ret_str << std::endl ; if ( ! ret_str.empty()) { io = io_map[ret_str] ; //std::cout << "stand-alone io " << io << std::endl ; io_found = true ; comment = get_regex_field(comment , "^[ \t\n\r]*(\\*io|\\*oi|\\*i|\\*o|\\*\\*)[ \t\n\r]*(.*)" , 2) ; } } //std::cout << "3. " << comment << std::endl ; if ( ! units_found ) { ret_str = get_regex_field(comment , "^[ \t\n\r]*\\(([^\\)]*)\\)" , 1) ; if ( ! ret_str.empty()) { units = ret_str ; //std::cout << "stand-alone units " << units << std::endl ; units_found = true ; comment = get_regex_field(comment , "^[ \t\n\r]*\\(([^\\)]*)\\)(.*)" , 2) ; } else { ret_str = get_regex_field(comment , "^[ \t\n\r]*([^ \t\n\r)]*)" , 1) ; if ( ! ret_str.empty()) { units = ret_str ; //std::cout << "stand-alone units " << units << " " << comment << std::endl ; units_found = true ; comment = get_regex_field(comment , "^[ \t\n\r]*([^ \t\n\r)]*)(.*)" , 2) ; } } } // Test if we have valid units. We need to have found a units string and an io spec not zero // Possible todo is to create a map of valid units so we don't have to retest each string. if ( units_found and io != 0 and (valid_units.find(units) == valid_units.end())) { // remove spaces units.erase(remove_if(units.begin(), units.end(), isspace), units.end()); if ( !units.compare("--") ) { units = "1" ; } else { // map old unit names to new names std::string new_units = map_trick_units_to_udunits(units) ; if ( units.compare(new_units) ) { if ( ! units_truth_is_scary ) { std::cout << "\033[33mUnits converted from [" << units << "] to [" << new_units << "] " << file_name << ":" << line_no << "\033[0m" << std::endl ; } units = new_units ; } ut_unit * test_units = ut_parse(u_system, units.c_str() , UT_ASCII) ; if ( test_units == NULL ) { // If the units are invalid write an error message and change the units to "1" std::cout << "\033[31mBad units specification [" << units << "] " << file_name << ":" << line_no << "\033[0m" << std::endl ; units = "1" ; } else { // If the units are valid, free the memory allocated by new_units. ut_free(test_units) ; valid_units.insert(units) ; } } } if ( io == 4 ) { std::cout << "\033[33mWarning: " << file_name << ": line " << line_no << ": " << "\"--\" is not a valid trick_io value. Setting to *io (3)\033[0m" << std::endl ; io = 3 ; } if ( chkpnt_io_found == true ) { // If a checkpoint I/O spec is found add it to the io field. io |= (chkpnt_io << 2 ) ; } else { // else duplicated the io field to the chkpnt io field. io |= (io << 2 ) ; } // The rest of the comment is the description of the variable. // remove the c comment end marker. comment = get_regex_field(comment , "(.*)\\*/" , 1) ; // posix c regular expressions are terrible. the regexes above will leave "@" signs because // the regular expressions are so greedy. comment = get_regex_field(comment , "^[ \t\n\r@]+(.*)" , 1) ; // remove leading and trailing whitespace comment = trim(comment) ; // escape special characters, convert tabs and newlines to spaces, remove multiple spaces. std::ostringstream ss ; bool is_space = false ; for (std::string::iterator it = comment.begin(); it != comment.end(); it++) { switch (*it) { case '\\': ss << "\\\\"; is_space = false ; break; case '"': ss << "\\\""; is_space = false ; break; case '\b': ss << "\\b"; is_space = false ; break; case '\f': ss << "\\f"; is_space = false ; break; case '\n': case '\r': case '\t': case ' ': if ( ! is_space ) ss << " "; is_space = true ; break; default: ss << *it; is_space = false ; break; } } description = ss.str() ; }