Logo ROOT  
Reference Guide
 
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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
37#include "Riostream.h"
38#include <cstdlib>
39
40#ifndef _WIN32
41#include <strings.h>
42#endif
43
44#include "RooStreamParser.h"
45#include "RooMsgService.h"
46#include "RooNumber.h"
47
48
49using std::istream, std::endl;
50
51
52
53////////////////////////////////////////////////////////////////////////////////
54/// Construct parser on given input stream
55
57 _is(&is), _atEOL(false), _atEOF(false), _prefix(""), _punct("()[]<>|/\:?.,=+-&^%$#@!`~")
58{
59}
60
61
62////////////////////////////////////////////////////////////////////////////////
63/// Construct parser on given input stream. Use given errorPrefix to
64/// prefix any parsing error messages
65
67 _is(&is), _atEOL(false), _atEOF(false), _prefix(errorPrefix), _punct("()[]<>|/\:?.,=+-&^%$#@!`~")
68{
69}
70
71////////////////////////////////////////////////////////////////////////////////
72/// If true, parser is at end of line in stream
73
75{
76 Int_t nc(_is->peek()) ;
77 return (nc=='\n'||nc==-1) ;
78}
79
80
81
82////////////////////////////////////////////////////////////////////////////////
83/// Change list of characters interpreted as punctuation
84
89
90
91
92////////////////////////////////////////////////////////////////////////////////
93/// Check if given char is considered punctuation
94
96{
97 const char* punct = _punct.Data() ;
98 for (int i = 0; i < _punct.Length(); i++) {
99 if (punct[i] == c) {
100 return true;
101 }
102 }
103 return false ;
104}
105
106
107
108////////////////////////////////////////////////////////////////////////////////
109/// Read one token separated by any of the know punctuation characters
110/// This function recognizes and handles comment lines in the istream (those
111/// starting with '#', quoted strings ("") the content of which is not tokenized
112/// and '+-.' characters that are part of a floating point numbers and are exempt
113/// from being interpreted as a token separator in case '+-.' are defined as
114/// token separators.
115
117{
118 // Smart tokenizer. Absorb white space and token must be either punctuation or alphanum
119 bool first(true);
120 bool quotedString(false);
121 bool lineCont(false);
122 char buffer[64000];
123 char c(0);
124 char cnext = '\0';
125 char cprev = ' ';
126 bool haveINF(false) ;
127 Int_t bufptr(0) ;
128
129 // Check for end of file
130 if (_is->eof() || _is->fail()) {
131 _atEOF = true ;
132 return TString("") ;
133 }
134
135 //Ignore leading newline
136 if (_is->peek()=='\n') {
137 _is->get(c) ;
138
139 // If new line starts with #, zap it
140 while (_is->peek()=='#') {
141 zapToEnd(false) ;
142 _is->get(c) ; // absorb newline
143 }
144 }
145
146 while(true) {
147 // Buffer overflow protection
148 if (bufptr >= 63999) {
149 oocoutW(nullptr, InputArguments)
150 << "RooStreamParser::readToken: token length exceeds buffer capacity, terminating token early" << std::endl;
151 break;
152 }
153
154 // Read next char
155 _is->get(c) ;
156
157
158
159 // Terminate at EOF, EOL or trouble
160 if (_is->eof() || _is->fail() || c=='\n') break ;
161
162 // Terminate as SPACE, unless we haven't seen any non-SPACE yet
163 if (isspace(c)) {
164 if (first) {
165 continue;
166 } else if (!quotedString) {
167 break;
168 }
169 }
170
171 // If '-' or '/' see what the next character is
172 if (c == '.' || c=='-' || c=='+' || c=='/' || c=='\') {
173 _is->get(cnext) ;
174
175
176 if (cnext=='I' || cnext=='i') {
177 char tmp1;
178 char tmp2;
179 _is->get(tmp1);
180 _is->get(tmp2);
181 _is->putback(tmp2);
182 _is->putback(tmp1);
183 haveINF = ((cnext == 'I' && tmp1 == 'N' && tmp2 == 'F') || (cnext == 'i' && tmp1 == 'n' && tmp2 == 'f'));
184 } else {
185 haveINF = false ;
186 }
187
188 _is->putback(cnext) ;
189 }
190
191
192 // Check for line continuation marker
193 if (c=='\' && cnext=='\') {
194 // Kill rest of line including std::endline marker
195 zapToEnd(false) ;
196 _is->get(c) ;
197 lineCont=true ;
198 break ;
199 }
200
201 // Stop if begin of comments is encountered
202 if (c=='/' && cnext=='/') {
203 zapToEnd(false) ;
204 break ;
205 }
206
207 // Special handling of quoted strings
208 if (c=='"') {
209 if (first) {
211 } else if (!quotedString) {
212 // Terminate current token. Next token will be quoted string
213 _is->putback('"') ;
214 break ;
215 }
216 }
217
218 if (!quotedString) {
219 // Decide if next char is punctuation (exempt - and . that are part of floating point numbers, or +/- preceding INF)
220 if (isPunctChar(c) && !(c=='.' && (isdigit(cnext)||isdigit(cprev)))
221 && !((c=='-'||c=='+') && isdigit(cnext) && (cprev == 'e' || cprev == 'E'))
222 && (!first || !((c=='-'||c=='+') && (isdigit(cnext)||cnext=='.'||haveINF)))) {
223
224 if (first) {
225 // Make this a one-char punctuation token
226 buffer[bufptr++]=c ;
227 break ;
228 } else {
229 // Put back punct. char and terminate current alphanum token
230 _is->putback(c) ;
231 break ;
232 }
233 }
234 } else {
235 // Inside quoted string conventional tokenizing rules do not apply
236
237 // Terminate token on closing quote
238 if (c=='"' && !first) {
239 buffer[bufptr++]=c ;
241 break ;
242 }
243 }
244
245 // Store in buffer
246 buffer[bufptr++]=c ;
247 first=false ;
248 cprev=c ;
249 }
250
251 if (_is->eof() || _is->bad()) {
252 _atEOF = true ;
253 }
254
255 // Check if closing quote was encountered
256 if (quotedString) {
257 oocoutW(nullptr,InputArguments) << "RooStreamParser::readToken: closing quote (\") missing" << std::endl ;
258 }
259
260 // Absorb trailing white space or absorb rest of line if // is encountered
261 if (c=='\n') {
262 if (!lineCont) {
263 _is->putback(c) ;
264 }
265 } else {
266 c = _is->peek() ;
267
268 while ((isspace(c) || c=='/') && c != '\n') {
269 if (c=='/') {
270 _is->get(c) ;
271 if (_is->peek()=='/') {
272 zapToEnd(false) ;
273 } else {
274 _is->putback('/') ;
275 }
276 break ;
277 } else {
278 _is->get(c) ;
279 c = _is->peek() ;
280 }
281 }
282 }
283
284 // If no token was read line is continued, return first token on next line
285 if (bufptr==0 && lineCont) {
286 return readToken() ;
287 }
288
289 // Zero terminate buffer and convert to TString
290 buffer[bufptr]=0 ;
291 return TString(buffer) ;
292}
293
294
295
296////////////////////////////////////////////////////////////////////////////////
297/// Read an entire line from the stream and return as TString
298/// This method recognizes the use of '\' in the istream
299/// as line continuation token.
300
302{
303 char c;
304 char buffer[64000];
305 Int_t nfree(63999);
306
307 if (_is->peek() == '\n')
308 _is->get(c);
309
310 // Read till end of line
311 _is->getline(buffer, nfree, '\n');
312
313 // Look for eventual continuation line sequence
314 char *pcontseq = strstr(buffer, "\\");
315 if (pcontseq)
316 nfree -= (pcontseq - buffer);
317 while (pcontseq) {
318 _is->getline(pcontseq, nfree, '\n');
319
320 char *nextpcontseq = strstr(pcontseq, "\\");
321 if (nextpcontseq)
324 }
325
326 // Chop eventual comments
327 char *pcomment = strstr(buffer, "//");
328 if (pcomment)
329 *pcomment = 0;
330
331 // Chop leading and trailing space
332 char *pstart = buffer;
333 while (isspace(*pstart)) {
334 pstart++;
335 }
336 char *pend = buffer + strlen(buffer) - 1;
337 if (pend > pstart) {
338 while (isspace(*pend)) {
339 *pend-- = 0;
340 }
341 }
342
343 if (_is->eof() || _is->fail()) {
344 _atEOF = true;
345 }
346
347 // Convert to TString
348 return TString(pstart);
349}
350
351
352
353////////////////////////////////////////////////////////////////////////////////
354/// Eat all characters up to and including then end of the
355/// current line. If inclContLines is true, all continuation lines
356/// marked by the '\' token are zapped as well
357
359{
360 // Skip over everything until the end of the current line
361 if (_is->peek()!='\n') {
362
363 char buffer[64000];
364 Int_t nfree(63999);
365
366 // Read till end of line
367 _is->getline(buffer, nfree, '\n');
368
369 if (inclContLines) {
370 // Look for eventual continuation line sequence
371 char *pcontseq = strstr(buffer, "\\");
372 if (pcontseq)
373 nfree -= (pcontseq - buffer);
374 while (pcontseq) {
375 _is->getline(pcontseq, nfree, '\n');
376
377 char *nextpcontseq = strstr(pcontseq, "\\");
378 if (nextpcontseq)
381 }
382 }
383
384 // Put back newline character in stream buffer
385 _is->putback('\n') ;
386 }
387}
388
389
390
391////////////////////////////////////////////////////////////////////////////////
392/// Read the next token and return true if it is identical to the given 'expected' token.
393
395{
397
398 bool error=token.CompareTo(expected) ;
399 if (error && !_prefix.IsNull()) {
400 oocoutW(nullptr,InputArguments) << _prefix << ": parse error, expected '"
401 << expected << "'" << ", got '" << token << "'" << std::endl ;
402 if (zapOnError) zapToEnd(true) ;
403 }
404 return error ;
405}
406
407
408
409////////////////////////////////////////////////////////////////////////////////
410/// Read the next token and convert it to a double. Returns true
411/// if an error occurred in reading or conversion
412
413bool RooStreamParser::readDouble(double& value, bool /*zapOnError*/)
414{
416 if (token.IsNull()) return true ;
417 return convertToDouble(token,value) ;
418
419}
420
421
422
423////////////////////////////////////////////////////////////////////////////////
424/// Convert given string to a double. Return true if the conversion fails.
425
427{
428 char *endptr = nullptr;
429 const char *data = token.Data();
430
431 // Handle +/- infinity cases, (token is guaranteed to be >1 char long)
432 if (!strcasecmp(data, "inf") || !strcasecmp(data + 1, "inf")) {
433 value = (data[0] == '-') ? -RooNumber::infinity() : RooNumber::infinity();
434 return false;
435 }
436
437 value = strtod(data, &endptr);
438 bool error = (endptr - data != token.Length());
439
440 if (error && !_prefix.IsNull()) {
441 oocoutE(nullptr, InputArguments) << _prefix << ": parse error, cannot convert '" << token << "'"
442 << " to double precision" << std::endl;
443 }
444 return error;
445}
446
447
448
449////////////////////////////////////////////////////////////////////////////////
450/// Read a token and convert it to an Int_t. Returns true
451/// if an error occurred in reading or conversion
452
453bool RooStreamParser::readInteger(Int_t& value, bool /*zapOnError*/)
454{
456 if (token.IsNull()) return true ;
458}
459
460
461
462////////////////////////////////////////////////////////////////////////////////
463/// Convert given string to an Int_t. Returns true if an error
464/// occurred in conversion
465
467{
468 char* endptr = nullptr;
469 const char* data=token.Data() ;
470 value = strtol(data,&endptr,10) ;
471 bool error = (endptr-data!=token.Length()) ;
472
473 if (error && !_prefix.IsNull()) {
474 oocoutE(nullptr,InputArguments)<< _prefix << ": parse error, cannot convert '"
475 << token << "'" << " to integer" << std::endl ;
476 }
477 return error ;
478}
479
480
481
482////////////////////////////////////////////////////////////////////////////////
483/// Read a string token. Returns true if an error occurred in reading
484/// or conversion. If a the read token is enclosed in quotation
485/// marks those are stripped in the returned value
486
487bool RooStreamParser::readString(TString& value, bool /*zapOnError*/)
488{
490 if (token.IsNull()) return true ;
491 return convertToString(token,value) ;
492}
493
494
495
496////////////////////////////////////////////////////////////////////////////////
497/// Convert given token to a string (i.e. remove eventual quotation marks)
498
500{
501 // Transport to buffer
502 char buffer[64000];
503 char *ptr;
504 strncpy(buffer, token.Data(), 63999);
505 if (token.Length() >= 63999) {
506 oocoutW(nullptr, InputArguments) << "RooStreamParser::convertToString: token length exceeds 63999, truncated"
507 << std::endl;
508 buffer[63999] = 0;
509 }
510 int len = strlen(buffer) ;
511
512 // Remove trailing quote if any
513 if ((len) && (buffer[len-1]=='"'))
514 buffer[len-1]=0 ;
515
516 // Skip leading quote, if present
517 ptr=(buffer[0]=='"') ? buffer+1 : buffer ;
518
519 string = ptr ;
520 return false ;
521}
#define c(i)
Definition RSha256.hxx:101
#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
static constexpr double infinity()
Return internal infinity representation.
Definition RooNumber.h:25
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. Return true 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:139
Ssiz_t Length() const
Definition TString.h:417
const char * Data() const
Definition TString.h:376
Bool_t IsNull() const
Definition TString.h:414