BDE 4.39.x Production Release
Loading...
Searching...
No Matches
balxml_listparser.h
Go to the documentation of this file.
1/// @file balxml_listparser.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// balxml_listparser.h -*-C++-*-
8#ifndef INCLUDED_BALXML_LISTPARSER
9#define INCLUDED_BALXML_LISTPARSER
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup balxml_listparser balxml_listparser
15/// @brief Provide push parser for lists.
16/// @addtogroup bal
17/// @{
18/// @addtogroup balxml
19/// @{
20/// @addtogroup balxml_listparser
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#balxml_listparser-purpose"> Purpose</a>
25/// * <a href="#balxml_listparser-classes"> Classes </a>
26/// * <a href="#balxml_listparser-description"> Description </a>
27/// * <a href="#balxml_listparser-usage"> Usage </a>
28/// * <a href="#balxml_listparser-example-1-basic-usage"> Example 1: Basic Usage </a>
29///
30/// # Purpose {#balxml_listparser-purpose}
31/// Provide push parser for lists.
32///
33/// # Classes {#balxml_listparser-classes}
34///
35/// - balxml::ListParser: push parser for lists
36///
37/// @see bdlat_arrayfunctions
38///
39/// # Description {#balxml_listparser-description}
40/// The `balxml::ListParser` class template provided by this
41/// component can be used to parse lists into an object that supports
42/// `bdlat_ArrayFunctions`.
43///
44/// This class template is a model of the `PushParser` concept, which contains
45/// the following methods:
46/// @code
47/// int beginParse(TYPE *object);
48/// // Prepare the parser to start parsing a new value and associate the
49/// // specified 'object' with the parser. Return 0 if successful and
50/// // non-zero otherwise.
51///
52/// int endParse();
53/// // Ends the parse operation and store the value parsed from the pushed
54/// // characters into the associated object. Return 0 if successful and
55/// // non-zero otherwise. The behavior is undefined unless an object is
56/// // associated with this parser. Upon successful completion, the parser
57/// // will be disassociated with the object.
58///
59/// template <typename INPUT_ITERATOR>
60/// int pushCharacters(INPUT_ITERATOR begin, INPUT_ITERATOR end);
61/// // Push the characters ranging from the specified 'begin' up to (but
62/// // not including) the specified 'end' into this parser. Return 0 if
63/// // successful and non-zero otherwise. The parameterized
64/// // 'INPUT_ITERATOR' must be dereferenceable to a 'char' value. The
65/// // behavior is undefined unless an object is associated with this
66/// // parser.
67/// @endcode
68///
69/// ## Usage {#balxml_listparser-usage}
70///
71///
72/// This section illustrates intended use of this component.
73///
74/// ### Example 1: Basic Usage {#balxml_listparser-example-1-basic-usage}
75///
76///
77/// The following snippets of code illustrate the usage of this component.
78/// Suppose you had an input stream that contained a list of doubles. The
79/// following `loadDoublesFromListStream` function loads this data into an
80/// `bsl::vector<double>`:
81/// @code
82/// #include <balxml_listparser.h>
83///
84/// #include <bdlt_date.h>
85///
86/// #include <istream>
87/// #include <iterator>
88/// #include <vector>
89/// #include <sstream>
90/// #include <string>
91///
92/// using namespace BloombergLP;
93///
94/// int parseDouble(double *result, const char *data, int dataLength);
95///
96/// int loadDoublesFromListStream(bsl::vector<double> *result,
97/// bsl::istream& stream)
98/// {
99/// enum { k_FAILURE = -1 };
100///
101/// balxml::ListParser<bsl::vector<double> > parser(&parseDouble);
102///
103/// if (0 != parser.beginParse(result)) {
104/// return k_FAILURE;
105/// }
106///
107/// if (0 != parser.pushCharacters(bsl::istreambuf_iterator<char>(stream),
108/// bsl::istreambuf_iterator<char>())) {
109/// return k_FAILURE;
110/// }
111///
112/// return parser.endParse();
113/// }
114/// @endcode
115/// The `parseDouble` function is implemented as follows:
116/// @code
117/// int parseDouble(double *result, const char *data, int dataLength)
118/// {
119/// bsl::stringstream ss(bsl::string(data, dataLength));
120/// ss >> (*result);
121/// return 0;
122/// }
123/// @endcode
124/// The following function demonstrates the `loadDoublesFromListStream`
125/// function:
126/// @code
127/// void usageExample()
128/// {
129/// const char INPUT[] = "1.5 2.0 3.8 1.0";
130///
131/// bsl::vector<double> vec;
132/// bsl::istringstream iss(INPUT);
133///
134/// int result = loadDoublesFromListStream(&vec, iss);
135///
136/// assert(0 == result);
137/// assert(4 == vec.size());
138/// assert(1.5 == vec[0]);
139/// assert(2.0 == vec[1]);
140/// assert(3.8 == vec[2]);
141/// assert(1.0 == vec[3]);
142/// }
143/// @endcode
144/// @}
145/** @} */
146/** @} */
147
148/** @addtogroup bal
149 * @{
150 */
151/** @addtogroup balxml
152 * @{
153 */
154/** @addtogroup balxml_listparser
155 * @{
156 */
157
158#include <balscm_version.h>
159
160#include <bdlat_arrayfunctions.h>
161
162#include <bslalg_typetraits.h>
163
164#include <bdlf_bind.h>
165#include <bdlf_placeholder.h>
166
167#include <bdlb_chartype.h>
168
169#include <bsls_assert.h>
170#include <bsls_review.h>
171
172#include <bsl_functional.h>
173#include <bsl_memory.h>
174#include <bsl_string.h>
175
176
177
178namespace balxml {
179 // ======================
180 // class ListParser<TYPE>
181 // ======================
182
183/// This is a push parser for lists.
184///
185/// See @ref balxml_listparser
186template <class TYPE>
188
189 // PRIVATE TYPES
190 typedef typename
192
193 struct ParseElementFunctor;
194
195 public:
196 // TYPES
197 typedef int (*ParseElementFunction)(ElementType*, const char*, int);
198 typedef bsl::function<int(ElementType*, const char*, int)>
200
201 private:
202 // PRIVATE DATA MEMBERS
203 bsl::string d_characters; // accumulated characters
204 TYPE *d_object_p; // associated object
205 ParseElementCallback d_parseElementCallback; // callback for parsing
206 // elements
207
208 private:
209 // NOT IMPLEMENTED
210 ListParser(const ListParser&);
211 ListParser& operator=(const ListParser&);
212
213 // PRIVATE MANIPULATORS
214
215 /// Append an element to the associated object having the specified
216 /// `data` of the specified `dataLength`.
217 int appendElement(const char *data, int dataLength);
218
219 public:
220 // CREATORS
221
222 /// Create a parser for lists using the specified `parseElementCallback`
223 /// functor to parse each element and the optionally specified
224 /// `basicAllocator` for supplying memory. If `basicAllocator` is 0,
225 /// the currently installed default allocator will be used.
226 explicit ListParser(ParseElementCallback parseElementCallback,
227 bslma::Allocator *basicAllocator = 0);
228
229#ifdef DOXYGEN // Generated by compiler:
230
231 ~ListParser();
232 // Destroy this object.
233
234#endif
235
236 /// Prepare the parser to start parsing a new value and associate the
237 /// specified `object` with the parser. Return 0 if successful and
238 /// non-zero otherwise.
239 int beginParse(TYPE *object);
240
241 /// Ends the parse operation and store the value parsed from the pushed
242 /// characters into the associated object. Return 0 if successful and non-zero otherwise.
243 ///
244 /// \pre The behavior is undefined unless an object is
245 /// associated with this parser. Upon successful completion, the parser
246 /// will be disassociated with the object.
247 int endParse();
248
249 /// Push the characters ranging from the specified `begin` up to (but
250 /// not including) the specified `end` into this parser. Return 0 if
251 /// successful and non-zero otherwise. The parameterized
252 /// `INPUT_ITERATOR` must be dereferenceable to a `char` value.
253 ///
254 /// \pre The behavior is undefined unless an object is associated with this
255 /// parser.
256 template <class INPUT_ITERATOR>
257 int pushCharacters(INPUT_ITERATOR begin, INPUT_ITERATOR end);
258};
259
260// ============================================================================
261// INLINE DEFINITIONS
262// ============================================================================
263
264 // ----------------------
265 // class ListParser<TYPE>
266 // ----------------------
267
268// PRIVATE MANIPULATORS
269
270template <class TYPE>
272 // PUBLIC DATA
274 const char *d_data;
276
277 // MANIPULATORS
278 int operator()(ElementType *elem)
279 {
280 return d_parseElementCallback(elem, d_data, d_dataLength);
281 }
282 template <class t_ELEM>
283 int operator()(t_ELEM *)
284 {
285 return -1;
286 }
287};
288
289template <class TYPE>
290int ListParser<TYPE>::appendElement(const char *data, int dataLength)
291{
292 BSLS_ASSERT(data);
293 BSLS_ASSERT(0 < dataLength);
294
295 enum { k_SUCCESS = 0, k_FAILURE = -1 };
296
297 const int i = static_cast<int>(bdlat_ArrayFunctions::size(*d_object_p));
298
299 bdlat_ArrayFunctions::resize(d_object_p, i + 1);
300
301 ParseElementFunctor parseElementFunctor = {d_parseElementCallback,
302 data,
303 dataLength};
304
305 if (0 != bdlat_ArrayFunctions::manipulateElement(d_object_p,
306 parseElementFunctor,
307 i)) {
308 // remove the new object from the array
309 bdlat_ArrayFunctions::resize(d_object_p, i);
310
311 return k_FAILURE; // RETURN
312 }
313
314 return k_SUCCESS;
315}
316
317// CREATORS
318
319template <class TYPE>
321 bslma::Allocator *basicAllocator)
322: d_characters(basicAllocator)
323, d_object_p(0)
324, d_parseElementCallback(bsl::allocator_arg_t(),
325 bsl::allocator<ParseElementCallback>(basicAllocator),
326 parseElementCallback)
327{
328}
329
330// MANIPULATORS
331
332template <class TYPE>
334{
335 BSLS_ASSERT(object);
336
337 enum { k_SUCCESS = 0 };
338
339 d_characters.clear();
340 d_object_p = object;
341
342 bdlat_ArrayFunctions::resize(d_object_p, 0);
343
344 return k_SUCCESS;
345}
346
347template <class TYPE>
349{
350 BSLS_ASSERT(d_object_p);
351
352 enum { k_SUCCESS = 0, k_FAILURE = -1 };
353
354 if (!d_characters.empty()) {
355 if (0 != appendElement(d_characters.data(),
356 static_cast<int>(d_characters.length()))) {
357 return k_FAILURE; // RETURN
358 }
359 }
360
361 d_object_p = 0;
362
363 return k_SUCCESS;
364}
365
366template <class TYPE>
367template <class INPUT_ITERATOR>
368int ListParser<TYPE>::pushCharacters(INPUT_ITERATOR begin, INPUT_ITERATOR end)
369{
370 BSLS_ASSERT(d_object_p);
371
372 enum { k_SUCCESS = 0, k_FAILURE = -1 };
373
374 while (begin != end) {
375 const char character = *begin;
376
377 ++begin;
378
379 if (bdlb::CharType::isSpace(character)) {
380 if (!d_characters.empty()) {
381 if (0 != appendElement(
382 d_characters.data(),
383 static_cast<int>(d_characters.length()))) {
384 return k_FAILURE; // RETURN
385 }
386
387 d_characters.clear();
388 }
389 }
390 else {
391 d_characters.push_back(character);
392 }
393 }
394
395 return k_SUCCESS;
396}
397
398} // close package namespace
399
400
401#endif // ! defined(INCLUDED_BAEXML_LISTPARSER)
402
403// ----------------------------------------------------------------------------
404// Copyright 2015 Bloomberg Finance L.P.
405//
406// Licensed under the Apache License, Version 2.0 (the "License");
407// you may not use this file except in compliance with the License.
408// You may obtain a copy of the License at
409//
410// http://www.apache.org/licenses/LICENSE-2.0
411//
412// Unless required by applicable law or agreed to in writing, software
413// distributed under the License is distributed on an "AS IS" BASIS,
414// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
415// See the License for the specific language governing permissions and
416// limitations under the License.
417// ----------------------------- END-OF-FILE ----------------------------------
418
419/** @} */
420/** @} */
421/** @} */
Definition balxml_listparser.h:187
int(* ParseElementFunction)(ElementType *, const char *, int)
Definition balxml_listparser.h:197
int pushCharacters(INPUT_ITERATOR begin, INPUT_ITERATOR end)
Definition balxml_listparser.h:368
int endParse()
Definition balxml_listparser.h:348
int beginParse(TYPE *object)
Definition balxml_listparser.h:333
bsl::function< int(ElementType *, const char *, int)> ParseElementCallback
Definition balxml_listparser.h:199
Definition bslstl_string.h:1252
Forward declaration.
Definition bslstl_function.h:946
Definition bslma_allocator.h:545
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1976
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
Definition balxml_base64parser.h:150
int manipulateElement(TYPE *array, MANIPULATOR &manipulator, int index)
void resize(TYPE *array, int newSize)
bsl::size_t size(const TYPE &array)
Return the number of elements in the specified array.
Definition bdlat_valuetypefunctions.h:939
Definition balxml_listparser.h:271
int operator()(ElementType *elem)
Definition balxml_listparser.h:278
int d_dataLength
Definition balxml_listparser.h:275
ParseElementCallback & d_parseElementCallback
Definition balxml_listparser.h:273
int operator()(t_ELEM *)
Definition balxml_listparser.h:283
const char * d_data
Definition balxml_listparser.h:274
Definition bdlat_arrayfunctions.h:756
static bool isSpace(char character)
Definition bdlb_chartype.h:814