1 #ifndef CORELIB___NCBIDIAG_P__HPP
2 #define CORELIB___NCBIDIAG_P__HPP
3 
4 /*  $Id: ncbidiag_p.hpp 611586 2020-07-08 13:47:46Z 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:  Vyacheslav Kononenko
30  *
31  *
32  */
33 
34 /// @file ncbidiag_p.hpp
35 ///
36 ///   Defines NCBI C++ service classes and functions for diagnostic APIs,
37 ///   classes, and macros.
38 ///
39 ///   More elaborate documentation could be found in:
40 ///     http://ncbi.github.io/cxx-toolkit/pages/ch_log
41 
42 #include <corelib/ncbiutil.hpp>
43 #include <deque>
44 
45 BEGIN_NCBI_SCOPE
46 
47 
48 /////////////////////////////////////////////////////////////////////////////
49 /// Forward declaration
50 
51 class CNcbiDiag;
52 
53 enum EDiagFilterAction {
54     eDiagFilter_None,
55     eDiagFilter_Accept,
56     eDiagFilter_Reject
57 };
58 
59 
60 /////////////////////////////////////////////////////////////////////////////
61 ///
62 /// CDiagStrMatcher --
63 ///
64 /// Abstract class that matches a char* string.
65 ///
66 
67 class CDiagStrMatcher
68 {
69 public:
70     virtual ~CDiagStrMatcher();
71 
72     /// Return true if str matches for this object
73     virtual bool Match(const char* str) const = 0;
74 
75     // Print state
76     virtual void Print(ostream& out) const = 0;
77 };
78 
79 
80 
81 /////////////////////////////////////////////////////////////////////////////
82 ///
83 /// CDiagStrEmptyMatcher --
84 ///
85 /// Specialization of CDiagStrMatcher that matches an empty string.
86 ///
87 
88 class CDiagStrEmptyMatcher : public CDiagStrMatcher
89 {
90 public:
91     /// Return true if str is empty
92     virtual bool Match(const char* str) const;
93 
94     // Print state
95     virtual void Print(ostream& out) const;
96 };
97 
98 
99 
100 /////////////////////////////////////////////////////////////////////////////
101 ///
102 /// CDiagStrStringMatcher --
103 ///
104 /// Specialization of CDiagStrMatcher that matches a given string.
105 ///
106 
107 class CDiagStrStringMatcher : public CDiagStrMatcher
108 {
109 public:
110     // Constructor - set the pattern to match
CDiagStrStringMatcher(const string & pattern)111     CDiagStrStringMatcher(const string& pattern)
112         : m_Pattern(pattern)
113     {}
114 
115     /// Return true if str is equal to pattern
116     virtual bool Match(const char* str) const;
117 
118     // Print state
119     virtual void Print(ostream& out) const;
120 
121 private:
122     string m_Pattern;
123 };
124 
125 /////////////////////////////////////////////////////////////////////////////
126 ///
127 /// CDiagStrPathMatcher --
128 ///
129 /// Specialization of CDiagStrMatcher that matches a path to the source file
130 ///
131 
132 class CDiagStrPathMatcher : public CDiagStrMatcher
133 {
134 public:
135     // Constructor - set the pattern to match. The pattern is converted
136     // to UNIX format ('/' rather than '\' or ':').
137     CDiagStrPathMatcher(const string& pattern);
138 
139     /// Return true if str is equal to pattern
140     virtual bool Match(const char* str) const;
141 
142     // Print state
143     virtual void Print(ostream& out) const;
144 
145 private:
146     string m_Pattern;
147 };
148 
149 /////////////////////////////////////////////////////////////////////////////
150 ///
151 /// CDiagStrErrCodeMatcher --
152 ///
153 /// Specialization of CDiagStrMatcher that matches error codes
154 ///
155 
156 class CDiagStrErrCodeMatcher : public CDiagStrMatcher
157 {
158 public:
159     // Constructor - set the pattern to match.
160     // Pattern ::= coderange '.' coderange
161     // coderange ::= (int | intpair) (',' (int | intpair))*
162     // intpair ::= int '-' int
163     // int ::= integer
164     CDiagStrErrCodeMatcher(const string& pattern);
165 
166     /// Return true if str matches pattern
167     /// str ::= errcode ':' subcode
168     virtual bool Match(const char* str) const;
169 
170     // Print state
171     virtual void Print(ostream& out) const;
172 
173 private:
174     typedef int  TCode;
175     typedef vector< pair<TCode, TCode> >  TPattern;
176 
177     static void x_Parse(TPattern& pattern, const string& str);
178     static bool x_Match(const TPattern& pattern, TCode code);
179     static void x_Print(const TPattern& pattern, ostream& out);
180     TPattern m_Code;
181     TPattern m_SubCode;
182 };
183 
184 
185 /////////////////////////////////////////////////////////////////////////////
186 ///
187 /// CDiagMatcher --
188 ///
189 /// Matcher of CNcbiDiag for module, class and function name if any
190 ///
191 
192 class CDiagMatcher
193 {
194 public:
195     // Takes ownership of module, nclass and function.
196     // If NULL pointer passed as CDiagStrMatcher*, then it accepts anything
CDiagMatcher(CDiagStrMatcher * errcode,CDiagStrMatcher * file,CDiagStrMatcher * module,CDiagStrMatcher * nclass,CDiagStrMatcher * func,EDiagFilterAction action)197     CDiagMatcher(CDiagStrMatcher*  errcode,
198                  CDiagStrMatcher*  file,
199                  CDiagStrMatcher*  module,
200                  CDiagStrMatcher*  nclass,
201                  CDiagStrMatcher*  func,
202                  EDiagFilterAction action)
203         : m_ErrCode(errcode), m_File(file),
204           m_Module(module), m_Class(nclass), m_Function(func),
205           m_Action(action), m_DiagSev(eDiag_Info)
206     {}
207 
208     EDiagFilterAction MatchErrCode(int code, int subcode) const;
209 
210     // Check if the filter accepts a filename
211     EDiagFilterAction MatchFile(const char* file) const;
212 
213     // Match whole set
214     EDiagFilterAction Match(const char* module,
215                             const char* nclass,
216                             const char* function) const;
217 
218     // Print state
219     void Print(ostream& out) const;
220 
GetSeverity() const221     EDiagSev GetSeverity() const { return m_DiagSev; }
SetSeverity(EDiagSev sev)222     void SetSeverity(EDiagSev sev) { m_DiagSev = sev; }
223 
IsErrCodeMatcher(void) const224     bool IsErrCodeMatcher(void) const {return m_ErrCode.get() != 0;}
225 
226 private:
227     AutoPtr<CDiagStrMatcher> m_ErrCode;
228     AutoPtr<CDiagStrMatcher> m_File;
229     AutoPtr<CDiagStrMatcher> m_Module;
230     AutoPtr<CDiagStrMatcher> m_Class;
231     AutoPtr<CDiagStrMatcher> m_Function;
232     EDiagFilterAction        m_Action;
233     EDiagSev                 m_DiagSev;
234 };
235 
236 
237 
238 /////////////////////////////////////////////////////////////////////////////
239 ///
240 /// CDiagFilter --
241 ///
242 /// Checks if SDiagMessage should be passed.
243 /// Contains 0..N CDiagMatcher objects
244 ///
245 
246 class NCBI_XNCBI_EXPORT CDiagFilter
247 {
248 public:
249     // 'tors
250     CDiagFilter(void);
251     ~CDiagFilter(void);
252 
253     /// Check if the filter accepts message.
254     /// In addition check an exception and all its backlog if specified.
255     EDiagFilterAction Check(const CNcbiDiag&  msg, const CException* ex = NULL) const;
256 
257     /// Fill the filter from a string
258     void Fill(const char* filter_string);
259 
260     /// Print state
261     void Print(ostream& out) const;
262 
GetFilterStr(void) const263     const string& GetFilterStr(void) const { return m_Filter; }
264 
265     void Append(const char* filter_string);
266 
267 private:
268     /// Check if the filter accepts errcode
269     EDiagFilterAction x_CheckErrCode(int code, int subcode, EDiagSev sev) const;
270 
271     /// Check if the filter accepts path
272     EDiagFilterAction x_CheckFile(const char* file, EDiagSev sev) const;
273 
274     // Check if the filter accepts the location
275     EDiagFilterAction x_CheckLocation(const char* module,
276                                       const char* nclass,
277                                       const char* function,
278                                       EDiagSev    sev) const;
279 
280     // CSyntaxParser can insert CDiagStrMatcher and clean
281     friend class CDiagSyntaxParser;
282 
283     // Insert a new matcher into the end of list
284     // Take ownership of the matcher
InsertMatcher(CDiagMatcher * matcher)285     void InsertMatcher(CDiagMatcher *matcher)
286     {
287         m_Matchers.push_back(matcher);
288     }
289 
290     // Negative matchers should be processed first
291     // because they are *AND NOT* matchers, not just *NOT*.
InsertNegativeMatcher(CDiagMatcher * matcher)292     void InsertNegativeMatcher(CDiagMatcher *matcher)
293     {
294         m_Matchers.push_front(matcher);
295         ++m_NotMatchersNum;
296     }
297 
298     // Remove and destroy all matchers, if any
299     void Clean(void);
300 
301 private:
302     typedef deque< AutoPtr<CDiagMatcher> >  TMatchers;
303     string m_Filter;
304     TMatchers m_Matchers;
305     size_t    m_NotMatchersNum;
306 };
307 
308 
309 
310 /////////////////////////////////////////////////////////////////////////////
311 ///
312 /// CDiagLexParser --
313 ///
314 /// Lexical parser
315 ///
316 
317 class CDiagLexParser
318 {
319 public:
320     // Symbols
321     enum ESymbol {
322         eDone,           // to mark that symbol was processed
323         eExpl,           // ! processed
324         ePath,           // path started with /
325         eId,             // id and ?
326         eDoubleColon,    // ::
327         ePars,           // ()
328         eBrackets,       // []
329         eErrCode,        // (code.subcode)
330         eEnd             // end of stream
331     };
332 
333     // Constructor
334     CDiagLexParser();
335 
336     // Takes next lexical symbol from the stream
337     ESymbol Parse(istream& in);
338 
339     // Returns id or ? string when eId is returned from parse()
GetId() const340     const string& GetId() const  { return m_Str; }
341 
342     // Returns current position
GetPos() const343     int GetPos() const { return m_Pos; }
344 
345 private:
346     string  m_Str;
347     int     m_Pos;
348 };
349 
350 
351 
352 /////////////////////////////////////////////////////////////////////////////
353 ///
354 /// CDiagSyntaxParser --
355 ///
356 /// Parses string and fills CDiagFilter with CDiagStrMatchers
357 ///
358 
359 class CDiagSyntaxParser
360 {
361 public:
362     // Error info type
363     typedef pair<const char*, int> TErrorInfo;
364 
365     // Constructor
366     CDiagSyntaxParser();
367 
368     // Parses stream and fills CDiagFilter to with CDiagStrMatchers
369     void Parse(istream& in, CDiagFilter& to);
370 
371 private:
372     enum EInto {
373         eModule,
374         eFunction
375     };
376 
377     // Puts CDiagMessageMatcher into CDiagFilter
378     void x_PutIntoFilter(CDiagFilter& to, EInto into);
379 
380     // Creates a CDiagStrMatcher by string
381     static CDiagStrMatcher* x_CreateMatcher(const string& str);
382 
383     /// "Info", "Warning", etc converted to enum value
384     /// Throws an excpetion if incorrect value passed
385     EDiagSev x_GetDiagSeverity(const string& sev_str);
386 
387 private:
388     typedef vector< AutoPtr<CDiagStrMatcher> >  TMatchers;
389     TMatchers                 m_Matchers;
390     AutoPtr<CDiagStrErrCodeMatcher>  m_ErrCodeMatcher;
391     AutoPtr<CDiagStrMatcher>  m_FileMatcher;
392     int                       m_Pos;
393     bool                      m_Negative;
394     EDiagSev                  m_DiagSev;
395 };
396 
397 
398 END_NCBI_SCOPE
399 
400 #endif  /* CORELIB___NCBIDIAG_P__HPP */
401