Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RooStreamParser.cxx
Go to the documentation of this file.
1/*****************************************************************************
2 * Project: RooFit *
3 * Package: RooFitCore *
4 * @(#)root/roofitcore:$Id$
5 * Authors: *
6 * WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu *
7 * DK, David Kirkby, UC Irvine, dkirkby@uci.edu *
8 * *
9 * Copyright (c) 2000-2005, Regents of the University of California *
10 * and Stanford University. All rights reserved. *
11 * *
12 * Redistribution and use in source and binary forms, *
13 * with or without modification, are permitted according to the terms *
14 * listed in LICENSE (http://roofit.sourceforge.net/license.txt) *
15 *****************************************************************************/
16
17//////////////////////////////////////////////////////////////////////////////
18//
19// RooStreamParser is a utility class to parse istreams into tokens and optionally
20// convert them into basic types (double,int,string)
21//
22// The general tokenizing philosophy is that there are two kinds of tokens: value
23// and punctuation. The former are variable length, the latter always
24// one character. A token is terminated if one of the following conditions
25// occur
26// - space character found (' ',tab,newline)
27// - change of token type (value -> punctuation or vv)
28// - end of fixed-length token (punctuation only)
29// - start or end of quoted string
30//
31// The parser is aware of floating point notation and will assign leading
32// minus signs, decimal points etc to a value token when this is obvious
33// from the context. The definition of what is punctuation can be redefined.
34//
35
36#ifndef _WIN32
37#include <strings.h>
38#endif
39
40#include "RooStreamParser.h"
41#include "RooMsgService.h"
42#include "RooFitImplHelpers.h"
43
44#include <cstdlib>
45#include <istream>
46
47using std::istream, std::endl;
48
49
50
51////////////////////////////////////////////////////////////////////////////////
52/// Construct parser on given input stream
53
55 _is(&is), _atEOL(false), _atEOF(false), _prefix(""), _punct("()[]<>|/\\:?.,=+-&^%$#@!`~")
56{
57}
58
59
60////////////////////////////////////////////////////////////////////////////////
61/// Construct parser on given input stream. Use given errorPrefix to
62/// prefix any parsing error messages
63
65 _is(&is), _atEOL(false), _atEOF(false), _prefix(errorPrefix), _punct("()[]<>|/\\:?.,=+-&^%$#@!`~")
66{
67}
68
69////////////////////////////////////////////////////////////////////////////////
70/// If true, parser is at end of line in stream
71
73{
74 Int_t nc(_is->peek()) ;
75 return (nc=='\n'||nc==-1) ;
76}
77
78
79
80////////////////////////////////////////////////////////////////////////////////
81/// Change list of characters interpreted as punctuation
82
87
88
89
90////////////////////////////////////////////////////////////////////////////////
91/// Check if given char is considered punctuation
92
94{
95 const char* punct = _punct.Data() ;
96 for (int i = 0; i < _punct.Length(); i++) {
97 if (punct[i] == c) {
98 return true;
99 }
100 }
101 return false ;
102}
103
104
105
106////////////////////////////////////////////////////////////////////////////////
107/// Read one token separated by any of the know punctuation characters
108/// This function recognizes and handles comment lines in the istream (those
109/// starting with '#', quoted strings ("") the content of which is not tokenized
110/// and '+-.' characters that are part of a floating point numbers and are exempt
111/// from being interpreted as a token separator in case '+-.' are defined as
112/// token separators.
113
115{
116 // Smart tokenizer. Absorb white space and token must be either punctuation or alphanum
117 bool first(true);
118 bool quotedString(false);
119 bool lineCont(false);
120 char buffer[64000];
121 char c(0);
122 char cnext = '\0';
123 char cprev = ' ';
124 bool haveINF(false) ;
125 Int_t bufptr(0) ;
126
127 // Check for end of file
128 if (_is->eof() || _is->fail()) {
129 _atEOF = true ;
130 return TString("") ;
131 }
132
133 //Ignore leading newline
134 if (_is->peek()=='\n') {
135 _is->get(c) ;
136
137 // If new line starts with #, zap it
138 while (_is->peek()=='#') {
139 zapToEnd(false) ;
140 _is->get(c) ; // absorb newline
141 }
142 }
143
144 while(true) {
145 // Buffer overflow protection
146 if (bufptr >= 63999) {
147 oocoutW(nullptr, InputArguments)
148 << "RooStreamParser::readToken: token length exceeds buffer capacity, terminating token early" << std::endl;
149 break;
150 }
151
152 // Read next char
153 _is->get(c) ;
154
155
156
157 // Terminate at EOF, EOL or trouble
158 if (_is->eof() || _is->fail() || c=='\n') break ;
159
160 // Terminate as SPACE, unless we haven't seen any non-SPACE yet
161 if (isspace(c)) {
162 if (first) {
163 continue;
164 } else if (!quotedString) {
165 break;
166 }
167 }
168
169 // If '-' or '/' see what the next character is
170 if (c == '.' || c=='-' || c=='+' || c=='/' || c=='\\') {
171 _is->get(cnext) ;
172
173
174 if (cnext=='I' || cnext=='i') {
175 char tmp1;
176 char tmp2;
177 _is->get(tmp1);
178 _is->get(tmp2);
179 _is->putback(tmp2);
180 _is->putback(tmp1);
181 haveINF = ((cnext == 'I' && tmp1 == 'N' && tmp2 == 'F') || (cnext == 'i' && tmp1 == 'n' && tmp2 == 'f'));
182 } else {
183 haveINF = false ;
184 }
185
186 _is->putback(cnext) ;
187 }
188
189
190 // Check for line continuation marker
191 if (c=='\\' && cnext=='\\') {
192 // Kill rest of line including std::endline marker
193 zapToEnd(false) ;
194 _is->get(c) ;
195 lineCont=true ;
196 break ;
197 }
198
199 // Stop if begin of comments is encountered
200 if (c=='/' && cnext=='/') {
201 zapToEnd(false) ;
202 break ;
203 }
204
205 // Special handling of quoted strings
206 if (c=='"') {
207 if (first) {
209 } else if (!quotedString) {
210 // Terminate current token. Next token will be quoted string
211 _is->putback('"') ;
212 break ;
213 }
214 }
215
216 if (!quotedString) {
217 // Decide if next char is punctuation (exempt - and . that are part of floating point numbers, or +/- preceding INF)
218 if (isPunctChar(c) && !(c=='.' && (isdigit(cnext)||isdigit(cprev)))
219 && !((c=='-'||c=='+') && isdigit(cnext) && (cprev == 'e' || cprev == 'E'))
220 && (!first || !((c=='-'||c=='+') && (isdigit(cnext)||cnext=='.'||haveINF)))) {
221
222 if (first) {
223 // Make this a one-char punctuation token
224 buffer[bufptr++]=c ;
225 break ;
226 } else {
227 // Put back punct. char and terminate current alphanum token
228 _is->putback(c) ;
229 break ;
230 }
231 }
232 } else {
233 // Inside quoted string conventional tokenizing rules do not apply
234
235 // Terminate token on closing quote
236 if (c=='"' && !first) {
237 buffer[bufptr++]=c ;
239 break ;
240 }
241 }
242
243 // Store in buffer
244 buffer[bufptr++]=c ;
245 first=false ;
246 cprev=c ;
247 }
248
249 if (_is->eof() || _is->bad()) {
250 _atEOF = true ;
251 }
252
253 // Check if closing quote was encountered
254 if (quotedString) {
255 oocoutW(nullptr,InputArguments) << "RooStreamParser::readToken: closing quote (\") missing" << std::endl ;
256 }
257
258 // Absorb trailing white space or absorb rest of line if // is encountered
259 if (c=='\n') {
260 if (!lineCont) {
261 _is->putback(c) ;
262 }
263 } else {
264 c = _is->peek() ;
265
266 while ((isspace(c) || c=='/') && c != '\n') {
267 if (c=='/') {
268 _is->get(c) ;
269 if (_is->peek()=='/') {
270 zapToEnd(false) ;
271 } else {
272 _is->putback('/') ;
273 }
274 break ;
275 } else {
276 _is->get(c) ;
277 c = _is->peek() ;
278 }
279 }
280 }
281
282 // If no token was read line is continued, return first token on next line
283 if (bufptr==0 && lineCont) {
284 return readToken() ;
285 }
286
287 // Zero terminate buffer and convert to TString
288 buffer[bufptr]=0 ;
289 return TString(buffer) ;
290}
291
292
293
294////////////////////////////////////////////////////////////////////////////////
295/// Read an entire line from the stream and return as TString
296/// This method recognizes the use of '\\' in the istream
297/// as line continuation token.
298
300{
301 char c;
302 char buffer[64000];
303 Int_t nfree(63999);
304
305 if (_is->peek() == '\n')
306 _is->get(c);
307
308 // Read till end of line
309 _is->getline(buffer, nfree, '\n');
310
311 // Look for eventual continuation line sequence
312 char *pcontseq = strstr(buffer, "\\\\");
313 if (pcontseq)
314 nfree -= (pcontseq - buffer);
315 while (pcontseq) {
316 _is->getline(pcontseq, nfree, '\n');
317
318 char *nextpcontseq = strstr(pcontseq, "\\\\");
319 if (nextpcontseq)
322 }
323
324 // Chop eventual comments
325 char *pcomment = strstr(buffer, "//");
326 if (pcomment)
327 *pcomment = 0;
328
329 // Chop leading and trailing space
330 char *pstart = buffer;
331 while (isspace(*pstart)) {
332 pstart++;
333 }
334 char *pend = buffer + strlen(buffer) - 1;
335 if (pend > pstart) {
336 while (isspace(*pend)) {
337 *pend-- = 0;
338 }
339 }
340
341 if (_is->eof() || _is->fail()) {
342 _atEOF = true;
343 }
344
345 // Convert to TString
346 return TString(pstart);
347}
348
349
350
351////////////////////////////////////////////////////////////////////////////////
352/// Eat all characters up to and including then end of the
353/// current line. If inclContLines is true, all continuation lines
354/// marked by the '\\' token are zapped as well
355
357{
358 // Skip over everything until the end of the current line
359 if (_is->peek()!='\n') {
360
361 char buffer[64000];
362 Int_t nfree(63999);
363
364 // Read till end of line
365 _is->getline(buffer, nfree, '\n');
366
367 if (inclContLines) {
368 // Look for eventual continuation line sequence
369 char *pcontseq = strstr(buffer, "\\\\");
370 if (pcontseq)
371 nfree -= (pcontseq - buffer);
372 while (pcontseq) {
373 _is->getline(pcontseq, nfree, '\n');
374
375 char *nextpcontseq = strstr(pcontseq, "\\\\");
376 if (nextpcontseq)
379 }
380 }
381
382 // Put back newline character in stream buffer
383 _is->putback('\n') ;
384 }
385}
386
387
388
389////////////////////////////////////////////////////////////////////////////////
390/// Read the next token and return true if it is identical to the given 'expected' token.
391
393{
395
396 bool error=token.CompareTo(expected) ;
397 if (error && !_prefix.IsNull()) {
398 oocoutW(nullptr,InputArguments) << _prefix << ": parse error, expected '"
399 << expected << "'" << ", got '" << token << "'" << std::endl ;
400 if (zapOnError) zapToEnd(true) ;
401 }
402 return error ;
403}
404
405
406
407////////////////////////////////////////////////////////////////////////////////
408/// Read the next token and convert it to a double. Returns true
409/// if an error occurred in reading or conversion
410
411bool RooStreamParser::readDouble(double& value, bool /*zapOnError*/)
412{
414 if (token.IsNull()) return true ;
415 return convertToDouble(token,value) ;
416
417}
418
419////////////////////////////////////////////////////////////////////////////////
420/// Convert given string to a double. Throws exceptions if the conversion fails.
421
423{
424 value = toDouble(token.Data());
425 return false;
426}
427
428
429
430////////////////////////////////////////////////////////////////////////////////
431/// Read a token and convert it to an Int_t. Returns true
432/// if an error occurred in reading or conversion
433
434bool RooStreamParser::readInteger(Int_t& value, bool /*zapOnError*/)
435{
437 if (token.IsNull()) return true ;
439}
440
441
442
443////////////////////////////////////////////////////////////////////////////////
444/// Convert given string to an Int_t. Returns true if an error
445/// occurred in conversion
446
448{
449 char* endptr = nullptr;
450 const char* data=token.Data() ;
451 value = strtol(data,&endptr,10) ;
452 bool error = (endptr-data!=token.Length()) ;
453
454 if (error && !_prefix.IsNull()) {
455 oocoutE(nullptr,InputArguments)<< _prefix << ": parse error, cannot convert '"
456 << token << "'" << " to integer" << std::endl ;
457 }
458 return error ;
459}
460
461
462
463////////////////////////////////////////////////////////////////////////////////
464/// Read a string token. Returns true if an error occurred in reading
465/// or conversion. If a the read token is enclosed in quotation
466/// marks those are stripped in the returned value
467
468bool RooStreamParser::readString(TString& value, bool /*zapOnError*/)
469{
471 if (token.IsNull()) return true ;
472 return convertToString(token,value) ;
473}
474
475
476
477////////////////////////////////////////////////////////////////////////////////
478/// Convert given token to a string (i.e. remove eventual quotation marks)
479
481{
482 // Transport to buffer
483 char buffer[64000];
484 char *ptr;
485 strncpy(buffer, token.Data(), 63999);
486 if (token.Length() >= 63999) {
487 oocoutW(nullptr, InputArguments) << "RooStreamParser::convertToString: token length exceeds 63999, truncated"
488 << std::endl;
489 buffer[63999] = 0;
490 }
491 int len = strlen(buffer) ;
492
493 // Remove trailing quote if any
494 if ((len) && (buffer[len-1]=='"'))
495 buffer[len-1]=0 ;
496
497 // Skip leading quote, if present
498 ptr=(buffer[0]=='"') ? buffer+1 : buffer ;
499
500 string = ptr ;
501 return false ;
502}
#define c(i)
Definition RSha256.hxx:101
double toDouble(const char *s)
#define oocoutW(o, a)
#define oocoutE(o, a)
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void data
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t UChar_t len
bool convertToInteger(const TString &token, Int_t &value)
Convert given string to an Int_t.
bool readString(TString &value, bool zapOnError=false)
Read a string token.
void setPunctuation(const TString &punct)
Change list of characters interpreted as punctuation.
bool isPunctChar(char c) const
Check if given char is considered punctuation.
bool expectToken(const TString &expected, bool zapOnError=false)
Read the next token and return true if it is identical to the given 'expected' token.
bool convertToDouble(const TString &token, double &value)
Convert given string to a double. Throws exceptions if the conversion fails.
bool atEOL()
If true, parser is at end of line in stream.
std::istream * _is
TString readLine()
Read an entire line from the stream and return as TString This method recognizes the use of '\' in th...
bool readDouble(double &value, bool zapOnError=false)
Read the next token and convert it to a double.
TString readToken()
Read one token separated by any of the know punctuation characters This function recognizes and handl...
bool readInteger(Int_t &value, bool zapOnError=false)
Read a token and convert it to an Int_t.
void zapToEnd(bool inclContLines=false)
Eat all characters up to and including then end of the current line.
bool convertToString(const TString &token, TString &string)
Convert given token to a string (i.e. remove eventual quotation marks)
RooStreamParser(std::istream &is)
Construct parser on given input stream.
Basic string class.
Definition TString.h:138
Ssiz_t Length() const
Definition TString.h:427
const char * Data() const
Definition TString.h:386
Bool_t IsNull() const
Definition TString.h:424