PlasCom2  1.0
XPACC Multi-physics simluation application
DiffDataFiles.C
Go to the documentation of this file.
1 #include <sstream>
7 #include <fstream>
8 #include <iomanip>
9 #include <math.h>
10 
11 #include "UnixUtils.H"
12 #include "ComLine.H"
13 #include "FDUtils.H"
14 #include "DiffDataFiles.H"
15 
16 namespace ix
17 {
18  bool isNumber(std::string sCheck){
19  if(sCheck == "")
20  return false;
21  for(int i=0; i < sCheck.size();i++){
22  if(!isdigit(sCheck[i]) && sCheck[i] != 'e' && sCheck[i] != 'E'
23  && sCheck[i] != '.' && sCheck[i] != '+' && sCheck[i] != '-'){
24  return false;
25  }
26  }
27  return true;
28  }
29 
30  int DiffDataFiles(int argc,char *argv[])
31  {
32 
33  DDFComLine comline((const char **)(argv));
34  // The call to comline.Initialize() reads the command line arguments
35  // from the array passed in the previous line.
36  comline.Initialize();
37  // The ProcessOptions() call does detailed examination of the command
38  // line arguments to check for user errors or other problems. This call
39  // will return non-zero if there were errors on the commandline.
40  int clerr = comline.ProcessOptions();
41  // Check if the user just wanted to get the help and exit
42  if(!comline.GetOption("help").empty()){
43  // Print out the "long usage" (i.e. help) message to stdout
44  std::cout << comline.LongUsage() << std::endl;
45  return(0);
46  }
47  if(clerr){
48  std::cout << comline.ErrorReport() << std::endl
49  << std::endl << comline.ShortUsage() << std::endl;
50  return(1);
51  }
52 
53  // These outstreams allow the output to file to be set up and separated
54  // from the stdout.
55  std::ofstream Ouf;
56  std::ostream *Out = &std::cout;
57 
58  // The next few lines populate some strings based on the
59  // users input from the commandline.
60  std::string OutFileName(comline.GetOption("output"));
61  std::vector<std::string> FileNames = comline.GetArgs();
62  std::string sverb(comline.GetOption("verblevel"));
63  std::string sTolerance(comline.GetOption("tolerance"));
64  std::string sNoBlank(comline.GetOption("blank"));
65 
66  int retval = 0;
67 
68  // The following block parses and sets the verbosity level
69  int verblevel = 1;
70  if(!sverb.empty()){
71  if(sverb != ".true."){
72  std::istringstream Istr(sverb);
73  Istr >> verblevel;
74  if(verblevel < 0)
75  verblevel = 1;
76  }
77  }
78 
79  // If the user only wants to compare numbers in the file set the bool for that
80  bool numbers = false;
81  if(!comline.GetOption("numbers").empty()){
82  numbers = true;
83  }
84 
85  // If there is a tolerance set the bool and convert the tolerance to a double
86  bool useTol = false;
87  double tolerance = 1.0e-12;
88  if(!sTolerance.empty()){
89  useTol = true;
90  if(sTolerance != ".true."){
91  std::istringstream Istr(sTolerance);
92  Istr >> tolerance;
93  }
94  }
95  //The tolerance flag must be used if the numbers flag is used
96  else if(numbers){
97  useTol = true;
98  }
99 
100  // If the flag to ignore blank space is used set the bool
101  bool noBlank = false;
102  if(!sNoBlank.empty())
103  noBlank = true;
104 
105  if(verblevel > 2){
106  std::cout << "ix::DiffDataFiles> Starting up with the following environment:" << std::endl
107  << "ix::DiffDataFiles> FileName1 = " << FileNames[0] << std::endl
108  << "ix::DiffDataFiles> FileName2 = " << FileNames[1] << std::endl
109  << "ix::DiffDataFiles> Verbosity = " << verblevel << std::endl
110  << "ix::DiffDataFiles> OutFileName = " << OutFileName << std::endl
111  << "ix::DiffDataFiles> IgnoreBlank = " << noBlank << std::endl
112  << "ix::DiffDataFiles> NumbersOnly = " << numbers << std::endl
113  << "ix::DiffDataFiles> Tolerance = ";
114  if(useTol)
115  std::cout << tolerance;
116  std::cout << std::endl;
117  }
118 
119  // This block sets up the output file if the user specified one
120  bool keep_outfile = false;
121  if(!OutFileName.empty()){
122  keep_outfile = true;
123  Ouf.open(OutFileName.c_str());
124  if(!Ouf){
125  std::cout << "ix::DiffDataFiles> Error: Could not open output file, "
126  << OutFileName << " for output. Exiting (fail)." << std::endl;
127  return(1);
128  }
129  Out = &Ouf;
130  }
131 
132  // Open the two files for reading
133  std::ifstream InFile1;
134  std::ifstream InFile2;
135 
136  InFile1.open(FileNames[0].c_str());
137  if(!InFile1){
138  std::cout << "ix::DiffDataFiles> Error: Could not open input file, "
139  << FileNames[0] << " for reading. Exiting (fail)." << std::endl;
140  return(1);
141  }
142  InFile2.open(FileNames[1].c_str());
143  if(!InFile2){
144  std::cout << "ix::DiffDataFiles> Error: Could not open input file, "
145  << FileNames[1] << " for reading. Exiting (fail)." << std::endl;
146  return(1);
147  }
148 
149  // Read in the two files and compare
150  std::string line1,line2, string1, string2, printString1="", printString2="";
151  std::stringstream ss1, ss2, ssPrint1, ssPrint2;
152  int lineNo = 0;
153  bool lineDiff = false, numDiff = false;
154  *Out << "File line: content" << std::endl;
155  while(!InFile1.eof() || !InFile2.eof()){
156  lineNo++;
157  if(!InFile1.eof())
158  std::getline(InFile1,line1);
159  if(!InFile2.eof())
160  std::getline(InFile2,line2);
161  //compare line by line as strings(including white space)
162  if(!noBlank && !useTol){
163  if(line1 != line2){
164  ssPrint1 << line1;
165  ssPrint2 << line2;
166  lineDiff = true;
167  retval = 1;
168  }
169  }
170  //compare each individual word in the file
171  else{
172  ss1 << line1;
173  ss2 << line2;
174  while(ss1 >> string1){
175  ss2 >> string2;
176  if(string1 != string2){
177  if(useTol){
178  if(!isNumber(string1) || !isNumber(string2)){
179  if(!numbers)
180  numDiff = true;
181  }
182  else{
183  std::stringstream convert;
184  double val1, val2;
185  convert << string1;
186  convert >> val1;
187  convert.clear();
188  convert.str("");
189  convert << string2;
190  convert >> val2;
191  if(fabs(val1 - val2) > tolerance)
192  numDiff = true;
193  else{
194  ssPrint1 << std::scientific << std::setw(20) << val1 << " ";
195  ssPrint2 << std::scientific << std::setw(20) << val2 << " ";
196  }
197  }
198  }
199  if(!useTol || numDiff){
200  lineDiff = true;
201  retval = 1;
202  printString1 += '[' + string1 + "]";
203  printString2 += '[' + string2 + "]";
204  ssPrint1 << std::setw(20) << printString1 << " ";
205  ssPrint2 << std::setw(20) << printString2 << " ";
206  }
207  }
208  else{
209  ssPrint1 << std::setw(20) << string1 << " ";
210  ssPrint2 << std::setw(20) << string2 << " ";
211  }
212  string1 = string2 = "";
213  printString1 = printString2 = "";
214  numDiff = false;
215  }
216  while(ss2 >> string2){
217  if(isNumber(string2) || !numbers){
218  lineDiff = true;
219  printString1 += '[' + string1 + "]";
220  printString2 += '[' + string2 + "]";
221  ssPrint1 << std::setw(20) << printString1 << " ";
222  ssPrint2 << std::setw(20) << printString2 << " ";
223  retval = 1;
224  }
225  }
226  printString1 = printString2 = string2 = "";
227  }
228  if(lineDiff){
229  *Out << std::setw(4) << std::right << "1" << " " << std::setw(8)
230  << lineNo << ": " << ssPrint1.str() << std::endl
231  << std::setw(4) << std::right << "2" << " " << std::setw(8)
232  << lineNo << ": " << ssPrint2.str() << std::endl;
233  }
234  ss1.clear();
235  ss2.clear();
236  ss1.str("");
237  ss2.str("");
238  ssPrint1.clear();
239  ssPrint2.clear();
240  ssPrint1.str("");
241  ssPrint2.str("");
242  lineDiff = false;
243  }
244  if(InFile1.eof() != InFile2.eof()){
245  retval = 1;
246  }
247 
248  if(keep_outfile)
249  Ouf.close();
250 
251  return(retval);
252  }
253 };
254 
255 
256 int main(int argc,char *argv[])
257 {
258  return(ix::DiffDataFiles(argc,argv));
259 }
int ProcessOptions()
Processes all command line tokens.
Definition: ComLine.C:330
std::string ErrorReport()
Error reporting.
Definition: ComLine.C:473
std::string GetOption(const char &s)
Get the value of an option.
Definition: ComLine.H:291
void Initialize()
virtual function for program specific Initialization.
Definition: DiffDataFiles.H:25
Defines MPI-specific parallel global and program classes.
Implements a command-line interface for ensuring that two data files are consistent.
std::vector< std::string > GetArgs() const
Argument access.
Definition: ComLine.H:314
bool isNumber(std::string sCheck)
Definition: DiffDataFiles.C:18
int DiffDataFiles(int argc, char *argv[])
Compare two data files within a given tolerance.
Definition: DiffDataFiles.C:30
ComLineObject header.
Unix System Tools interface.
Implementation of stream object for Unix file descriptors.
std::string LongUsage()
Generate long usage string.
Definition: ComLine.C:188
ComLine object for test running utility.
Definition: DiffDataFiles.H:16
int main(int argc, char *argv[])
std::string ShortUsage()
Generate short usage string.
Definition: ComLine.C:244