Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

datafile.cc

Go to the documentation of this file.
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 doxygen1.2.7