NCBI C++ ToolKit
agp_util.hpp
Go to the documentation of this file.

Go to the SVN repository for this file.

1 #ifndef OBJTOOLS_READERS___AGP_UTIL__HPP
2 #define OBJTOOLS_READERS___AGP_UTIL__HPP
3 
4 /* $Id: agp_util.hpp 101726 2024-02-02 12:49:19Z grichenk $
5  * ===========================================================================
6  *
7  * PUBLIC DOMAIN NOTICE
8  * National Center for Biotechnology Information
9  *
10  * This software/database is a "United States Government Work" under the
11  * terms of the United States Copyright Act. It was written as part of
12  * the author's official duties as a United States Government employee and
13  * thus cannot be copyrighted. This software/database is freely available
14  * to the public for use. The National Library of Medicine and the U.S.
15  * Government have not placed any restriction on its use or reproduction.
16  *
17  * Although all reasonable efforts have been taken to ensure the accuracy
18  * and reliability of the software and data, the NLM and the U.S.
19  * Government do not and cannot warrant the performance or results that
20  * may be obtained by using this software or data. The NLM and the U.S.
21  * Government disclaim all warranties, express or implied, including
22  * warranties of performance, merchantability or fitness for any particular
23  * purpose.
24  *
25  * Please cite the author in any work or product based on this material.
26  *
27  * ===========================================================================
28  *
29  * Author: Victor Sapojnikov
30  *
31  * File Description:
32  * Generic fast AGP stream reader (CAgpReader),
33  * and even more generic line parser (CAgpRow).
34  * Example: test/agp_*.cpp
35  *
36  * Accession naming patterns (CAccPatternCounter).
37  * Find ranges for consequtive digits. Not related to the above.
38  * Sample input : AC123.1 AC456.1 AC789.1 NC8967.4 NC8967.5
39  * ^^^ ^ ^^^^ ^
40  * Sample output: AC[123..789].1 3 NC8967.[4,5] 2
41  * Example: test/pacc.cpp
42  */
43 
44 
45 
46 #include <corelib/ncbistd.hpp>
47 #include <corelib/ncbistr.hpp>
48 #include <corelib/ncbimtx.hpp>
50 #include <map>
51 
53 
54 // As time goes on, we should remove support for older versions.
56  eAgpVersion_auto, ///< auto-detect using the first gap line
57  eAgpVersion_1_1, ///< AGP spec 1.1
58  eAgpVersion_2_0 ///< AGP spec 2.0 or later
59 };
60 
61 class CAgpErr; // full definition below
62 class CAgpReader; // full definition below
63 
64 typedef TSeqPos TAgpPos;
65 typedef TSeqPos TAgpLen;
66 
67 /// A container for both the original string column values (Get*() methods)
68 /// and the values converted to int, char, bool types (member variables).
69 /// Detects formatting errors within a single line, checks that
70 /// object range length equals gap length or component range length.
72 {
73 protected:
74  // constructors are protected to prevent users from creating
75  // instances on the stack
76 
77  // reader argument is used for notification of version auto-detection via SetVersion()
78  CAgpRow(CAgpErr* arg, EAgpVersion agp_version = eAgpVersion_auto,
79  CAgpReader* reader = nullptr);
80  // constructs a default error handler
81  CAgpRow(EAgpVersion agp_version = eAgpVersion_auto,
82  CAgpReader* reader = nullptr);
83 
84  CAgpRow(const CAgpRow &);
85 
86 public:
87 
88  virtual ~CAgpRow();
89 
91  CAgpErr* arg, EAgpVersion agp_version = eAgpVersion_auto,
92  CAgpReader* reader = nullptr)
93  {
94  return Ref(new CAgpRow(arg, agp_version, reader));
95  }
96 
98  CAgpReader* reader = nullptr)
99  {
100  return Ref( new CAgpRow(agp_version, reader) );
101  }
102 
103  CRef<CAgpRow> Clone(void) const {
104  return Ref( new CAgpRow(*this) );
105  }
106 
107  // Returns:
108  // -1 comment line (to be silently skipped)
109  // 0 parsed successfully
110  // >0 an error code (copied to last_error)
111  int FromString(const string& line);
112  // Generates G_CompEndGtLength message and returns false on error.
113  string GetErrorMessage();
114  string ToString(bool reorder_linkage_evidences=false); // 9 column tab-separated string without EOL comments
115 
116  //// Unparsed columns
117  SIZE_TYPE pcomment; // NPOS if no comment for this line, 0 if the entire line is comment
118  vector<string> cols;
119 
120  string& GetObject () {return cols[0];} // no corresponding member variable
121  string& GetObjectBeg () {return cols[1];}
122  string& GetObjectEnd () {return cols[2];}
123  string& GetPartNumber () {return cols[3];}
124  string& GetComponentType() {return cols[4];}
125 
126  string& GetComponentId () {return cols[5];} // no corresponding member variable
127  string& GetComponentBeg () {return cols[6];}
128  string& GetComponentEnd () {return cols[7];}
129  string& GetOrientation ()
130  {
131  if(cols.size()==8) {
132  // prevent out-of-range accesses in GetLinkageEvidence() and GetOrientation()
133  cols.push_back(NcbiEmptyString);
134  }
135 
136  return cols[8];
137  }
138 
139  string& GetGapLength() {return cols[5];}
140  string& GetGapType () {return cols[6];}
141  string& GetLinkage () {return cols[7];}
142  string& GetLinkageEvidence () // AGP v. 2.0
143  {
144  if(cols.size()==8) {
145  // prevent out-of-range accesses in GetLinkageEvidence() and GetOrientation()
146  cols.push_back(NcbiEmptyString);
147  }
148 
149  return cols[8];
150  }
151 
152  //// Parsed columns
153  TAgpPos object_beg, object_end, part_number;
155 
156  bool is_gap;
157 
158  TAgpPos component_beg, component_end;
160  // numeric values of the enum are equal to ASCII values of
161  // AGP 1.1's values for
162  // backward compatibility. Intentionally obfuscated to discourage
163  // you from using the underlying char representation and because
164  // it doesn't match later versions. (e.g. unknown char is now '?' in
165  // AGP 2.0, etc.)
166  eOrientationPlus = 43,
167  eOrientationMinus = 45,
168  eOrientationUnknown = 48,
169  eOrientationIrrelevant = 110
170  };
172 
174  // if you update this enum, make sure to update CAgpRow::gap_types
175  enum EGap{
176  eGapClone , // AGP 1.1 only
177  eGapFragment , // AGP 1.1 only
179  eGapScaffold , // AGP 2.0 and later
180  eGapContamination , // AGP 2.1 and later
181 
188 
190  eGapYes_count=eGapContamination+1
191  };
193  bool linkage;
194 
196  fLinkageEvidence_paired_ends = (1 << 0),
197  fLinkageEvidence_align_genus = (1 << 1),
198  fLinkageEvidence_align_xgenus = (1 << 2),
199  fLinkageEvidence_align_trnscpt= (1 << 3),
200  fLinkageEvidence_within_clone = (1 << 4),
201  fLinkageEvidence_clone_contig = (1 << 5),
202  fLinkageEvidence_map = (1 << 6),
203  fLinkageEvidence_strobe = (1 << 7),
204  fLinkageEvidence_pcr = (1 << 8),
205  fLinkageEvidence_proximity_ligation = (1 << 9),
206  // update fLinkageEvidence_HIGHEST_BIT_MASK if more added
207  fLinkageEvidence_HIGHEST_BIT_MASK = fLinkageEvidence_proximity_ligation,
208 
209  fLinkageEvidence_unspecified = 0,
210  fLinkageEvidence_INVALID = -1,
211  fLinkageEvidence_na = -2
212  };
213  /// Might have duplicates, and is empty on error or
214  /// if there are no actual linkage evidences (e.g. "na" or "unspecified")
215  /// It does NOT hold unusual values like fLinkageEvidence_INVALID.
216  typedef vector<ELinkageEvidence> TLinkageEvidenceVec;
218  /// a bit map which holds summary of info in linkage_evidences.
219  /// In particular, this is useful for weeding out duplicates
221 
222  static bool IsGap(char c)
223  {
224  return c=='N' || c=='U';
225  }
226  static bool IsDraftComponent(char c)
227  {
228  // Active finishing, Draft HTG, Pre draft
229  return c=='A' || c=='D' || c=='P';
230  }
231  static bool GapValidAtObjectEnd(EGap gap_type)
232  {
233  return gap_type==eGapCentromere || gap_type==eGapTelomere ||
234  gap_type==eGapShort_arm || gap_type==eGapHeterochromatin ||
235  gap_type==eGapContamination;
236  }
237 
238 
239  bool IsGap() const
240  {
241  return is_gap;
242  }
244  {
245  return IsDraftComponent(component_type);
246  }
247 
248  bool GapEndsScaffold() const
249  {
250  // m_agp_version == eAgpVersion_1_1 &&
251  if( gap_type==eGapFragment) return false;
252  return linkage==false;
253  }
254  bool GapValidAtObjectEnd() const
255  {
256  //return gap_type==eGapCentromere || gap_type==eGapTelomere || gap_type==eGapShort_arm;
257  return GapValidAtObjectEnd(gap_type);
258  }
259 
260 
261  static bool CheckComponentEnd(const string& comp_id, TAgpPos comp_end, TAgpLen comp_len,
262  CAgpErr& agp_err);
263  bool CheckComponentEnd(TAgpLen comp_len) {
264  return CheckComponentEnd(GetComponentId(), component_end, comp_len, *m_AgpErr);
265  }
266 
267  // terms in the original order
268  string LinkageEvidencesToString(void);
269  // terms in the preferred order
270  static string LinkageEvidenceFlagsToString(int le);
272  {
273  return LinkageEvidenceFlagsToString(linkage_evidence_flags);
274  }
275  static const char* le_str(ELinkageEvidence le);
276  static int str_to_le(const string& str);
277  /** Returns a string describing suggested replacement, or "" if none is needed.
278  Use do_subst=true to do the actial substitution in this object.
279  */
280  string SubstOldGap(bool do_subst);
281 
282  string OrientationToString( EOrientation orientation );
283 
284  virtual void SetVersion(EAgpVersion ver);
285 
286 protected:
287  TAgpPos ReadSeqPos(const CTempString seq_pos_str, const string& details,
288  int *perror_code, bool log_errors = true);
289  int ParseComponentCols(bool log_errors=true);
290  int ParseGapCols(bool log_errors=true);
291 
292  typedef const char* TStr;
293  static const TStr gap_types[eGapCount];
294 
297 
298  static TMapStrEGap * gap_type_codes_creator(void);
299 
300 private:
302 
303  // raw pointer because we *never* own this.
305 
307 
308 public:
309  CAgpErr* GetErrorHandler() { return m_AgpErr; }
310  void SetErrorHandler(CAgpErr* arg);
311 
312  static const char* GapTypeToString(int i)
313  {
314  if(i<0 || i>=eGapCount) return NcbiEmptyCStr;
315  return gap_types[i];
316  }
317 
319  {
320  return m_agp_version;
321  }
322 };
323 
324 /// Detects scaffolds, object boundaries, errors that involve 2 consecutive lines,
325 /// and is intended as a superclass for more complex readers.
327 {
328 public:
329  CAgpReader(CAgpErr* arg,
330  EAgpVersion agp_version = eAgpVersion_auto );
331  // constructs a default error handler for this object instance
332  CAgpReader(EAgpVersion agp_version = eAgpVersion_auto );
333  virtual ~CAgpReader();
334 
335  /// Whether or not the function should call Finalize() when it's done successfully
336  enum EFinalize {
338  eFinalize_Yes
339  };
340  /// Read an AGP file from the given input stream.
341  ///
342  /// @param is
343  /// The input stream we're reading the AGP from
344  /// @param eFinalize
345  /// If we successfully read the AGP file, this param determines
346  /// whether or not we call Finalize().
347  /// @return
348  /// Returns the error code, where 0 means "okay". Non-zero error
349  /// codes are usually values from the unnamed enum in CAgpErr
350  /// that has E_ColumnCount, E_EmptyColumn, etc., but subclasses
351  /// can have their own custom error codes, so other values
352  /// can appear.
353  virtual int ReadStream(CNcbiIstream& is, EFinalize eFinalize = eFinalize_Yes );
354 
355  /// Deprecated backward-compatibility wrapper.
356  /// @deprecated
358  int ReadStream(CNcbiIstream& is, bool bFinalize)
359  {
360  return ReadStream(is, (bFinalize ? eFinalize_Yes : eFinalize_No) );
361  }
362 
363  /// This is called at the end of the file, usually automatically but can be called manually if
364  /// the automatic call was intentionally disabled.
365  ///
366  /// @return
367  /// Returns error code on whether the "Finalize" operation succeeded, where 0 means "okay".
368  virtual int Finalize(); // by default, invoked automatically at the end of ReadStream()
369 
370  /// Return a string with one (or two, depending on error) source line(s)
371  /// on which the error occured, along with the error message(s) themselves.
372  ///
373  /// @param filename
374  /// If filename is non-empty, each line is preceded with "FILENAME:"
375  /// (useful when reading several files).
376  virtual string GetErrorMessage(const string& filename=NcbiEmptyString);
377 
378  /// Invoked from ReadStream(), after the row has been parsed, and
379  /// seldom needs to be invoked by user.
380  /// One occassion is in agp_renumber - to force a line NOT to be skipped
381  /// it is called from OnError() when m_line_skipped=true
382  /// and m_error_code=E_ObjRangeNeGap or E_ObjRangeNeComp.
383  bool ProcessThisRow();
384 
385  /// Change what AGP version to use for the next input that's read.
386  /// Please prefer setting the version in the CAgpReader constructor instead
387  /// and if SetVersion must be used, it's best to use it at a clean stopping
388  /// point. (Example: immediately after a Finalize() call)
389  virtual void SetVersion(EAgpVersion ver);
390 
391 protected:
393 
394  bool m_at_beg; // m_this_row is the first valid component or gap line;
395  // m_prev_row undefined.
396  bool m_at_end; // after the last line; could be true only in OnScaffoldEnd(), OnObjectChange().
397  // m_prev_row is the last component or gap line;
398  // m_this_row undefined.
399 
400  bool m_line_skipped; // true after a syntax error or E_Obj/CompEndLtBeg, E_ObjRangeNeGap/Comp
401  bool m_prev_line_skipped; // (i.e. single-line errors detected by CAgpRow);
402  // Not affected by comment lines, even though these are skipped, too.
403 
404  bool m_new_obj; // For OnScaffoldEnd(), true if this scaffold ends with an object.
405  // (false if there are scaffold-breaking gaps at object end)
406  bool m_content_line_seen; // True after we see and process a line that is
407  // not just comment or whitespace
408  int m_error_code; // Set to a positive value to trigger OnError().
409  // Set to -1 to graciously stop reading of the stream midway:
410  // void OnGapOrComponent()
411  // {
412  // if(need to stop && m_error_code==0) m_error_code=-1;
413  // }
414 
417  int m_line_num, m_prev_line_num;
418  string m_line; // for valid gap/component lines, corresponds to this_row
419  // To save time, we do not keep the line corresponding to m_prev_row.
420  // You can use m_prev_row->ToString(), or save it at the end of OnGapOrComponent():
421  // m_prev_line=m_line; // preserves EOL comments
422  //
423  // Note that m_prev_line_num != m_line_num - 1:
424  // - after skipped lines (syntax errors or comments)
425  // - when reading from multiple files without Finalize().
426 
427  //// Callbacks, in the order of invocation.
428  //// Override to implement custom functionality.
429  //// Callbacks can read m_this_row, m_prev_row and all other instance variables.
430 
431  virtual void OnScaffoldEnd()
432  {
433  // m_prev_row = the last line of the scaffold --
434  // usually component, but could be non-breaking gap (which generates a warning)
435 
436  // this function should not use m_this_row, which may be undefined (when at the end of the file), or not relevant (elsewhere)
437  }
438 
439  virtual void OnObjectChange()
440  {
441  // unless(m_at_beg): m_prev_row = the last line of the old object
442  // unless(m_at_end): m_this_row = the first line of the new object
443  }
444 
445  virtual void OnGapOrComponent()
446  {
447  // m_this_row = current gap or component (check with m_this_row->IsGap())
448  }
449 
450  virtual bool OnError()
451  {
452  // in m_line_skipped :
453  // false: Non-fatal error, line saved to m_this_row.
454  // All appropriate preceding callbacks were called before OnError() for this line.
455  // They can check m_error_code, if they need to (not very likely).
456  // true : Syntax error; m_this_row most likely incomplete.
457  // (or complete but inconsistent for E_ObjRangeNeGap, E_ObjRangeNeComp)
458  // No other callbacks invoked for this line.
459  // On the next iteration, m_prev_row will retain the last known valid line.
460  // out m_line_skipped: copied to m_prev_line_skipped;
461  // set to true to enable the checks that require 2 lines.
462 
463  return false; // abort on any error
464  }
465 
466  virtual void OnComment()
467  {
468  // Line that starts with "#".
469  // No other callbacks invoked for this line.
470  }
471 
472 private:
473 
474  CRef<CAgpErr> m_AgpErr; // Error handler
475 
476  void Init();
477 
478  void x_CheckPragmaComment(void);
479 
480 public:
481  CAgpErr* GetErrorHandler() { return m_AgpErr; }
482  void SetErrorHandler(CAgpErr* arg);
484  {
485  return m_agp_version;
486  }
487 };
488 
489 
491 {
492 public:
493  CAgpErr();
494  virtual ~CAgpErr() {}
495 
497  fAtThisLine= 1,
498  fAtPrevLine= 4, // use fAtThisLine|fAtPrevLine when both lines are involved
499  fAtNone = 8, // Not tied to any specifc line(s) (empty file; possibly, taxid errors)
500  fAtPpLine =16 // applies to 3 conseq lines (only W_BreakingGapSameCompId so far)
501  };
502 
503  // This implementation accumulates multiple errors separately for
504  // the current and the previous lines, ignores warnings.
505  virtual void Msg(int code, const string& details, int appliesTo=fAtThisLine);
506  virtual void Msg(int code, int appliesTo=fAtThisLine)
507  {
508  Msg(code, NcbiEmptyString, appliesTo);
509  }
510  void Clear();
511 
512  // The following 2 methods are needed for CAgpRow/CAgpReader::GetErrorMessage()
513  virtual string GetErrorMessage(int mask=0xFFFFFFFF);
514  virtual int AppliesTo(int mask=0xFFFFFFFF);
515 
516  // When adding new errors to this enum, also update sMessageMap
517  enum EErrCode {
518  // Errors within one line (detected in CAgpRow)
519  E_ColumnCount=1 ,
524 
531 
532  // Other errors, some detected only by agp_validate.
533  // We define the codes here to preserve the historical error codes.
534  // CAgpRow and CAgpReader do not know of such errors.
535  E_DuplicateObj , // CAgpValidateReader
536  E_ObjMustBegin1 , // CAgpReader
537  E_PartNumberNot1, // CAgpReader
538  E_PartNumberNotPlus1, // CAgpReader
539  E_UnknownOrientation, // CAgpValidateReader
540 
541  E_ObjBegNePrevEndPlus1, // CAgpReader
542  E_NoValidLines, // CAgpReader (Make it a warning?)
546 
547  E_UnknownScaf, // CAgpValidateReader
548  E_UnusedScaf, // CAgpValidateReader
549  E_SameGapLength, // CAgpValidateReader
550  E_InvalidBarInId, // CAgpValidateReader
551  E_Last, E_First=1, E_LastToSkipLine=E_ObjRangeNeComp,
552 
553  // Warnings.
554  W_GapObjEnd=31, // CAgpReader
555  W_GapObjBegin, // CAgpReader
556  W_ConseqGaps, // CAgpReader
557  W_ObjNoComp, // CAgpValidateReader
558  W_SpansOverlap, // CAgpValidateReader
559 
560  W_SpansOrder, // CAgpValidateReader
561  W_DuplicateComp, // CAgpValidateReader
562  W_LooksLikeGap, // CAgpRow
563  W_LooksLikeComp, // CAgpRow
564  W_ExtraTab, // CAgpRow
565 
567  W_NoEolAtEof, // CAgpReader
569  W_ObjOrderNotNumerical, // CAgpValidateReader
570  // NOTE: "Wgs" warnings must come last so that "Use -g..." hint
571  // printed in CAgpValidateReader::x_PrintTotals()
572  // comes right after the "Wgs" warning counts.
573  W_CompIsWgsTypeIsNot, // CAgpValidateReader
574 
575  W_CompIsNotWgsTypeIs, // CAgpValidateReader
576  W_ObjEqCompId, // CAgpValidateReader
577  W_GapSizeNot100, // CAgpRow
578  W_BreakingGapSameCompId,// CAgpValidateReader
579  W_UnSingleCompNotInFull,// CAgpValidateReader
580 
581  W_SingleOriNotPlus, // CAgpValidateReader
582  W_ShortGap , // CAgpValidateReader
583  W_SpaceInObjName , // CAgpValidateReader
584  W_CommentsAfterStart, // CAgpRow (v. >= 2.0)
585  W_OrientationZeroDeprecated, // CAgpRow (v. >= 2.0)
586 
587  W_NaLinkageExpected, // CAgpRow (v. >= 2.0 )
588  W_OldGapType, // CAgpRow (v. >= 2.0 )
589  W_AssumingVersion, // CAgpRow (v. == auto)
590  W_ScafNotInFull, // CAgpValidateReader
591  W_MissingLinkage, // CAgpRow (v. >= 2.0 )
592 
595  W_DuplicateEvidence, // CAgpRow (v. >= 2.0 )
598 
601  W_Last, W_First = 31,
602 
603  // "GenBank" checks that rely on information about the sequence
604  G_InvalidCompId=71, // CAgpValidateReader
605  G_NotInGenbank, // CAgpValidateReader
606  G_NeedVersion, // CAgpValidateReader
607  G_CompEndGtLength, // CAgpRow::CheckComponentEnd() (used in agp_validate)
608  G_DataError, // CAgpValidateReader
609 
610  G_TaxError, // CAgpValidateReader
611  G_InvalidObjId, // CAgpValidateReader
612  G_BadObjLen, // CAgpValidateReader
615 
616  G_First = G_InvalidCompId,
617  };
618 
619  static const char* ErrorWarningOrNote(int code)
620  {
621  if((code<W_First || code>W_Last) && code!=G_NsWithinCompSpan) return "ERROR";
622  if(code==W_ShortGap || code==W_AssumingVersion) return "NOTE";
623  return "WARNING";
624  }
625 
626  static const char* GetMsg(int code);
627 
628 protected:
629  typedef const char* TStr;
630  static const TStr s_msg[]; // s_msg is deprecated and will be removed in SC-25. Use s_MessageMap instead.
631 
633  static const TMsgMap sMessageMap;
634 
635  static string FormatMessage(const string& msg, const string& details);
636 
637  string m_messages;
638  string m_messages_prev_line; // Messages that apply ONLY to the previous line;
639  // relatively uncommon - most that apply to previous
640  // also apply to current, and are saved in m_messages instead.
641 
642  int m_apply_to; // which lines to print before the message(s): previous, current, both, whole file
643 };
644 
645 
646 /// Correctly print multiple errors and warnings on consequitive lines;
647 /// suppress undesired or higly repetitive messages;
648 /// calculate total counts for each type of error.
650 {
651 public:
652 
653  enum {
654  /// The number of the first CAgpErr error enum
655  CODE_First = E_First,
656  /// Reserve space for some user errors (to count, or to skip).
657  /// The strange value of this enum is meant to give a separation
658  /// of 10 or 20 between the last built-in error
659  /// (currently G_Last) and the first user errors.
660  CODE_Extended = ((((G_Last / 10 ) + 2) * 10) + 1),
661  /// This is one past the last code allowed, after built-in and user errors.
662  CODE_Last=CODE_Extended+20
663  };
664 
665  //static const char* GetMsgEx(int code);
666  string GetPrintableCode(int code, bool strict=false) const; // Returns a string like e01 w12
667  void PrintAllMessages(CNcbiOstream& out) const;
668 
669 
670  // The max number of times to print a given error message.
672  // If this turns true, we can inform user about -limit 0 option
674 
675  // Warnings + errors skipped,
676  // either because of m_MaxRepeat or MustSkip().
679  bool m_use_xml;
680 
681  // Print the source line along with filename and line number.
682  static void PrintLine (CNcbiOstream& ostr,
683  const string& filename, int linenum, const string& content);
684  static void PrintLineXml(CNcbiOstream& ostr, const string& filename, int linenum, const string& content, bool two_lines_involved);
685 
686  // Most warnings are treated as errors in the strict mode.
687  bool m_strict;
688  // A bit mask for warnings that are still warnings in the strict mode.
689  // The lowest bit stands for W_First (aka w31, W_GapObjBegin),
690  // the highest, as of 2015/03/25 - W_Last, w66, W_GnlId.
691  static const Uint8 s_StrictModeWarningMask =
692  (Uint8(1) << (W_ExtraTab -W_First)) |
693  (Uint8(1) << (W_GapLineMissingCol9 -W_First)) |
694  (Uint8(1) << (W_NoEolAtEof -W_First)) |
695  (Uint8(1) << (W_GapLineIgnoredCol9 -W_First)) |
696  (Uint8(1) << (W_ObjOrderNotNumerical -W_First)) |
697  (Uint8(1) << (W_GapSizeNot100 -W_First)) |
698  (Uint8(1) << (W_ShortGap -W_First)) |
699  (Uint8(1) << (W_CommentsAfterStart -W_First)) |
700  (Uint8(1) << (W_AssumingVersion -W_First)) |
701  (Uint8(1) << (W_AGPVersionCommentInvalid -W_First)) |
702  (Uint8(1) << (W_AGPVersionCommentUnnecessary-W_First)) ;
703  static inline bool IsStrictModeWarning(int code)
704  {
705  return s_StrictModeWarningMask & (Uint8(1) << (code-W_First));
706  }
707  const char* ErrorWarningOrNoteEx(int code);
708 
709  /// Print the message by code, preceded by "ERROR" or "WARNING".
710  /// See also: CAgpErr::FormatMessage().
711  /// Override this you define user errors or warnings -
712  /// you cannot override GetMsgEx().
713  virtual void PrintMessage(CNcbiOstream& ostr, int code,
714  const string& details=NcbiEmptyString);
715  virtual void PrintMessageXml(CNcbiOstream& ostr, int code, const string& details, int appliesTo);
716 
717  // Construct a readable message on total error & warning counts
718  static void PrintTotals(CNcbiOstream& ostr, int e_count, int w_count, int note_count, int skipped_count);
719  static void PrintTotals(CNcbiOstream& ostr, int e_count, int w_count, int skipped_count)
720  {
721  PrintTotals(ostr, e_count, w_count, 0, skipped_count);
722  }
723  static void PrintTotalsXml(CNcbiOstream& ostr, int e_count, int w_count, int note_count, int skipped_count);
724 
725  CAgpErrEx(
726  CNcbiOstream* out=&cerr,
727  bool use_xml=false,
728  EOwnership eOwnsOut = eNoOwnership);
729 
730  // Can skip unwanted messages, record a message for printing (CAgpErr::fAtThisLine),
731  // print it immediately if it applies to the previous line (CAgpErr::fAtPrevLine),
732  // print the previous line and record the message
733  // if it applies to the 2 last lines (CAgpErr::fAtPrevLine|CAgpErr::fAtThisLine).
734  //
735  // The resulting output format works well when:
736  // 1)there are multiple errors in one line:
737  // file:linenum:agp content
738  // MSG1
739  // MSG2
740  // 2)there is an error that involves 2 lines:
741  // file1:linenum1:agp content1
742  // file2:linenum2:agp content2
743  // MSG
744  // The format is still acceptable if both 1 and 2 are true.
745  //
746  // When the message applies to 2 non-consequitive lines
747  // (e.g. intersecting component spans), we do not print the first line involved.
748 
749  // we override Msg() that comes from CAgpErr
750  virtual void Msg(int code, const string& details, int appliesTo=fAtThisLine);
751  virtual void Msg(int code, int appliesTo=fAtThisLine)
752  {
753  Msg(code, NcbiEmptyString, appliesTo);
754  }
755 
756  // Print any accumulated messages.
757  virtual void LineDone(const string& s, int line_num, bool invalid_line=false);
758 
759  // No need to call this function when reading from STDIN,
760  // or when reading only one file. For multiple files,
761  // invoke with the next filename prior to reading it.
762  void StartFile(const string& s);
763 
764  // 'fgrep' errors out, or keep only the given errors (skip_other=true)
765  // Can include/exclude by code (see GetPrintableCode()), or by substring.
766  // Return values:
767  // "" no matches found for str
768  // string beginning with " " one or more messages that matched
769  // else printable [error] message
770  // Note: call SkipMsg("all") before SkipMsg(smth, true)
771  string SkipMsg(const string& str, bool skip_other=false);
772  void SkipMsg(int code, bool skip_other=false)
773  {
774  if(code>=E_First && code<CODE_Last) m_MustSkip[code] = !skip_other;
775  }
776 
777  bool MustSkip(int code);
778 
779  // 1 argument:
780  // E_Last: count errors
781  // W_Last: count warnings
782  // G_Last: count GenBank errors
783  // other: errors/warnings of one given type
784  // 2 arguments: range of int-s
785  int CountTotals(int from, int to=E_First);
786  int GetCount(EErrCode code) const;
787  void ResetTotals();
788 
789  // Print individual error counts (important if we skipped some errors)
791  void PrintMessageCounts(CNcbiOstream& ostr, int from, int to=E_First, bool report_lines_skipped=false, TMapCcodeToString* hints=nullptr);
792 
793 protected:
794  // Count errors of each type, including skipped ones.
795  int m_MsgCount[CODE_Last];
796  char m_MustSkip[CODE_Last];
797 
798 
799  // pp: line before previous (not supported by CAgpReader, but used in agp_validate for W_BreakingGapSameCompId)
800  int m_filenum_prev, m_filenum_pp;
801  // Not m_line_num-1 when the previous line:
802  // - was in the different file;
803  // - was a skipped comment line.
804  string m_line_prev, m_line_pp;
805  int m_line_num_prev, m_line_num_pp;
806  bool m_prev_printed, m_pp_printed; // true: previous line was already printed
807  // (probably had another error);
808  // no need to-reprint "fname:linenum:content"
809  bool m_two_lines_involved; // true: do not print "\n" after the previous line
810  //bool m_invalid_prev; // true: suppress errors concerning the previous line
811 
812  // a stream to Accumulate messages for the current line.
813  // (We immediately print messages that apply only to the previous line.)
814  string m_filename;
816 
817  // For reporting filenames of the lines we passed a long time ago
818  // (intersecting component spans, duplicate objects, etc)
819  vector<string> m_InputFiles;
820 
821  // If this instance owns m_out, we set this AutoPtr so
822  // it will automatically be destroyed. It is otherwise
823  // not used.
825 
826 public:
827  // m_messages is public because:
828  // Genbank validator may stow away the syntax errors for the current line
829  // while it processes a batch of preceding lines without syntax errors;
830  // afterwards, it can put the stowed m_messages back, and print them in the
831  // correct place, following any Genbank validation errors for the batch.
832  // CNcbiOstrstream* tmp = agpErr.m_messages;
833  // agpErr.m_messages = new CNcbiOstrstream();
834  // << process a batch of preceding lines >>
835  // agpErr.m_messages = tmp;
836  // agpErr.LineDone(line_orig, line_num, true);
839 
840  // 0: reading from STDIN or from a single file
842  {
843  return static_cast<int>(m_InputFiles.size());
844  }
845 
846  const string& GetFile(int num)
847  {
848  return m_InputFiles[num-1];
849  }
850 
852 
854  m_UpgradedWarnings.insert(code);
855  }
856 
857  bool TreatAsError(int code) const {
858  return TreatAsError(static_cast<EErrCode>(code));
859  }
860 
861  bool TreatAsError(EErrCode code) const {
862  return (m_UpgradedWarnings.find(code) != m_UpgradedWarnings.end());
863  }
864 
865 
866 private:
868 };
869 
870 
871 class CPatternStats; // internal for CAccPatternCounter
872 /// Accession naming patterns; find ranges for consequtive digits.
873 /// Sample input : AC123.1 AC456.1 AC789.1 NC8967.4 NC8967.5
874 /// ^^^ ^ ^^^^ ^
875 /// Sample output: AC[123..789].1 3 NC8967.[4,5] 2
876 class NCBI_XOBJREAD_EXPORT CAccPatternCounter : public map<string, CPatternStats*>
877 {
878 public:
879  typedef vector<double> TDoubleVec;
880  iterator AddName(const string& name, TDoubleVec* runsOfDigits = nullptr);
881 
882  // Replace "0"s in a simple pattern like BCM_Spur_v0.0_Scaffold0
883  // (which is a key in this map) with real numbers or [ranges].
884  static string GetExpandedPattern(value_type* p);
885  static int GetCount(value_type* p);
886 
887  // Export expanded patterns sorted by accession count.
889  void GetSortedPatterns(TMapCountToString& dst);
890 
892 };
893 
895 
896 #endif /* OBJTOOLS_READERS___AGP_UTIL__HPP */
TSeqPos TAgpLen
Definition: agp_util.hpp:65
EAgpVersion
Definition: agp_util.hpp:55
@ eAgpVersion_auto
auto-detect using the first gap line
Definition: agp_util.hpp:56
@ eAgpVersion_1_1
AGP spec 1.1.
Definition: agp_util.hpp:57
@ eAgpVersion_2_0
AGP spec 2.0 or later.
Definition: agp_util.hpp:58
TSeqPos TAgpPos
Definition: agp_util.hpp:62
ncbi::TMaskedQueryRegions mask
Accession naming patterns; find ranges for consequtive digits.
Definition: agp_util.hpp:877
vector< double > TDoubleVec
Definition: agp_util.hpp:879
multimap< int, string > TMapCountToString
Definition: agp_util.hpp:888
Correctly print multiple errors and warnings on consequitive lines; suppress undesired or higly repet...
Definition: agp_util.hpp:650
bool m_strict
Definition: agp_util.hpp:687
map< int, string > TMapCcodeToString
Definition: agp_util.hpp:790
int m_msg_skipped
Definition: agp_util.hpp:677
void UpgradeToError(EErrCode code)
Definition: agp_util.hpp:853
AutoPtr< CNcbiOstrstream > m_messages
Definition: agp_util.hpp:837
string m_filename
Definition: agp_util.hpp:814
int m_MaxRepeat
Definition: agp_util.hpp:671
vector< string > m_InputFiles
Definition: agp_util.hpp:819
bool m_two_lines_involved
Definition: agp_util.hpp:809
string m_line_prev
Definition: agp_util.hpp:804
int m_line_num
Definition: agp_util.hpp:815
int m_lines_skipped
Definition: agp_util.hpp:678
set< EErrCode > m_UpgradedWarnings
Definition: agp_util.hpp:867
bool TreatAsError(EErrCode code) const
Definition: agp_util.hpp:861
bool m_use_xml
Definition: agp_util.hpp:679
virtual void Msg(int code, int appliesTo=fAtThisLine)
Definition: agp_util.hpp:751
bool TreatAsError(int code) const
Definition: agp_util.hpp:857
bool m_prev_printed
Definition: agp_util.hpp:806
bool m_MaxRepeatTopped
Definition: agp_util.hpp:673
int m_filenum_prev
Definition: agp_util.hpp:800
AutoPtr< CNcbiOstream > m_out_destroyer
Definition: agp_util.hpp:824
int m_line_num_prev
Definition: agp_util.hpp:805
void SkipMsg(int code, bool skip_other=false)
Definition: agp_util.hpp:772
static void PrintTotals(CNcbiOstream &ostr, int e_count, int w_count, int skipped_count)
Definition: agp_util.hpp:719
const string & GetFile(int num)
Definition: agp_util.hpp:846
CNcbiOstream * m_out
Definition: agp_util.hpp:838
int GetFileNum()
Definition: agp_util.hpp:841
static bool IsStrictModeWarning(int code)
Definition: agp_util.hpp:703
virtual ~CAgpErr()
Definition: agp_util.hpp:494
virtual void Msg(int code, int appliesTo=fAtThisLine)
Definition: agp_util.hpp:506
static const char * ErrorWarningOrNote(int code)
Definition: agp_util.hpp:619
@ W_ShortGap
Definition: agp_util.hpp:582
@ E_UnknownOrientation
Definition: agp_util.hpp:539
@ G_NotInGenbank
Definition: agp_util.hpp:605
@ W_ExtraTab
Definition: agp_util.hpp:564
@ E_ObjRangeNeComp
Definition: agp_util.hpp:530
@ W_CompIsNotHtgTypeIs
Definition: agp_util.hpp:596
@ G_BadObjLen
Definition: agp_util.hpp:612
@ E_PartNumberNotPlus1
Definition: agp_util.hpp:538
@ E_UnusedScaf
Definition: agp_util.hpp:548
@ E_MustBePositive
Definition: agp_util.hpp:525
@ W_CommentsAfterStart
Definition: agp_util.hpp:584
@ W_SingletonsOnly
Definition: agp_util.hpp:597
@ W_DuplicateComp
Definition: agp_util.hpp:561
@ E_PartNumberNot1
Definition: agp_util.hpp:537
@ W_CompIsNotWgsTypeIs
Definition: agp_util.hpp:575
@ E_ScafBreakingGap
Definition: agp_util.hpp:544
@ W_GapSizeNot100
Definition: agp_util.hpp:577
@ W_LooksLikeGap
Definition: agp_util.hpp:562
@ W_SingleOriNotPlus
Definition: agp_util.hpp:581
@ G_NsWithinCompSpan
Definition: agp_util.hpp:613
@ E_EmptyLine
Definition: agp_util.hpp:521
@ W_ScafNotInFull
Definition: agp_util.hpp:590
@ E_ObjMustBegin1
Definition: agp_util.hpp:536
@ E_InvalidBarInId
Definition: agp_util.hpp:550
@ E_SameGapLength
Definition: agp_util.hpp:549
@ E_InvalidValue
Definition: agp_util.hpp:522
@ E_SameConseqGaps
Definition: agp_util.hpp:543
@ W_AGPVersionCommentUnnecessary
Definition: agp_util.hpp:594
@ E_ObjRangeNeGap
Definition: agp_util.hpp:529
@ W_SpaceInObjName
Definition: agp_util.hpp:583
@ W_GapLineIgnoredCol9
Definition: agp_util.hpp:568
@ W_NaLinkageExpected
Definition: agp_util.hpp:587
@ E_NoValidLines
Definition: agp_util.hpp:542
@ W_CompIsLocalTypeNotW
Definition: agp_util.hpp:600
@ E_InvalidLinkage
Definition: agp_util.hpp:523
@ W_ObjOrderNotNumerical
Definition: agp_util.hpp:569
@ W_NoEolAtEof
Definition: agp_util.hpp:567
@ W_ObjNoComp
Definition: agp_util.hpp:557
@ E_UnknownScaf
Definition: agp_util.hpp:547
@ G_CompEndGtLength
Definition: agp_util.hpp:607
@ W_BreakingGapSameCompId
Definition: agp_util.hpp:578
@ W_LooksLikeComp
Definition: agp_util.hpp:563
@ G_InvalidObjId
Definition: agp_util.hpp:611
@ E_DuplicateObj
Definition: agp_util.hpp:535
@ W_DuplicateEvidence
Definition: agp_util.hpp:595
@ W_SpansOrder
Definition: agp_util.hpp:560
@ E_EmptyColumn
Definition: agp_util.hpp:520
@ E_ObjBegNePrevEndPlus1
Definition: agp_util.hpp:541
@ E_WithinScafGap
Definition: agp_util.hpp:545
@ W_ObjEqCompId
Definition: agp_util.hpp:576
@ W_GapLineMissingCol9
Definition: agp_util.hpp:566
@ W_AGPVersionCommentInvalid
Definition: agp_util.hpp:593
@ W_OldGapType
Definition: agp_util.hpp:588
@ W_MissingLinkage
Definition: agp_util.hpp:591
@ W_SpansOverlap
Definition: agp_util.hpp:558
@ W_AssumingVersion
Definition: agp_util.hpp:589
@ E_MustFitSeqPosType
Definition: agp_util.hpp:526
@ G_NeedVersion
Definition: agp_util.hpp:606
@ W_CompIsWgsTypeIsNot
Definition: agp_util.hpp:573
@ W_UnSingleCompNotInFull
Definition: agp_util.hpp:579
@ W_GapObjBegin
Definition: agp_util.hpp:555
@ W_ConseqGaps
Definition: agp_util.hpp:556
@ E_CompEndLtBeg
Definition: agp_util.hpp:528
@ G_TaxError
Definition: agp_util.hpp:610
@ W_OrientationZeroDeprecated
Definition: agp_util.hpp:585
@ E_ObjEndLtBeg
Definition: agp_util.hpp:527
@ G_DataError
Definition: agp_util.hpp:608
string m_messages_prev_line
Definition: agp_util.hpp:638
static const TMsgMap sMessageMap
Definition: agp_util.hpp:633
int m_apply_to
Definition: agp_util.hpp:642
const char * TStr
Definition: agp_util.hpp:629
string m_messages
Definition: agp_util.hpp:637
Detects scaffolds, object boundaries, errors that involve 2 consecutive lines, and is intended as a s...
Definition: agp_util.hpp:327
EFinalize
Whether or not the function should call Finalize() when it's done successfully.
Definition: agp_util.hpp:336
string m_line
Definition: agp_util.hpp:418
CAgpErr * GetErrorHandler()
Definition: agp_util.hpp:481
int m_error_code
Definition: agp_util.hpp:408
virtual void OnObjectChange()
Definition: agp_util.hpp:439
CRef< CAgpRow > m_prev_row
Definition: agp_util.hpp:415
bool m_at_beg
Definition: agp_util.hpp:394
CRef< CAgpRow > m_this_row
Definition: agp_util.hpp:416
virtual void OnScaffoldEnd()
Definition: agp_util.hpp:431
EAgpVersion m_agp_version
Definition: agp_util.hpp:392
CRef< CAgpErr > m_AgpErr
Definition: agp_util.hpp:474
bool m_new_obj
Definition: agp_util.hpp:404
virtual void OnGapOrComponent()
Definition: agp_util.hpp:445
bool m_line_skipped
Definition: agp_util.hpp:400
virtual void OnComment()
Definition: agp_util.hpp:466
bool m_at_end
Definition: agp_util.hpp:396
virtual bool OnError()
Definition: agp_util.hpp:450
bool m_prev_line_skipped
Definition: agp_util.hpp:401
bool m_content_line_seen
Definition: agp_util.hpp:406
int m_prev_line_num
Definition: agp_util.hpp:417
int ReadStream(CNcbiIstream &is, bool bFinalize)
Deprecated backward-compatibility wrapper.
Definition: agp_util.hpp:358
EAgpVersion GetVersion()
Definition: agp_util.hpp:483
A container for both the original string column values (Get*() methods) and the values converted to i...
Definition: agp_util.hpp:72
bool CheckComponentEnd(TAgpLen comp_len)
Definition: agp_util.hpp:263
string & GetObjectEnd()
Definition: agp_util.hpp:122
@ eGapUnknown
Definition: agp_util.hpp:187
@ eGapRepeat
Definition: agp_util.hpp:178
@ eGapShort_arm
Definition: agp_util.hpp:184
@ eGapFragment
Definition: agp_util.hpp:177
@ eGapHeterochromatin
Definition: agp_util.hpp:185
@ eGapContamination
Definition: agp_util.hpp:180
@ eGapClone
Definition: agp_util.hpp:176
@ eGapTelomere
Definition: agp_util.hpp:186
@ eGapCentromere
Definition: agp_util.hpp:183
@ eGapScaffold
Definition: agp_util.hpp:179
@ eGapCount
Definition: agp_util.hpp:189
@ eGapContig
Definition: agp_util.hpp:182
ELinkageEvidence
Definition: agp_util.hpp:195
vector< string > cols
Definition: agp_util.hpp:118
bool IsDraftComponent()
Definition: agp_util.hpp:243
CAgpReader * m_reader
Definition: agp_util.hpp:304
string & GetLinkage()
Definition: agp_util.hpp:141
TAgpPos part_number
Definition: agp_util.hpp:153
string & GetGapType()
Definition: agp_util.hpp:140
EGap gap_type
Definition: agp_util.hpp:192
EAgpVersion GetVersion()
Definition: agp_util.hpp:318
SIZE_TYPE pcomment
Definition: agp_util.hpp:117
string & GetObjectBeg()
Definition: agp_util.hpp:121
string & GetComponentId()
Definition: agp_util.hpp:126
bool GapValidAtObjectEnd() const
Definition: agp_util.hpp:254
string & GetObject()
Definition: agp_util.hpp:120
static CRef< CAgpRow > New(CAgpErr *arg, EAgpVersion agp_version=eAgpVersion_auto, CAgpReader *reader=nullptr)
Definition: agp_util.hpp:90
string LinkageEvidenceFlagsToString()
Definition: agp_util.hpp:271
CAgpErr * GetErrorHandler()
Definition: agp_util.hpp:309
int linkage_evidence_flags
a bit map which holds summary of info in linkage_evidences.
Definition: agp_util.hpp:220
char component_type
Definition: agp_util.hpp:154
map< string, EGap > TMapStrEGap
Definition: agp_util.hpp:295
static bool IsGap(char c)
Definition: agp_util.hpp:222
bool IsGap() const
Definition: agp_util.hpp:239
bool GapEndsScaffold() const
Definition: agp_util.hpp:248
string & GetOrientation()
Definition: agp_util.hpp:129
const char * TStr
Definition: agp_util.hpp:292
static bool GapValidAtObjectEnd(EGap gap_type)
Definition: agp_util.hpp:231
EAgpVersion m_agp_version
Definition: agp_util.hpp:301
static bool IsDraftComponent(char c)
Definition: agp_util.hpp:226
EOrientation orientation
Definition: agp_util.hpp:171
CRef< CAgpErr > m_AgpErr
Definition: agp_util.hpp:306
string & GetComponentType()
Definition: agp_util.hpp:124
string & GetGapLength()
Definition: agp_util.hpp:139
TLinkageEvidenceVec linkage_evidences
Definition: agp_util.hpp:217
static const char * GapTypeToString(int i)
Definition: agp_util.hpp:312
CRef< CAgpRow > Clone(void) const
Definition: agp_util.hpp:103
static CRef< CAgpRow > New(EAgpVersion agp_version=eAgpVersion_auto, CAgpReader *reader=nullptr)
Definition: agp_util.hpp:97
string & GetComponentEnd()
Definition: agp_util.hpp:128
string & GetPartNumber()
Definition: agp_util.hpp:123
static CSafeStatic< TMapStrEGap > gap_type_codes
Definition: agp_util.hpp:296
TAgpPos component_end
Definition: agp_util.hpp:158
TAgpLen gap_length
Definition: agp_util.hpp:173
bool linkage
Definition: agp_util.hpp:193
string & GetComponentBeg()
Definition: agp_util.hpp:127
string & GetLinkageEvidence()
Definition: agp_util.hpp:142
bool is_gap
Definition: agp_util.hpp:156
vector< ELinkageEvidence > TLinkageEvidenceVec
Might have duplicates, and is empty on error or if there are no actual linkage evidences (e....
Definition: agp_util.hpp:216
CObject –.
Definition: ncbiobj.hpp:180
CSafeStatic<>::
CTempString implements a light-weight string on top of a storage buffer whose lifetime management is ...
Definition: tempstr.hpp:65
Definition: map.hpp:338
Include a standard set of the NCBI C++ Toolkit most basic headers.
The NCBI C++ standard methods for dealing with std::string.
std::ofstream out("events_result.xml")
main entry point for tests
static unsigned int line_num
Definition: attributes.c:11
static void Init(void)
Definition: cursor6.c:76
static const char * str(char *buf, int n)
Definition: stats.c:84
unsigned int TSeqPos
Type for sequence locations and lengths.
Definition: ncbimisc.hpp:875
@ eNoOwnership
No ownership is assumed.
Definition: ncbi_types.h:135
EOrientation
Definition: gltypes.hpp:58
CRef< C > Ref(C *object)
Helper functions to get CRef<> and CConstRef<> objects.
Definition: ncbiobj.hpp:2015
#define NCBI_DEPRECATED
uint64_t Uint8
8-byte (64-bit) unsigned integer
Definition: ncbitype.h:105
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
IO_PREFIX::ostream CNcbiOstream
Portable alias for ostream.
Definition: ncbistre.hpp:149
IO_PREFIX::istream CNcbiIstream
Portable alias for istream.
Definition: ncbistre.hpp:146
NCBI_NS_STD::string::size_type SIZE_TYPE
Definition: ncbistr.hpp:132
#define NcbiEmptyCStr
Definition: ncbistr.hpp:59
#define NcbiEmptyString
Definition: ncbistr.hpp:122
enum ENcbiOwnership EOwnership
Ownership relations between objects.
#define NCBI_XOBJREAD_EXPORT
Definition: ncbi_export.h:1315
int i
double value_type
The numeric datatype used by the parser.
Definition: muParserDef.h:228
Static variables safety - create on demand, destroy on application termination.
Multi-threading – mutexes; rw-locks; semaphore.
bool le(T x_, T y_, T round_)
Definition: njn_approx.hpp:84
Definition: inftrees.h:24
string ToString(const wxRect &rc)
Definition: wx_utils.cpp:773
Modified on Tue Apr 23 07:39:36 2024 by modify_doxy.py rev. 669887