USGS

Isis 3.0 Application Source Code Reference

Home

WriteTabular.cpp

Go to the documentation of this file.
00001 /**
00002  * @file
00003  * $Revision: 1.1 $
00004  * $Date: 2007/08/09 18:24:24 $
00005  *
00006  *   Unless noted otherwise, the portions of Isis written by the USGS are public
00007  *   domain. See individual third-party library and package descriptions for
00008  *   intellectual property information,user agreements, and related information.
00009  *
00010  *   Although Isis has been used by the USGS, no warranty, expressed or implied,
00011  *   is made by the USGS as to the accuracy and functioning of such software
00012  *   and related material nor shall the fact of distribution constitute any such
00013  *   warranty, and no responsibility is assumed by the USGS in connection
00014  *   therewith.
00015  *
00016  *   For additional information, launch
00017  *   $ISISROOT/doc//documents/Disclaimers/Disclaimers.html in a browser or see
00018  *   the Privacy & Disclaimers page on the Isis website,
00019  *   http://isis.astrogeology.usgs.gov, and the USGS privacy and disclaimers on
00020  *   http://www.usgs.gov/privacy.html.
00021  */
00022 
00023 #include <fstream>
00024 #include <iomanip>
00025 #include <iostream>
00026 #include <sstream>
00027 
00028 #include "WriteTabular.h"
00029 #include "IString.h"
00030 #include "Message.h"
00031 #include "IException.h"
00032 #include "SpecialPixel.h"
00033 
00034 using std::stringstream;
00035 
00036 namespace Isis {
00037 
00038   /**
00039    * Constructor
00040    * @param filename The name of the file where the table will be written
00041    */
00042   WriteTabular::WriteTabular(std::ostream &strm) : p_outfile(strm) {
00043     p_rows = 0;
00044     p_delimiter = ",";
00045     p_curCol = 0;
00046   }
00047 
00048   /**
00049    * Constructor
00050    * @param filename The name of the target file to contain the table, once
00051    *                 formatted
00052    * @param cols The Column headers, containing information about the Columns
00053    */
00054   WriteTabular::WriteTabular(std::ostream &strm, std::vector<Column> cols) : p_outfile(strm) {
00055     p_rows = 0;
00056     p_delimiter = ",";
00057     p_curCol = 0;
00058     SetColumns(cols);
00059   }
00060 
00061   /**
00062    * Sets the vector of Columns and writes out the first row of the file.
00063    *
00064    * @param cols A vector of Columns, setting the format of the table
00065    */
00066   void WriteTabular::SetColumns(std::vector <Column> cols) {
00067     for(unsigned int index = 0; index < cols.size(); index++) {
00068       Column thisCol = cols[index];
00069       QString thisTitle = thisCol.Name();
00070 
00071       if((int)thisTitle.length() > (int)thisCol.Width()) {
00072         QString message = "Column header [" + thisTitle + "] is wider " +
00073                               "than the set width for column [" + toString((int)index) + "]";
00074         throw IException(IException::User, message, _FILEINFO_);
00075       }
00076 
00077       int iteration = 0;
00078       while((int)thisTitle.length() < (int)thisCol.Width()) {
00079         if(thisCol.Alignment() == Column::Left) {
00080           thisTitle += " ";
00081         }
00082         else if(thisCol.Alignment() == Column::Right ||
00083                 thisCol.Alignment() == Column::Decimal) {
00084           thisTitle = " " + thisTitle;
00085         }
00086         else {
00087           QString message = "Alignment is improperly set";
00088           throw IException(IException::User, message, _FILEINFO_);
00089         }
00090         iteration++;
00091       }//end while
00092 
00093       p_cols.push_back(thisCol);
00094       p_outfile << thisTitle;
00095       if(index < (cols.size() - 1)) {
00096         p_outfile << p_delimiter;
00097       }
00098     }//end for
00099     p_outfile << "\n";
00100   }//end function
00101 
00102   /**
00103    * Writes a blank space in the next column in the current row
00104    */
00105   void WriteTabular::Write() {
00106     Column thisCol = p_cols[p_curCol];
00107 
00108     QString item = "";
00109 
00110     stringstream tempStream;
00111     tempStream.width(thisCol.Width());
00112     tempStream.fill(' ');
00113     tempStream << item;
00114     item = tempStream.str().c_str();
00115 
00116     if(p_curCol == 0) {
00117       p_rows++;
00118     }
00119 
00120     if(p_curCol < (p_cols.size() - 1)) {
00121       item += p_delimiter;
00122       p_curCol++;
00123     }
00124     else {
00125       item += "\n";
00126       p_curCol = 0;
00127     }
00128     p_outfile << item;
00129   }
00130 
00131   /**
00132    * Add an integer value to the next column in this row
00133    *
00134    * @param item The integer value to put in this column.
00135    */
00136   void WriteTabular::Write(int item) {
00137     Column thisCol = p_cols[p_curCol];
00138     if(thisCol.DataType() != Column::Integer &&
00139         thisCol.DataType() != Column::Pixel) {
00140       if(thisCol.DataType() == Column::Real ||
00141           thisCol.DataType() == Column::Pixel) {
00142         Write((double)item);
00143         return;
00144       }
00145       QString message = "Wrong data type for this Column";
00146       throw IException(IException::User, message, _FILEINFO_);
00147     }
00148     QString thisItem(toString(item));
00149     if(thisItem.length() > (int)thisCol.Width()) {
00150       thisItem = "*";
00151       while(thisItem.length() < (int)thisCol.Width()) {
00152         thisItem += "*";
00153       }
00154     }
00155     stringstream tempStream;
00156     tempStream.width(thisCol.Width());
00157     tempStream.fill(' ');
00158 
00159     if(thisCol.Alignment() == Column::Left) {
00160       tempStream.setf(std::ios::left);
00161     }
00162     else tempStream.setf(std::ios::right);
00163 
00164     tempStream << thisItem;
00165     thisItem = tempStream.str().c_str();
00166 
00167     if(p_curCol == 0) {
00168       p_rows++;
00169     }
00170 
00171     if(p_curCol < (p_cols.size() - 1)) {
00172       thisItem += p_delimiter;
00173       p_curCol++;
00174     }
00175     else {
00176       thisItem += "\n";
00177       p_curCol = 0;
00178     }
00179     p_outfile << thisItem;
00180   }
00181 
00182   /**
00183    * Writes a string to the next column in the current row
00184    *
00185    * @param item The string to write out
00186    */
00187   void WriteTabular::Write(const char *itemCStr) {
00188     Column thisCol = p_cols[p_curCol];
00189     if(thisCol.DataType() != Column::String &&
00190         thisCol.DataType() != Column::Pixel) {
00191       QString message = "Wrong data type for this Column";
00192       throw IException(IException::User, message, _FILEINFO_);
00193     }
00194 
00195     QString item(itemCStr);
00196     if(item.length() > (int)thisCol.Width()) {
00197       item = "*";
00198       while(item.length() < (int)thisCol.Width()) {
00199         item += "*";
00200       }
00201     }
00202     stringstream tempStream;
00203     tempStream.width(thisCol.Width());
00204     tempStream.fill(' ');
00205 
00206     if(thisCol.Alignment() == Column::Left) {
00207       tempStream.setf(std::ios::left);
00208     }
00209     else tempStream.setf(std::ios::right);
00210 
00211     tempStream << item;
00212     item = tempStream.str().c_str();
00213 
00214     if(p_curCol == 0) {
00215       p_rows++;
00216     }
00217 
00218     if(p_curCol < (p_cols.size() - 1)) {
00219       item += p_delimiter;
00220       p_curCol++;
00221     }
00222     else {
00223       item += "\n";
00224       p_curCol = 0;
00225     }
00226     p_outfile << item;
00227   }
00228 
00229   /**
00230    * Writes a floating-point value out to the next column in the current row
00231    *
00232    * @param item The value to be printed out
00233    */
00234   void WriteTabular::Write(double item) {
00235     Column thisCol = p_cols[p_curCol];
00236     if(thisCol.DataType() != Column::Real &&
00237         thisCol.DataType() != Column::Pixel) {
00238       QString message = "Wrong data type for this Column";
00239       throw IException(IException::User, message, _FILEINFO_);
00240     }
00241 
00242     //Check for special pixels, if it's a pixel column
00243     if(thisCol.DataType() == Column::Pixel && IsSpecial(item)) {
00244       if(IsNullPixel(item)) {
00245         Write("Null");
00246         return;
00247       }
00248       if(IsHisPixel(item)) {
00249         Write("His");
00250         return;
00251       }
00252       if(IsHrsPixel(item)) {
00253         Write("Hrs");
00254         return;
00255       }
00256       if(IsLisPixel(item)) {
00257         Write("Lis");
00258         return;
00259       }
00260       if(IsLrsPixel(item)) {
00261         Write("Lrs");
00262         return;
00263       }
00264     }
00265 
00266     QString thisItem(toString(item));
00267 
00268 
00269     if(thisCol.Alignment() == Column::Decimal) {
00270 
00271       //Format and round the number
00272 
00273       //First, split the number at the decimal point
00274       QStringList tempString = thisItem.split(".");
00275       QString intPart = tempString.takeFirst();
00276 
00277       //Make the fractional portion appear as such, so the iomanipulators
00278       //handle it properly
00279       if(!tempString.isEmpty()) {
00280         tempString.prepend("0");
00281       }
00282       else {
00283         tempString.append("0");
00284         tempString.append("0");
00285       }
00286 
00287       //Put the fractional portion into a stringstream, and use
00288       //stream manipulators to round it properly
00289       stringstream b;
00290       b << std::showpoint
00291         << std::setprecision(thisCol.Precision())
00292         << toDouble(tempString.join("."));
00293 
00294       //if the rounding causes a rollover (i.e. the decimal portion is greater
00295       //than 0.95) increment the integer portion
00296       if(toDouble(QString(b.str().c_str())) >= 1) {
00297         intPart = toString(toInt(intPart) + 1);
00298       }
00299 
00300       //Put it back into an QString, for easier manipulation
00301       QString tempString2 = b.str().c_str();
00302       tempString2.remove(QRegExp("[^.]*\\."));
00303       //Add any zeros necessary to pad the number
00304       while(tempString2.size() < (int)thisCol.Precision()) {
00305         tempString2 += "0";
00306       }
00307 
00308       //Put the number back together, adding the decimal point in the right location
00309       thisItem = intPart + "." + tempString2;
00310     }
00311     stringstream tempStream;
00312     tempStream.width(thisCol.Width());
00313     tempStream.fill(' ');
00314 
00315     if(thisCol.Alignment() == Column::Left) {
00316       tempStream.setf(std::ios::left);
00317     }
00318     else tempStream.setf(std::ios::right);
00319 
00320     tempStream << thisItem;
00321     thisItem = tempStream.str().c_str();
00322 
00323     if(p_curCol == 0) {
00324       p_rows++;
00325     }
00326 
00327     //If the number is too wide for the column, replace with a string of stars
00328     if(thisItem.length() > (int)thisCol.Width()) {
00329       thisItem = "*";
00330       while(thisItem.length() < (int)thisCol.Width()) {
00331         thisItem += "*";
00332       }
00333     }
00334 
00335     if(p_curCol < (p_cols.size() - 1)) {
00336       thisItem += p_delimiter;
00337       p_curCol++;
00338     }
00339     else {
00340       thisItem += "\n";
00341       p_curCol = 0;
00342     }
00343     p_outfile << thisItem;
00344 
00345   }
00346 
00347   /**
00348    * Sets the string to be put between columns for this table
00349    *
00350    * @param delim The string to separate columns
00351    */
00352   void WriteTabular::SetDelimiter(QString delim) {
00353     p_delimiter = delim;
00354   }
00355 
00356 }