mummy
1.0.2
|
00001 //---------------------------------------------------------------------------- 00002 // 00003 // $Id: MummyLineOrientedTextFileReader.cxx 470 2009-06-12 17:43:02Z hoffman $ 00004 // 00005 // $Author: hoffman $ 00006 // $Date: 2009-06-12 13:43:02 -0400 (Fri, 12 Jun 2009) $ 00007 // $Revision: 470 $ 00008 // 00009 // Copyright (C) 2007 Kitware, Inc. 00010 // 00011 //---------------------------------------------------------------------------- 00012 00013 #include "MummyLineOrientedTextFileReader.h" 00014 #include "MummyLog.h" 00015 #include "MummySettings.h" 00016 00017 #include "gxsys/RegularExpression.hxx" 00018 #include "gxsys/ios/fstream" 00019 #include "gxsys/ios/sstream" 00020 00021 00022 //---------------------------------------------------------------------------- 00023 MummyLineOrientedTextFileReader::MummyLineOrientedTextFileReader() 00024 { 00025 //this->FileName; // correctly constructed empty 00026 //this->Lines; // correctly constructed empty 00027 this->ExcludeMarkedLines = false; 00028 //this->BeginExcludeRegex; // correctly constructed empty 00029 //this->EndExcludeRegex; // correctly constructed empty 00030 } 00031 00032 00033 //---------------------------------------------------------------------------- 00034 MummyLineOrientedTextFileReader::~MummyLineOrientedTextFileReader() 00035 { 00036 } 00037 00038 00039 //---------------------------------------------------------------------------- 00040 gxsys_stl::string MummyLineOrientedTextFileReader::GetFileName() 00041 { 00042 return this->FileName; 00043 } 00044 00045 00046 //---------------------------------------------------------------------------- 00047 void MummyLineOrientedTextFileReader::SetFileName(const char *filename) 00048 { 00049 if (filename) 00050 { 00051 this->FileName = filename; 00052 } 00053 else 00054 { 00055 this->FileName = ""; 00056 } 00057 00058 this->Update(); 00059 } 00060 00061 00062 //---------------------------------------------------------------------------- 00063 bool MummyLineOrientedTextFileReader::GetExcludeMarkedLines() 00064 { 00065 return this->ExcludeMarkedLines; 00066 } 00067 00068 00069 //---------------------------------------------------------------------------- 00070 void MummyLineOrientedTextFileReader::SetExcludeMarkedLines(bool excludeMarkedLines) 00071 { 00072 this->ExcludeMarkedLines = excludeMarkedLines; 00073 } 00074 00075 00076 //---------------------------------------------------------------------------- 00077 gxsys_stl::string MummyLineOrientedTextFileReader::GetBeginExcludeRegex() 00078 { 00079 return this->BeginExcludeRegex; 00080 } 00081 00082 00083 //---------------------------------------------------------------------------- 00084 void MummyLineOrientedTextFileReader::SetBeginExcludeRegex(const gxsys_stl::string& beginExcludeRegex) 00085 { 00086 this->BeginExcludeRegex = beginExcludeRegex; 00087 } 00088 00089 00090 //---------------------------------------------------------------------------- 00091 gxsys_stl::string MummyLineOrientedTextFileReader::GetEndExcludeRegex() 00092 { 00093 return this->EndExcludeRegex; 00094 } 00095 00096 00097 //---------------------------------------------------------------------------- 00098 void MummyLineOrientedTextFileReader::SetEndExcludeRegex(const gxsys_stl::string& endExcludeRegex) 00099 { 00100 this->EndExcludeRegex = endExcludeRegex; 00101 } 00102 00103 00104 //---------------------------------------------------------------------------- 00105 void MummyLineOrientedTextFileReader::Update() 00106 { 00107 gxsys_ios::ifstream file(this->GetFileName().c_str()); 00108 00109 this->Lines.clear(); 00110 00111 if (file) 00112 { 00113 char line[4100]; 00114 00115 bool trackBtxEtxLevel = !this->GetBeginExcludeRegex().empty() && 00116 !this->GetEndExcludeRegex().empty(); 00117 int btxEtxLevel = 0; 00118 bool isLineComment = false; 00119 00120 gxsys::RegularExpression reLineComment; 00121 reLineComment.compile("^[\\t ]*//"); 00122 00123 gxsys::RegularExpression reBTX; 00124 gxsys::RegularExpression reETX; 00125 if (trackBtxEtxLevel) 00126 { 00127 reBTX.compile(this->GetBeginExcludeRegex().c_str()); 00128 reETX.compile(this->GetEndExcludeRegex().c_str()); 00129 } 00130 // 00131 // Old hard-coded values were eerily similar to BTX/ETX regexes found in 00132 // the VTK source tree in Wrapping/vtkParse.l... ;) 00133 // 00134 //reBTX.compile("^[\\t ]*//BTX.*$"); 00135 //reETX.compile("^[\\t ]*//ETX.*$"); 00136 00137 while (!file.eof()) 00138 { 00139 line[0] = 0; 00140 file.getline(line, 4099); 00141 00142 isLineComment = reLineComment.find(line); 00143 00144 if (trackBtxEtxLevel && reBTX.find(line)) 00145 { 00146 btxEtxLevel++; 00147 } 00148 00149 this->Lines.push_back(LineData(line, isLineComment, btxEtxLevel)); 00150 00151 if (trackBtxEtxLevel && reETX.find(line)) 00152 { 00153 btxEtxLevel--; 00154 } 00155 } 00156 } 00157 00158 00159 #if 0 00160 // Dump it out with Trace to see what the settings and the output 00161 // data look like... This is a Print-method-in-waiting... 00162 // 00163 gxsys_stl::ostringstream oss; 00164 00165 oss << "FileName: " << this->FileName << gxsys_stl::endl; 00166 oss << "ExcludeMarkedLines: " << this->ExcludeMarkedLines << gxsys_stl::endl; 00167 oss << "BeginExcludeRegex: " << this->BeginExcludeRegex << gxsys_stl::endl; 00168 oss << "EndExcludeRegex: " << this->EndExcludeRegex << gxsys_stl::endl; 00169 00170 oss << "Lines:" << gxsys_stl::endl; 00171 00172 unsigned int i = 1; 00173 gxsys_stl::vector<LineData>::iterator itLines; 00174 00175 for (itLines = this->Lines.begin(); itLines != this->Lines.end(); 00176 ++itLines) 00177 { 00178 LineData line = *itLines; 00179 00180 // Comment? 00181 // 00182 if (line.IsLineComment) 00183 { 00184 oss << "C | "; 00185 } 00186 else 00187 { 00188 oss << " | "; 00189 } 00190 00191 // BTX/ETX level: 00192 // 00193 if (line.BtxEtxLevel) 00194 { 00195 00196 oss << line.BtxEtxLevel; 00197 00198 00199 oss << " | "; 00200 } 00201 else 00202 { 00203 oss << " | "; 00204 } 00205 00206 // Line number, i - 4 digits with leading zeroes: 00207 // 00208 char f = oss.fill(); 00209 gxsys_stl::streamsize w = oss.width(); 00210 oss.fill('0'); 00211 oss.width(4); 00212 oss << i; 00213 oss.fill(f); 00214 oss.width(w); 00215 00216 // The line itself: 00217 // 00218 oss << ": " << line.Line << gxsys_stl::endl; 00219 00220 ++i; 00221 } 00222 00223 Trace(oss.str().c_str()); 00224 #endif 00225 } 00226 00227 00228 //---------------------------------------------------------------------------- 00229 unsigned int MummyLineOrientedTextFileReader::GetNumberOfLines() 00230 { 00231 return static_cast<unsigned int>(this->Lines.size()); 00232 } 00233 00234 00235 //---------------------------------------------------------------------------- 00236 gxsys_stl::string MummyLineOrientedTextFileReader::GetLine(unsigned int lineNumber) 00237 { 00238 if (lineNumber<1 || lineNumber>this->GetNumberOfLines()) 00239 { 00240 LogWarning(mw_NoSuchLineNumber, "lineNumber out of range in GetLine"); 00241 return ""; 00242 } 00243 00244 return this->Lines.at(lineNumber-1).Line; 00245 } 00246 00247 00248 //---------------------------------------------------------------------------- 00249 bool MummyLineOrientedTextFileReader::GetIsLineComment(unsigned int lineNumber) 00250 { 00251 if (lineNumber<1 || lineNumber>this->GetNumberOfLines()) 00252 { 00253 LogWarning(mw_NoSuchLineNumber, "lineNumber out of range in GetIsLineComment"); 00254 return false; 00255 } 00256 00257 return this->Lines.at(lineNumber-1).IsLineComment; 00258 } 00259 00260 00261 //---------------------------------------------------------------------------- 00262 int MummyLineOrientedTextFileReader::GetBtxEtxLevel(unsigned int lineNumber) 00263 { 00264 if (lineNumber<1 || lineNumber>this->GetNumberOfLines()) 00265 { 00266 LogWarning(mw_NoSuchLineNumber, "lineNumber out of range in GetBtxEtxLevel"); 00267 return 0; 00268 } 00269 00270 return this->Lines.at(lineNumber-1).BtxEtxLevel; 00271 } 00272 00273 00274 //---------------------------------------------------------------------------- 00275 bool MummyLineOrientedTextFileReader::IsLineExcluded(unsigned int lineNumber) 00276 { 00277 return this->GetExcludeMarkedLines() && 00278 this->GetBtxEtxLevel(lineNumber) > 0; 00279 } 00280 00281 00282 //---------------------------------------------------------------------------- 00283 void MummyLineOrientedTextFileReader::GetCommentBlockBefore(unsigned int lineNumber, gxsys_stl::vector<gxsys_stl::string>& block, unsigned int smallestAcceptableLineNumber) 00284 { 00285 if (lineNumber<2 || lineNumber>this->GetNumberOfLines()) 00286 { 00287 LogWarning(mw_NoSuchLineNumber, "lineNumber out of range in GetCommentBlockBefore"); 00288 return; 00289 } 00290 00291 // We seek the comment block before a class or method declaration in a 00292 // header file. Like this line-numbered example from vtkObject.h: 00293 // 00294 // 52: 00295 // 53: // Description: 00296 // 54: // Create an object with Debug turned off, modified time initialized 00297 // 55: // to zero, and reference counting on. 00298 // 56: static vtkObject *New(); 00299 // 57: 00300 // 00301 // If given lineNumber==56 as input, we should compute begin==53 and end==55 00302 // and return the comment block as a vector of line strings from 00303 // begin to end inclusive... 00304 00305 unsigned int begin = 0; 00306 unsigned int end = 0; 00307 unsigned int i = lineNumber; 00308 00309 // Find the first comment before lineNumber, saving its index in 'end'. 00310 // If no line comments occur before lineNumber, end will be 0. 00311 // 00312 while (0 == end && i>1) 00313 { 00314 i--; 00315 if (GetIsLineComment(i) && 0==GetBtxEtxLevel(i)) 00316 { 00317 end = i; 00318 } 00319 } 00320 00321 // Now find the first non-comment before end, saving the index of the comment 00322 // line *after* it in 'begin'. 00323 // 00324 if (0 != end) 00325 { 00326 while (0 == begin && i>1) 00327 { 00328 i--; 00329 if (!GetIsLineComment(i) && 0==GetBtxEtxLevel(i)) 00330 { 00331 begin = i + 1; 00332 } 00333 } 00334 00335 // Didn't find a non-comment line before 'end'... Comment block must start 00336 // right at line 1. 00337 // 00338 if (0 == begin) 00339 { 00340 begin = 1; 00341 } 00342 } 00343 00344 // If end==0 then there are no comment lines prior to lineNumber. 00345 // 00346 if (0 == end) 00347 { 00348 LogFileLineWarningMsg(this->FileName.c_str(), lineNumber, mw_UndocumentedEntity, 00349 "No comment lines prior to line " << lineNumber << ". Undocumented class or method?"); 00350 } 00351 else if (smallestAcceptableLineNumber > begin) 00352 { 00353 block.push_back(std::string("//Undocumented Block")); 00354 } 00355 else 00356 { 00357 gxsys_stl::string s; 00358 00359 gxsys::RegularExpression reBeginsWithWhiteSpace; 00360 reBeginsWithWhiteSpace.compile("^([\\t ]*)[^\\t ].*"); 00361 size_t from = 0; 00362 size_t to = 0; 00363 00364 for (i= begin; i<=end; ++i) 00365 { 00366 s = GetLine(i); 00367 00368 if (reBeginsWithWhiteSpace.find(s)) 00369 { 00370 from = reBeginsWithWhiteSpace.match(1).size(); 00371 to = s.size() - from; 00372 s = s.substr(from, to); 00373 } 00374 00375 block.push_back(s); 00376 } 00377 } 00378 } 00379 00380 00381 //---------------------------------------------------------------------------- 00382 void MummyLineOrientedTextFileReader::GetFirstCommentBlock(gxsys_stl::vector<gxsys_stl::string>& block) 00383 { 00384 // Find the first non-comment line after the first comment line and use it 00385 // to call GetCommentBlockBefore... 00386 // 00387 unsigned int i = 1; 00388 unsigned int n = this->GetNumberOfLines(); 00389 bool foundFirstComment = false; 00390 00391 for (i= 1; i<=n; ++i) 00392 { 00393 if (this->GetIsLineComment(i) && 0==GetBtxEtxLevel(i)) 00394 { 00395 foundFirstComment = true; 00396 } 00397 else if (foundFirstComment) 00398 { 00399 this->GetCommentBlockBefore(i+1, block, 1); 00400 break; 00401 } 00402 } 00403 }