/src/resiprocate/resip/stack/LazyParser.hxx
Line | Count | Source (jump to first uncovered line) |
1 | | #if !defined(RESIP_LAZYPARSER_HXX) |
2 | | #define RESIP_LAZYPARSER_HXX |
3 | | |
4 | | #ifdef HAVE_CONFIG_H |
5 | | #include "config.h" |
6 | | #endif |
7 | | |
8 | | #include <iosfwd> |
9 | | #include "resip/stack/HeaderFieldValue.hxx" |
10 | | #include "rutil/resipfaststreams.hxx" |
11 | | |
12 | | namespace resip |
13 | | { |
14 | | |
15 | | class ParseBuffer; |
16 | | class Data; |
17 | | |
18 | | /** |
19 | | @brief The base-class for all lazily-parsed SIP grammar elements. |
20 | | |
21 | | Subclasses of this are parse-on-access; the parse will be carried out (if |
22 | | it hasn't already) the first time one of the members is accessed. Right now, |
23 | | all header field values and SIP bodies are lazily parsed. |
24 | | |
25 | | Application writers are expected to make consistent use of isWellFormed() in |
26 | | order to determine whether an element is parseable. Using a try/catch block |
27 | | around accesses will not work as expected, since an exception will only be |
28 | | thrown the _first_ time an access is made, and it is determined that the |
29 | | element isn't parseable. |
30 | | |
31 | | @ingroup resip_crit |
32 | | @ingroup sip_parse |
33 | | */ |
34 | | class LazyParser |
35 | | { |
36 | | public: |
37 | | /** |
38 | | @internal |
39 | | */ |
40 | | explicit LazyParser(const HeaderFieldValue& headerFieldValue); |
41 | | |
42 | | /** |
43 | | @internal |
44 | | */ |
45 | | LazyParser(const char* buf, int length); |
46 | | |
47 | | /** |
48 | | @internal |
49 | | */ |
50 | | LazyParser(const HeaderFieldValue& headerFieldValue, |
51 | | HeaderFieldValue::CopyPaddingEnum e); |
52 | | |
53 | | /** |
54 | | @internal |
55 | | */ |
56 | | LazyParser(const LazyParser& rhs); |
57 | | |
58 | | /** |
59 | | @internal |
60 | | */ |
61 | | LazyParser(const LazyParser& rhs,HeaderFieldValue::CopyPaddingEnum e); |
62 | | |
63 | | /** |
64 | | @internal |
65 | | */ |
66 | | LazyParser& operator=(const LazyParser& rhs); |
67 | | virtual ~LazyParser(); |
68 | | |
69 | | /** |
70 | | @internal |
71 | | */ |
72 | | virtual EncodeStream& encodeParsed(EncodeStream& str) const = 0; |
73 | | |
74 | | /** |
75 | | @internal |
76 | | */ |
77 | | virtual void parse(ParseBuffer& pb) = 0; |
78 | | |
79 | | /** |
80 | | @brief Encodes this element to a stream, in the fashion it should be |
81 | | represented on the wire. |
82 | | @param str The ostream to encode to. |
83 | | @return A reference to str. |
84 | | */ |
85 | | EncodeStream& encode(EncodeStream& str) const; |
86 | | |
87 | | /** |
88 | | @brief Returns true iff a parse has been attempted. |
89 | | @note This means that this will return true if a parse failed earlier. |
90 | | */ |
91 | 84.7k | bool isParsed() const {return (mState!=NOT_PARSED);} |
92 | | |
93 | | /** |
94 | | @internal |
95 | | */ |
96 | 0 | HeaderFieldValue& getHeaderField() { return mHeaderField; } |
97 | | |
98 | | // call (internally) before every access |
99 | | /** |
100 | | @internal |
101 | | */ |
102 | | void checkParsed() const |
103 | 231k | { |
104 | 231k | if (mState==NOT_PARSED) |
105 | 156k | { |
106 | 156k | doParse(); |
107 | 156k | } |
108 | 231k | } |
109 | | void checkParsed() |
110 | 169k | { |
111 | 169k | const LazyParser* constThis = const_cast<const LazyParser*>(this); |
112 | 169k | constThis->checkParsed(); |
113 | 169k | mState=DIRTY; |
114 | 169k | } |
115 | | void doParse() const; |
116 | 0 | inline void markDirty() const {mState=DIRTY;} |
117 | | |
118 | | /** |
119 | | @brief Returns true iff this element was parsed successfully, according |
120 | | to the implementation of parse(). |
121 | | |
122 | | App writers are expected to use this extensively, since a failure in |
123 | | the parse-on-access will throw an exception the _first_ time access is |
124 | | made, but nothing will happen on subsequent accesses. (Writing a |
125 | | try/catch block when you try to inspect the members of a subclass will |
126 | | only work as intended if the subclass hasn't been accessed before.) |
127 | | */ |
128 | | bool isWellFormed() const; |
129 | | protected: |
130 | | LazyParser(); |
131 | | |
132 | | // called in destructor and on assignment |
133 | | void clear(); |
134 | | |
135 | | // context for error messages |
136 | | virtual const Data& errorContext() const = 0; |
137 | | |
138 | | private: |
139 | | // !dlb! bit of a hack until the dust settles |
140 | | friend class Contents; |
141 | | |
142 | | HeaderFieldValue mHeaderField; |
143 | | |
144 | | typedef enum |
145 | | { |
146 | | NOT_PARSED, |
147 | | WELL_FORMED, // Parsed, well-formed, but underlying buffer is still valid |
148 | | MALFORMED, // Parsed, malformed, underlying buffer is still valid |
149 | | DIRTY // Well-formed, and underlying buffer is invalid |
150 | | } ParseState; |
151 | | mutable ParseState mState; |
152 | | }; |
153 | | |
154 | | #ifndef RESIP_USE_STL_STREAMS |
155 | | EncodeStream& |
156 | | operator<<(EncodeStream&, const LazyParser& lp); |
157 | | #endif |
158 | | |
159 | | //need this for MD5Stream |
160 | | std::ostream& |
161 | | operator<<(std::ostream&, const LazyParser& lp); |
162 | | |
163 | | } |
164 | | |
165 | | #endif |
166 | | |
167 | | /* ==================================================================== |
168 | | * The Vovida Software License, Version 1.0 |
169 | | * |
170 | | * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved. |
171 | | * |
172 | | * Redistribution and use in source and binary forms, with or without |
173 | | * modification, are permitted provided that the following conditions |
174 | | * are met: |
175 | | * |
176 | | * 1. Redistributions of source code must retain the above copyright |
177 | | * notice, this list of conditions and the following disclaimer. |
178 | | * |
179 | | * 2. Redistributions in binary form must reproduce the above copyright |
180 | | * notice, this list of conditions and the following disclaimer in |
181 | | * the documentation and/or other materials provided with the |
182 | | * distribution. |
183 | | * |
184 | | * 3. The names "VOCAL", "Vovida Open Communication Application Library", |
185 | | * and "Vovida Open Communication Application Library (VOCAL)" must |
186 | | * not be used to endorse or promote products derived from this |
187 | | * software without prior written permission. For written |
188 | | * permission, please contact vocal@vovida.org. |
189 | | * |
190 | | * 4. Products derived from this software may not be called "VOCAL", nor |
191 | | * may "VOCAL" appear in their name, without prior written |
192 | | * permission of Vovida Networks, Inc. |
193 | | * |
194 | | * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED |
195 | | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
196 | | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND |
197 | | * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA |
198 | | * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES |
199 | | * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, |
200 | | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
201 | | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
202 | | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
203 | | * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
204 | | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE |
205 | | * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
206 | | * DAMAGE. |
207 | | * |
208 | | * ==================================================================== |
209 | | * |
210 | | * This software consists of voluntary contributions made by Vovida |
211 | | * Networks, Inc. and many individuals on behalf of Vovida Networks, |
212 | | * Inc. For more information on Vovida Networks, Inc., please see |
213 | | * <http://www.vovida.org/>. |
214 | | * |
215 | | */ |