00001 // datafile.cc 00002 // SuperMix version 1.0 C++ source file 00003 // 00004 // Copyright (c) 1999 California Institute of Technology. 00005 // All rights reserved. 00006 // 00007 // Redistribution and use in source and binary forms for noncommercial 00008 // purposes are permitted provided that the above copyright notice and 00009 // this paragraph are duplicated in all such forms and that any 00010 // documentation and other materials related to such distribution and 00011 // use acknowledge that the software was developed by California 00012 // Institute of Technology. Redistribution and/or use in source or 00013 // binary forms is not permitted for any commercial purpose. Use of 00014 // this software does not include a permitted use of the Institute's 00015 // name or trademark for any purpose. 00016 // 00017 // DISCLAIMER: 00018 // THIS SOFTWARE AND/OR RELATED MATERIALS ARE PROVIDED "AS-IS" WITHOUT 00019 // WARRANTY OF ANY KIND INCLUDING ANY WARRANTIES OF PERFORMANCE OR 00020 // MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE OR PURPOSE (AS SET 00021 // FORTH IN UCC 23212-2313) OR FOR ANY PURPOSE WHATSOEVER, FOR THE 00022 // LICENSED PRODUCT, HOWEVER USED. IN NO EVENT SHALL CALTECH/JPL BE 00023 // LIABLE FOR ANY DAMAGES AND/OR COSTS, INCLUDING BUT NOT LIMITED TO 00024 // INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING ECONOMIC 00025 // DAMAGE OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF 00026 // WHETHER CALTECH/JPL SHALL BE ADVISED, HAVE REASON TO KNOW, OR IN 00027 // FACT SHALL KNOW OF THE POSSIBILITY. THE USER BEARS ALL RISK 00028 // RELATING TO QUALITY AND PERFORMANCE OF THE SOFTWARE AND/OR RELATED 00029 // MATERIALS. 00030 // 00031 // 00032 // has a bug: final line in datafile must terminate in '\n' or 00033 // it will be ignored. 00034 // 00035 // Change history: 00036 // 1/19/99: Fixed the file name arguments (added const) 00037 // 11/11/98: Changed table access to new syntax 00038 // 6/16/98: FR mods to elim String.h 00039 // 1/9/98: FR fixed up some things for latest table.cc 00040 00041 #include "datafile.h" 00042 #include "error.h" 00043 #include <stdio.h> // for snprintf() 00044 #include <stdlib.h> // for strtod() 00045 #include <strings.h> // for strchr() 00046 #include <ctype.h> // for isspace() 00047 #include <iostream.h> 00048 #include <fstream.h> // file version of iostream 00049 00050 // Maximum line length (in characters) we wish to process 00051 const unsigned int datafile::maxline = 32767 ; 00052 00053 // Maximum error message string length (in characters) 00054 const int msglen = 2000 ; 00055 00056 // Comment delimiters (may want to move to global.h) 00057 static char comment[] = "#!" ; 00058 00059 // fuctions to skip over whitespace or nonwhitespace chars 00060 static void skipwhite(char * & c) 00061 { while (*c && isspace(*c)) c++; return; } 00062 static void skipnonwhite(char * & c) 00063 { while (*c && !isspace(*c)) c++; return; } 00064 00065 // 00066 // datafile constructor 00067 // 00068 // The constructor initializes data table with zero lines, columns 00069 // it then reads in the data file, throwing out comments, and storing 00070 // all doubles it finds in a temporary list, along with the line and column 00071 // numbers associated with the double. It then creates a data table 00072 // large enough to hold all of the data, and fills it in from the list 00073 // (the list elements are then deleted). 00074 // The number of columns in the table is set to the *maximum* number of 00075 // columns found in the data file. If the lines in the file do not all 00076 // have the same number of columns, the table is padded with zeros for 00077 // the missing columns. (Columns are always filled in starting at 00078 // column 1.) 00079 00080 datafile::datafile(char const * const filename) : 00081 ncolumns(0), nlines(0), data(0) 00082 { 00083 ifstream infile(filename) ; 00084 if(!infile) { // couldn't open the file 00085 char errmsg[msglen] ; 00086 snprintf(errmsg, msglen, "Couldn't open data file: %s", filename); 00087 error::warning(errmsg) ; 00088 return ; 00089 } 00090 00091 // file opened OK, so let's read in the data 00092 00093 // we'll read lines into a freshly allocated char[] array... 00094 char * line = new char[maxline] ; 00095 00096 int iline = 0 ; // number of current line of data 00097 int file_line_number = 0 ; // number of current line in file 00098 tempnumber *head = 0 ; // first member in our temp data list 00099 00100 while(!infile.eof()) { 00101 int icol = 0 ; // a new line, so no columns yet 00102 file_line_number++ ; // keep track of where we are in file 00103 00104 // read the next line 00105 infile.get(line, maxline, '\n') ; 00106 // discard trailing '\n', check if line truncated and complain if so 00107 if (!infile.eof() && infile.get() != '\n') { 00108 // then there are additional chars on the line 00109 // discard them and final newline 00110 while (!infile.eof() && infile.get() != '\n') ; // discarding 00111 // then complain to the user 00112 char errmsg[msglen] ; 00113 snprintf(errmsg, msglen, 00114 "Line number %i in file: %s exceeds %i characters. Truncating!!", 00115 file_line_number, filename, maxline) ; 00116 error::warning(errmsg) ; 00117 } 00118 00119 // process the line 00120 char * c = line; // moving pointer within line 00121 char * next; // used to update c 00122 double value ; // holds converted doubles 00123 00124 while ( *c ) { // not '\0' 00125 skipwhite(c); // move c to next token in line 00126 00127 // a comment char effectively terminates the line 00128 if ( strchr(comment, *c) ) { 00129 // found a comment delimiter 00130 *c = '\0'; 00131 continue; 00132 } 00133 00134 // attempt to convert token to double, stored in value 00135 value = strtod(c, & next); 00136 if ( next == c ) { 00137 // then it's not a double, so skip it 00138 skipnonwhite(c); 00139 continue; 00140 } 00141 00142 // a valid double was found; store it in list and move on 00143 c = next; // skip over the parsed double 00144 if (icol == 0) iline++ ; // increment iline only once each line 00145 icol++ ; // now (icol,iline) are coordinates of this value 00146 tempnumber *temp = new tempnumber ; // allocate another link 00147 if(!temp) { // memory allocation failed 00148 // we're in trouble - function call may bomb (no memory) 00149 error::fatal( // but attempt to tell user 00150 "Out of memory in datafile constructor - file too large!!") ; 00151 } 00152 temp->value = value ; 00153 temp->icol = icol ; 00154 temp->iline = iline ; 00155 temp->next = head ; // update links 00156 head = temp ; 00157 00158 } // finished processing the line 00159 if (icol > ncolumns) ncolumns = icol; // update max column number 00160 00161 } // finished processing the file 00162 infile.close(); 00163 nlines = iline; 00164 00165 // now we need to check if there was really any data 00166 if(nlines == 0 || ncolumns == 0) { 00167 // an empty table 00168 char errmsg[msglen] ; 00169 snprintf(errmsg, msglen, 00170 "Didn't find any data in file: %s", 00171 filename) ; 00172 error::warning(errmsg) ; 00173 nlines = ncolumns = 0; // make sure both are zero 00174 return ; 00175 } 00176 00177 // allocate memory for table, using 1..N indexing, and fill it 00178 data.reallocate(ncolumns, nlines, Index_1, Index_1) ; 00179 // don't need this, already full of 0.0: data.fill(0.) ; 00180 tempnumber *temp = head ; 00181 tempnumber *trash ; 00182 while(temp) { 00183 data[temp->icol][temp->iline] = temp->value ; 00184 trash = temp ; temp = temp->next ; 00185 delete trash ; // recover heap memory 00186 } 00187 00188 // finally recover memory for character buffer 00189 delete [] line; 00190 00191 } 00192 00193 00194 // copy constructor - just initialize using data member copy constructors 00195 00196 datafile::datafile(const datafile &df) : 00197 ncolumns(df.ncolumns), nlines(df.nlines), data(df.data) 00198 { } 00199 00200 // assignment operator 00201 // not declared with const argument until table operator= is fixed -- fixed F.R. 00202 00203 datafile & datafile::operator=(const datafile & df) 00204 { 00205 if(this != &df) { // no self-assignment 00206 ncolumns = df.ncolumns ; 00207 nlines = df.nlines ; 00208 data.resize(0) = df.data ; // throw away old, copy the new table 00209 } 00210 return(*this) ; 00211 }
Please direct comments and corrections to
supermix@submm.caltech.edu
Go to the supermix home page
Generated by
1.2.7