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 }