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 namespace Isis {
00035 
00036   /**
00037    * Constructor
00038    * @param filename The name of the file where the table will be written
00039    */
00040   WriteTabular::WriteTabular(std::ostream &strm) : p_outfile(strm) {
00041     p_rows = 0;
00042     p_delimiter = ",";
00043     p_curCol = 0;
00044   }
00045 
00046   /**
00047    * Constructor
00048    * @param filename The name of the target file to contain the table, once
00049    *                 formatted
00050    * @param cols The Column headers, containing information about the Columns
00051    */
00052   WriteTabular::WriteTabular(std::ostream &strm, std::vector<Column> cols) : p_outfile(strm) {
00053     p_rows = 0;
00054     p_delimiter = ",";
00055     p_curCol = 0;
00056     SetColumns(cols);
00057   }
00058 
00059   /**
00060    * Sets the vector of Columns and writes out the first row of the file.
00061    *
00062    * @param cols A vector of Columns, setting the format of the table
00063    */
00064   void WriteTabular::SetColumns(std::vector <Column> cols) {
00065     for(unsigned int index = 0; index < cols.size(); index++) {
00066       Column thisCol = cols[index];
00067       std::string thisTitle = thisCol.Name();
00068 
00069       if(thisTitle.length() > thisCol.Width()) {
00070         std::string message = "Column header [" + thisTitle + "] is wider " +
00071                               "than the set width for column [" + iString((int)index) + "]";
00072         throw Isis::iException::Message(Isis::iException::User, message, _FILEINFO_);
00073       }
00074 
00075       int iteration = 0;
00076       while(thisTitle.length() < thisCol.Width()) {
00077         if(thisCol.Alignment() == Column::Left) {
00078           thisTitle += " ";
00079         }
00080         else if(thisCol.Alignment() == Column::Right ||
00081                 thisCol.Alignment() == Column::Decimal) {
00082           thisTitle = " " + thisTitle;
00083         }
00084         else {
00085           std::string message = "Alignment is improperly set";
00086           throw Isis::iException::Message(Isis::iException::User, message, _FILEINFO_);
00087         }
00088         iteration++;
00089       }//end while
00090 
00091       p_cols.push_back(thisCol);
00092       p_outfile << thisTitle;
00093       if(index < (cols.size() - 1)) {
00094         p_outfile << p_delimiter;
00095       }
00096     }//end for
00097     p_outfile << "\n";
00098   }//end function
00099 
00100   /**
00101    * Writes a blank space in the next column in the current row
00102    */
00103   void WriteTabular::Write() {
00104     Column thisCol = p_cols[p_curCol];
00105 
00106     std::string item = "";
00107 
00108     std::stringstream tempStream;
00109     tempStream.width(thisCol.Width());
00110     tempStream.fill(' ');
00111     tempStream << item;
00112     item = tempStream.str();
00113 
00114     if(p_curCol == 0) {
00115       p_rows++;
00116     }
00117 
00118     if(p_curCol < (p_cols.size() - 1)) {
00119       item += p_delimiter;
00120       p_curCol++;
00121     }
00122     else {
00123       item += "\n";
00124       p_curCol = 0;
00125     }
00126     p_outfile << item;
00127   }
00128 
00129   /**
00130    * Add an integer value to the next column in this row
00131    *
00132    * @param item The integer value to put in this column.
00133    */
00134   void WriteTabular::Write(int item) {
00135     Column thisCol = p_cols[p_curCol];
00136     if(thisCol.DataType() != Column::Integer &&
00137         thisCol.DataType() != Column::Pixel) {
00138       if(thisCol.DataType() == Column::Real ||
00139           thisCol.DataType() == Column::Pixel) {
00140         Write((double)item);
00141         return;
00142       }
00143       std::string message = "Wrong data type for this Column";
00144       throw Isis::iException::Message(Isis::iException::User, message, _FILEINFO_);
00145     }
00146     iString thisItem(item);
00147     if(thisItem.length() > thisCol.Width()) {
00148       thisItem = "*";
00149       while(thisItem.length() < thisCol.Width()) {
00150         thisItem += "*";
00151       }
00152     }
00153     std::stringstream tempStream;
00154     tempStream.width(thisCol.Width());
00155     tempStream.fill(' ');
00156 
00157     if(thisCol.Alignment() == Column::Left) {
00158       tempStream.setf(std::ios::left);
00159     }
00160     else tempStream.setf(std::ios::right);
00161 
00162     tempStream << thisItem;
00163     thisItem = tempStream.str();
00164 
00165     if(p_curCol == 0) {
00166       p_rows++;
00167     }
00168 
00169     if(p_curCol < (p_cols.size() - 1)) {
00170       thisItem += p_delimiter;
00171       p_curCol++;
00172     }
00173     else {
00174       thisItem += "\n";
00175       p_curCol = 0;
00176     }
00177     p_outfile << thisItem.c_str();
00178   }
00179 
00180   /**
00181    * Writes a string to the next column in the current row
00182    *
00183    * @param item The string to write out
00184    */
00185   void WriteTabular::Write(std::string item) {
00186     Column thisCol = p_cols[p_curCol];
00187     if(thisCol.DataType() != Column::String &&
00188         thisCol.DataType() != Column::Pixel) {
00189       std::string message = "Wrong data type for this Column";
00190       throw Isis::iException::Message(Isis::iException::User, message, _FILEINFO_);
00191     }
00192     if(item.length() > thisCol.Width()) {
00193       item = "*";
00194       while(item.length() < thisCol.Width()) {
00195         item += "*";
00196       }
00197     }
00198     std::stringstream tempStream;
00199     tempStream.width(thisCol.Width());
00200     tempStream.fill(' ');
00201 
00202     if(thisCol.Alignment() == Column::Left) {
00203       tempStream.setf(std::ios::left);
00204     }
00205     else tempStream.setf(std::ios::right);
00206 
00207     tempStream << item;
00208     item = tempStream.str();
00209 
00210     if(p_curCol == 0) {
00211       p_rows++;
00212     }
00213 
00214     if(p_curCol < (p_cols.size() - 1)) {
00215       item += p_delimiter;
00216       p_curCol++;
00217     }
00218     else {
00219       item += "\n";
00220       p_curCol = 0;
00221     }
00222     p_outfile << item;
00223   }
00224 
00225   /**
00226    * Writes a floating-point value out to the next column in the current row
00227    *
00228    * @param item The value to be printed out
00229    */
00230   void WriteTabular::Write(double item) {
00231     Column thisCol = p_cols[p_curCol];
00232     if(thisCol.DataType() != Column::Real &&
00233         thisCol.DataType() != Column::Pixel) {
00234       std::string message = "Wrong data type for this Column";
00235       throw Isis::iException::Message(Isis::iException::User, message, _FILEINFO_);
00236     }
00237 
00238     //Check for special pixels, if it's a pixel column
00239     if(thisCol.DataType() == Column::Pixel && IsSpecial(item)) {
00240       if(IsNullPixel(item)) {
00241         Write("Null");
00242         return;
00243       }
00244       if(IsHisPixel(item)) {
00245         Write("His");
00246         return;
00247       }
00248       if(IsHrsPixel(item)) {
00249         Write("Hrs");
00250         return;
00251       }
00252       if(IsLisPixel(item)) {
00253         Write("Lis");
00254         return;
00255       }
00256       if(IsLrsPixel(item)) {
00257         Write("Lrs");
00258         return;
00259       }
00260     }
00261 
00262     iString thisItem(item);
00263 
00264 
00265     if(thisCol.Alignment() == Column::Decimal) {
00266 
00267       //Format and round the number
00268 
00269       //First, split the number at the decimal point
00270       iString tempString = thisItem;
00271       iString intPart = tempString.Token(".");
00272       //Make the fractional portion appear as such, so the iomanipulators
00273       //handle it properly
00274       if(tempString != "") {
00275         tempString = "0." + tempString;
00276       }
00277       else tempString = "0.0";
00278 
00279       //Put the fractional portion into a stringstream, and use
00280       //stream manipulators to round it properly
00281       std::stringstream b;
00282       b << std::showpoint
00283         << std::setprecision(thisCol.Precision())
00284         << tempString.ToDouble();
00285 
00286       //if the rounding causes a rollover (i.e. the decimal portion is greater
00287       //than 0.95) increment the integer portion
00288       if(iString(b.str()).ToDouble() >= 1) {
00289         intPart = iString(intPart.ToInteger() + 1);
00290       }
00291 
00292       //Put it back into an iString, for easier manipulation
00293       tempString = b.str();
00294       tempString.Token(".");
00295       //Add any zeros necessary to pad the number
00296       while(tempString.size() < thisCol.Precision()) {
00297         tempString += "0";
00298       }
00299 
00300       //Put the number back together, adding the decimal point in the right location
00301       thisItem = intPart + "." + tempString;
00302     }
00303     std::stringstream tempStream;
00304     tempStream.width(thisCol.Width());
00305     tempStream.fill(' ');
00306 
00307     if(thisCol.Alignment() == Column::Left) {
00308       tempStream.setf(std::ios::left);
00309     }
00310     else tempStream.setf(std::ios::right);
00311 
00312     tempStream << thisItem;
00313     thisItem = tempStream.str();
00314 
00315     if(p_curCol == 0) {
00316       p_rows++;
00317     }
00318 
00319     //If the number is too wide for the column, replace with a string of stars
00320     if(thisItem.length() > thisCol.Width()) {
00321       thisItem = "*";
00322       while(thisItem.length() < thisCol.Width()) {
00323         thisItem += "*";
00324       }
00325     }
00326 
00327     if(p_curCol < (p_cols.size() - 1)) {
00328       thisItem += p_delimiter;
00329       p_curCol++;
00330     }
00331     else {
00332       thisItem += "\n";
00333       p_curCol = 0;
00334     }
00335     p_outfile << thisItem;
00336 
00337   }
00338 
00339   /**
00340    * Sets the string to be put between columns for this table
00341    *
00342    * @param delim The string to separate columns
00343    */
00344   void WriteTabular::SetDelimiter(std::string delim) {
00345     p_delimiter = delim;
00346   }
00347 
00348 }