mummy  1.0.3
MummyLineOrientedTextFileReader.cxx
Go to the documentation of this file.
1 //----------------------------------------------------------------------------
2 //
3 // $Id: MummyLineOrientedTextFileReader.cxx 470 2009-06-12 17:43:02Z hoffman $
4 //
5 // $Author: hoffman $
6 // $Date: 2009-06-12 13:43:02 -0400 (Fri, 12 Jun 2009) $
7 // $Revision: 470 $
8 //
9 // Copyright (C) 2007 Kitware, Inc.
10 //
11 //----------------------------------------------------------------------------
12 
14 #include "MummyLog.h"
15 #include "MummySettings.h"
16 
17 #include "gxsys/RegularExpression.hxx"
18 #include "gxsys/ios/fstream"
19 #include "gxsys/ios/sstream"
20 
21 
22 //----------------------------------------------------------------------------
24 {
25  //this->FileName; // correctly constructed empty
26  //this->Lines; // correctly constructed empty
27  this->ExcludeMarkedLines = false;
28  //this->BeginExcludeRegex; // correctly constructed empty
29  //this->EndExcludeRegex; // correctly constructed empty
30 }
31 
32 
33 //----------------------------------------------------------------------------
35 {
36 }
37 
38 
39 //----------------------------------------------------------------------------
41 {
42  return this->FileName;
43 }
44 
45 
46 //----------------------------------------------------------------------------
48 {
49  if (filename)
50  {
51  this->FileName = filename;
52  }
53  else
54  {
55  this->FileName = "";
56  }
57 
58  this->Update();
59 }
60 
61 
62 //----------------------------------------------------------------------------
64 {
65  return this->ExcludeMarkedLines;
66 }
67 
68 
69 //----------------------------------------------------------------------------
71 {
72  this->ExcludeMarkedLines = excludeMarkedLines;
73 }
74 
75 
76 //----------------------------------------------------------------------------
78 {
79  return this->BeginExcludeRegex;
80 }
81 
82 
83 //----------------------------------------------------------------------------
84 void MummyLineOrientedTextFileReader::SetBeginExcludeRegex(const gxsys_stl::string& beginExcludeRegex)
85 {
86  this->BeginExcludeRegex = beginExcludeRegex;
87 }
88 
89 
90 //----------------------------------------------------------------------------
92 {
93  return this->EndExcludeRegex;
94 }
95 
96 
97 //----------------------------------------------------------------------------
98 void MummyLineOrientedTextFileReader::SetEndExcludeRegex(const gxsys_stl::string& endExcludeRegex)
99 {
100  this->EndExcludeRegex = endExcludeRegex;
101 }
102 
103 
104 //----------------------------------------------------------------------------
106 {
107  gxsys_ios::ifstream file(this->GetFileName().c_str());
108 
109  this->Lines.clear();
110 
111  if (file)
112  {
113  char line[4100];
114 
115  bool trackBtxEtxLevel = !this->GetBeginExcludeRegex().empty() &&
116  !this->GetEndExcludeRegex().empty();
117  int btxEtxLevel = 0;
118  bool isLineComment = false;
119 
120  gxsys::RegularExpression reLineComment;
121  reLineComment.compile("^[\\t ]*//");
122 
123  gxsys::RegularExpression reBTX;
124  gxsys::RegularExpression reETX;
125  if (trackBtxEtxLevel)
126  {
127  reBTX.compile(this->GetBeginExcludeRegex().c_str());
128  reETX.compile(this->GetEndExcludeRegex().c_str());
129  }
130  //
131  // Old hard-coded values were eerily similar to BTX/ETX regexes found in
132  // the VTK source tree in Wrapping/vtkParse.l... ;)
133  //
134  //reBTX.compile("^[\\t ]*//BTX.*$");
135  //reETX.compile("^[\\t ]*//ETX.*$");
136 
137  while (!file.eof())
138  {
139  line[0] = 0;
140  file.getline(line, 4099);
141 
142  isLineComment = reLineComment.find(line);
143 
144  if (trackBtxEtxLevel && reBTX.find(line))
145  {
146  btxEtxLevel++;
147  }
148 
149  this->Lines.push_back(LineData(line, isLineComment, btxEtxLevel));
150 
151  if (trackBtxEtxLevel && reETX.find(line))
152  {
153  btxEtxLevel--;
154  }
155  }
156  }
157 
158 
159 #if 0
160  // Dump it out with Trace to see what the settings and the output
161  // data look like... This is a Print-method-in-waiting...
162  //
163  gxsys_stl::ostringstream oss;
164 
165  oss << "FileName: " << this->FileName << gxsys_stl::endl;
166  oss << "ExcludeMarkedLines: " << this->ExcludeMarkedLines << gxsys_stl::endl;
167  oss << "BeginExcludeRegex: " << this->BeginExcludeRegex << gxsys_stl::endl;
168  oss << "EndExcludeRegex: " << this->EndExcludeRegex << gxsys_stl::endl;
169 
170  oss << "Lines:" << gxsys_stl::endl;
171 
172  unsigned int i = 1;
173  gxsys_stl::vector<LineData>::iterator itLines;
174 
175  for (itLines = this->Lines.begin(); itLines != this->Lines.end();
176  ++itLines)
177  {
178  LineData line = *itLines;
179 
180  // Comment?
181  //
182  if (line.IsLineComment)
183  {
184  oss << "C | ";
185  }
186  else
187  {
188  oss << " | ";
189  }
190 
191  // BTX/ETX level:
192  //
193  if (line.BtxEtxLevel)
194  {
195 
196  oss << line.BtxEtxLevel;
197 
198 
199  oss << " | ";
200  }
201  else
202  {
203  oss << " | ";
204  }
205 
206  // Line number, i - 4 digits with leading zeroes:
207  //
208  char f = oss.fill();
209  gxsys_stl::streamsize w = oss.width();
210  oss.fill('0');
211  oss.width(4);
212  oss << i;
213  oss.fill(f);
214  oss.width(w);
215 
216  // The line itself:
217  //
218  oss << ": " << line.Line << gxsys_stl::endl;
219 
220  ++i;
221  }
222 
223  Trace(oss.str().c_str());
224 #endif
225 }
226 
227 
228 //----------------------------------------------------------------------------
230 {
231  return static_cast<unsigned int>(this->Lines.size());
232 }
233 
234 
235 //----------------------------------------------------------------------------
236 gxsys_stl::string MummyLineOrientedTextFileReader::GetLine(unsigned int lineNumber)
237 {
238  if (lineNumber<1 || lineNumber>this->GetNumberOfLines())
239  {
240  LogWarning(mw_NoSuchLineNumber, "lineNumber out of range in GetLine");
241  return "";
242  }
243 
244  return this->Lines.at(lineNumber-1).Line;
245 }
246 
247 
248 //----------------------------------------------------------------------------
250 {
251  if (lineNumber<1 || lineNumber>this->GetNumberOfLines())
252  {
253  LogWarning(mw_NoSuchLineNumber, "lineNumber out of range in GetIsLineComment");
254  return false;
255  }
256 
257  return this->Lines.at(lineNumber-1).IsLineComment;
258 }
259 
260 
261 //----------------------------------------------------------------------------
263 {
264  if (lineNumber<1 || lineNumber>this->GetNumberOfLines())
265  {
266  LogWarning(mw_NoSuchLineNumber, "lineNumber out of range in GetBtxEtxLevel");
267  return 0;
268  }
269 
270  return this->Lines.at(lineNumber-1).BtxEtxLevel;
271 }
272 
273 
274 //----------------------------------------------------------------------------
276 {
277  return this->GetExcludeMarkedLines() &&
278  this->GetBtxEtxLevel(lineNumber) > 0;
279 }
280 
281 
282 //----------------------------------------------------------------------------
283 void MummyLineOrientedTextFileReader::GetCommentBlockBefore(unsigned int lineNumber, gxsys_stl::vector<gxsys_stl::string>& block, unsigned int smallestAcceptableLineNumber)
284 {
285  if (lineNumber<2 || lineNumber>this->GetNumberOfLines())
286  {
287  LogWarning(mw_NoSuchLineNumber, "lineNumber out of range in GetCommentBlockBefore");
288  return;
289  }
290 
291  // We seek the comment block before a class or method declaration in a
292  // header file. Like this line-numbered example from vtkObject.h:
293  //
294  // 52:
295  // 53: // Description:
296  // 54: // Create an object with Debug turned off, modified time initialized
297  // 55: // to zero, and reference counting on.
298  // 56: static vtkObject *New();
299  // 57:
300  //
301  // If given lineNumber==56 as input, we should compute begin==53 and end==55
302  // and return the comment block as a vector of line strings from
303  // begin to end inclusive...
304 
305  unsigned int begin = 0;
306  unsigned int end = 0;
307  unsigned int i = lineNumber;
308 
309  // Find the first comment before lineNumber, saving its index in 'end'.
310  // If no line comments occur before lineNumber, end will be 0.
311  //
312  while (0 == end && i>1)
313  {
314  i--;
315  if (GetIsLineComment(i) && 0==GetBtxEtxLevel(i))
316  {
317  end = i;
318  }
319  }
320 
321  // Now find the first non-comment before end, saving the index of the comment
322  // line *after* it in 'begin'.
323  //
324  if (0 != end)
325  {
326  while (0 == begin && i>1)
327  {
328  i--;
329  if (!GetIsLineComment(i) && 0==GetBtxEtxLevel(i))
330  {
331  begin = i + 1;
332  }
333  }
334 
335  // Didn't find a non-comment line before 'end'... Comment block must start
336  // right at line 1.
337  //
338  if (0 == begin)
339  {
340  begin = 1;
341  }
342  }
343 
344  // If end==0 then there are no comment lines prior to lineNumber.
345  //
346  if (0 == end)
347  {
348  LogFileLineWarningMsg(this->FileName.c_str(), lineNumber, mw_UndocumentedEntity,
349  "No comment lines prior to line " << lineNumber << ". Undocumented class or method?");
350  }
351  else if (smallestAcceptableLineNumber > begin)
352  {
353  block.push_back(std::string("//Undocumented Block"));
354  }
355  else
356  {
357  gxsys_stl::string s;
358 
359  gxsys::RegularExpression reBeginsWithWhiteSpace;
360  reBeginsWithWhiteSpace.compile("^([\\t ]*)[^\\t ].*");
361  size_t from = 0;
362  size_t to = 0;
363 
364  for (i= begin; i<=end; ++i)
365  {
366  s = GetLine(i);
367 
368  if (reBeginsWithWhiteSpace.find(s))
369  {
370  from = reBeginsWithWhiteSpace.match(1).size();
371  to = s.size() - from;
372  s = s.substr(from, to);
373  }
374 
375  block.push_back(s);
376  }
377  }
378 }
379 
380 
381 //----------------------------------------------------------------------------
382 void MummyLineOrientedTextFileReader::GetFirstCommentBlock(gxsys_stl::vector<gxsys_stl::string>& block)
383 {
384  // Find the first non-comment line after the first comment line and use it
385  // to call GetCommentBlockBefore...
386  //
387  unsigned int i = 1;
388  unsigned int n = this->GetNumberOfLines();
389  bool foundFirstComment = false;
390 
391  for (i= 1; i<=n; ++i)
392  {
393  if (this->GetIsLineComment(i) && 0==GetBtxEtxLevel(i))
394  {
395  foundFirstComment = true;
396  }
397  else if (foundFirstComment)
398  {
399  this->GetCommentBlockBefore(i+1, block, 1);
400  break;
401  }
402  }
403 }
virtual void GetFirstCommentBlock(gxsys_stl::vector< gxsys_stl::string > &block)
Retrieve the first block of comment lines, if any, in the file.
virtual void SetFileName(const char *filename)
Set the filename.
gxsys_stl::string Line
virtual int GetBtxEtxLevel(unsigned int lineNumber)
Get the current nesting level at line number 'lineNumber' of "//BTX - //ETX" style wrapper exclusion ...
virtual bool GetIsLineComment(unsigned int lineNumber)
Query if line number 'lineNumber' is a "line comment." Valid 'lineNumber' values are 1 through GetNum...
virtual void SetEndExcludeRegex(const gxsys_stl::string &endExcludeRegex)
Set the regular expression that delineates a line as the end of a "marked as excluded" block...
virtual gxsys_stl::string GetFileName()
Get the filename.
virtual gxsys_stl::string GetEndExcludeRegex()
Get the regular expression that delineates a line as the end of a "marked as excluded" block...
Internal, implementation detail class that caches information associated with a line in a line orient...
virtual unsigned int GetNumberOfLines()
Retrieve the total number of lines currently cached.
virtual void SetExcludeMarkedLines(bool excludeMarkedLines)
Set whether to exclude lines between beginExcludeRegex and endExcludeRegex matching lines when consid...
virtual gxsys_stl::string GetBeginExcludeRegex()
Get the regular expression that delineates a line as the beginning of a "marked as excluded" block...
virtual void SetBeginExcludeRegex(const gxsys_stl::string &beginExcludeRegex)
Set the regular expression that delineates a line as the beginning of a "marked as excluded" block...
virtual bool IsLineExcluded(unsigned int lineNumber)
Query whether the given line number should be excluded based on the exclude flag and the line number'...
virtual void Update()
Read the current text file and cache its lines for subsequent quick lookup by line number...
virtual void GetCommentBlockBefore(unsigned int lineNumber, gxsys_stl::vector< gxsys_stl::string > &block, unsigned int smallestAcceptableLineNumber)
Retrieve the nearest preceding block of comment lines relative to line number 'lineNumber'. Valid 'lineNumber' values are 2 through GetNumberOfLines inclusive.
virtual bool GetExcludeMarkedLines()
Get whether to exclude lines between beginExcludeRegex and endExcludeRegex matching lines when consid...
void Trace(const char *s)
virtual gxsys_stl::string GetLine(unsigned int lineNumber)
Retrieve line number 'lineNumber' as a string from the currently cached text file. Valid 'lineNumber' values are 1 through GetNumberOfLines inclusive.
#define LogWarning(n, m)
Definition: MummyLog.h:44
#define LogFileLineWarningMsg(file, line, n, m)
Definition: MummyLog.h:31