/*****************************************************************************
* Project: RooFit *
* Package: RooFitCore *
* File: $Id: RooStreamParser.cc,v 1.32 2005/06/21 19:59:51 wverkerke Exp $
* Authors: *
* WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu *
* DK, David Kirkby, UC Irvine, dkirkby@uci.edu *
* *
* Copyright (c) 2000-2005, Regents of the University of California *
* and Stanford University. All rights reserved. *
* *
* Redistribution and use in source and binary forms, *
* with or without modification, are permitted according to the terms *
* listed in LICENSE (http://roofit.sourceforge.net/license.txt) *
*****************************************************************************/
// -- CLASS DESCRIPTION [AUX] --
// RooStreamParser is a utility class to parse istreams into tokens and optionally
// convert them into basic types (double,int,string)
//
// The general tokenizing philosophy is that there are two kinds of tokens: value
// and punctuation. The former are variable length, the latter always
// one character. A token is terminated if one of the following conditions
// occur
// - space character found (' ',tab,newline)
// - change of token type (value -> punctuation or vv)
// - end of fixed-length token (punctuation only)
// - start or end of quoted string
//
// The parser is aware of floating point notation and will assign leading
// minus signs, decimal points etc to a value token when this is obvious
// from the context. The definition of what is punctuation can be redefined.
#include "RooFit.h"
#include "Riostream.h"
#include "Riostream.h"
#include <stdlib.h>
#include <ctype.h>
#ifndef _WIN32
#include <strings.h>
#endif
#include "RooStreamParser.h"
#include "RooNumber.h"
ClassImp(RooStreamParser)
RooStreamParser::RooStreamParser(istream& is) :
_is(is), _atEOF(kFALSE), _prefix(""), _punct("()[]<>|/\\:?.,=+-&^%$#@!`~")
{
// Constructor
}
RooStreamParser::RooStreamParser(istream& is, const TString& errorPrefix) :
_is(is), _atEOF(kFALSE), _prefix(errorPrefix), _punct("()[]<>|/\\:?.,=+-&^%$#@!`~")
{
// Constructor with error message prefix
}
RooStreamParser::~RooStreamParser()
{
// Destructor
}
void RooStreamParser::setPunctuation(const TString& punct)
{
// Change list of punctuation characters
_punct = punct ;
}
Bool_t RooStreamParser::isPunctChar(char c) const
{
// Check if given char is considered punctuation
const char* punct = _punct.Data() ;
for (int i=0 ; i<_punct.Length() ; i++)
if (punct[i] == c) {
return kTRUE ;
}
return kFALSE ;
}
TString RooStreamParser::readToken()
{
// Read one token
// Smart tokenizer. Absorb white space and token must be either punctuation or alphanum
Bool_t first(kTRUE), quotedString(kFALSE), lineCont(kFALSE) ;
char buffer[10240], c, cnext, cprev=' ' ;
Int_t bufptr(0) ;
// Check for end of file
if (_is.eof() || _is.fail()) {
_atEOF = kTRUE ;
return TString("") ;
}
//Ignore leading newline
if (_is.peek()=='\n') {
_is.get(c) ;
// If new line starts with #, zap it
while (_is.peek()=='#') {
zapToEnd(kFALSE) ;
_is.get(c) ; // absorb newline
}
}
while(1) {
// Buffer overflow protection
if (bufptr>=10239) {
cout << "RooStreamParser::readToken: token length exceeds buffer capacity, terminating token early" << endl ;
break ;
}
// Read next char
_is.get(c) ;
// Terminate at EOF, EOL or trouble
if (_is.eof() || _is.fail() || c=='\n') break ;
// Terminate as SPACE, unless we haven't seen any non-SPACE yet
if (isspace(c)) {
if (first)
continue ;
else
if (!quotedString) {
break ;
}
}
// If '-' or '/' see what the next character is
if (c == '.' || c=='-' || c=='+' || c=='/' || c=='\\') {
_is.get(cnext) ;
_is.putback(cnext) ;
}
// Check for line continuation marker
if (c=='\\' && cnext=='\\') {
// Kill rest of line including endline marker
zapToEnd(kFALSE) ;
_is.get(c) ;
lineCont=kTRUE ;
break ;
}
// Stop if begin of comments is encountered
if (c=='/' && cnext=='/') {
zapToEnd(kFALSE) ;
break ;
}
// Special handling of quoted strings
if (c=='"') {
if (first) {
quotedString=kTRUE ;
} else if (!quotedString) {
// Terminate current token. Next token will be quoted string
_is.putback('"') ;
break ;
}
}
if (!quotedString) {
// Decide if next char is punctuation (exempt - and . that are part of floating point numbers, or +/- preceeding INF)
if (isPunctChar(c) && !(c=='.' && (isdigit(cnext)||isdigit(cprev)))
&& !((c=='-'||c=='+') && (isdigit(cnext)||cnext=='.'||cnext=='i'||cnext=='I'))) {
if (first) {
// Make this a one-char punctuation token
buffer[bufptr++]=c ;
break ;
} else {
// Put back punct. char and terminate current alphanum token
_is.putback(c) ;
break ;
}
}
} else {
// Inside quoted string conventional tokenizing rules do not apply
// Terminate token on closing quote
if (c=='"' && !first) {
buffer[bufptr++]=c ;
quotedString=kFALSE ;
break ;
}
}
// Store in buffer
buffer[bufptr++]=c ;
first=kFALSE ;
cprev=c ;
}
if (_is.eof() || _is.bad()) {
_atEOF = kTRUE ;
}
// Check if closing quote was encountered
if (quotedString) {
cout << "RooStreamParser::readToken: closing quote (\") missing" << endl ;
}
// Absorb trailing white space or absorb rest of line if // is encountered
if (c=='\n') {
if (!lineCont) {
_is.putback(c) ;
}
} else {
c = _is.peek() ;
while ((isspace(c) || c=='/') && c != '\n') {
if (c=='/') {
_is.get(c) ;
if (_is.peek()=='/') {
zapToEnd(kFALSE) ;
} else {
_is.putback('/') ;
}
break ;
} else {
_is.get(c) ;
c = _is.peek() ;
}
}
}
// If no token was read line is continued, return first token on next line
if (bufptr==0 && lineCont) {
return readToken() ;
}
// Zero terminate buffer and convert to TString
buffer[bufptr]=0 ;
return TString(buffer) ;
}
TString RooStreamParser::readLine()
{
// Read an entire line
char c,buffer[10240] ;
Int_t nfree(10239) ;
if (_is.peek()=='\n') _is.get(c) ;
// Read till end of line
_is.getline(buffer,nfree,'\n') ;
// Look for eventual continuation line sequence
char *pcontseq = strstr(buffer,"\\\\") ;
if (pcontseq) nfree -= (pcontseq-buffer) ;
while(pcontseq) {
_is.getline(pcontseq,nfree,'\n') ;
char* nextpcontseq = strstr(pcontseq,"\\\\") ;
if (nextpcontseq) nfree -= (nextpcontseq-pcontseq) ;
pcontseq = nextpcontseq ;
}
// Chop eventual comments
char *pcomment = strstr(buffer,"//") ;
if (pcomment) *pcomment=0 ;
// Chop leading and trailing space
char *pstart=buffer ;
while (isspace(*pstart)) {
pstart++ ;
}
char *pend=buffer+strlen(buffer)-1 ;
if (pend>pstart)
while (isspace(*pend)) { *pend--=0 ; }
if (_is.eof() || _is.fail()) {
_atEOF = kTRUE ;
}
// Convert to TString
return TString(pstart) ;
}
void RooStreamParser::zapToEnd(Bool_t inclContLines)
{
// Skip over everything until the end of the current line
if (_is.peek()!='\n') {
char buffer[10240] ;
Int_t nfree(10239) ;
// Read till end of line
_is.getline(buffer,nfree,'\n') ;
if (inclContLines) {
// Look for eventual continuation line sequence
char *pcontseq = strstr(buffer,"\\\\") ;
if (pcontseq) nfree -= (pcontseq-buffer) ;
while(pcontseq) {
_is.getline(pcontseq,nfree,'\n') ;
char* nextpcontseq = strstr(pcontseq,"\\\\") ;
if (nextpcontseq) nfree -= (nextpcontseq-pcontseq) ;
pcontseq = nextpcontseq ;
}
}
// Put back newline character in stream buffer
_is.putback('\n') ;
}
}
Bool_t RooStreamParser::expectToken(const TString& expected, Bool_t zapOnError)
{
// Read a token and check if it matches the given expected value
TString token(readToken()) ;
Bool_t error=token.CompareTo(expected) ;
if (error && !_prefix.IsNull()) {
cout << _prefix << ": parse error, expected '"
<< expected << "'" << ", got '" << token << "'" << endl ;
if (zapOnError) zapToEnd(kTRUE) ;
}
return error ;
}
Bool_t RooStreamParser::readDouble(Double_t& value, Bool_t /*zapOnError*/)
{
// Read a token and convert it to a Double_t
TString token(readToken()) ;
if (token.IsNull()) return kTRUE ;
return convertToDouble(token,value) ;
}
Bool_t RooStreamParser::convertToDouble(const TString& token, Double_t& value)
{
// Convert given string to a double
char* endptr = 0;
const char* data=token.Data() ;
// Handle +/- infinity cases, (token is guaranteed to be >1 char long)
if (!strcasecmp(data,"inf") || !strcasecmp(data+1,"inf")) {
value = (data[0]=='-') ? -RooNumber::infinity : RooNumber::infinity ;
return kFALSE ;
}
value = strtod(data,&endptr) ;
Bool_t error = (endptr-data!=token.Length()) ;
if (error && !_prefix.IsNull()) {
cout << _prefix << ": parse error, cannot convert '"
<< token << "'" << " to double precision" << endl ;
}
return error ;
}
Bool_t RooStreamParser::readInteger(Int_t& value, Bool_t /*zapOnError*/)
{
// Read a token and convert it to an Int_t
TString token(readToken()) ;
if (token.IsNull()) return kTRUE ;
return convertToInteger(token,value) ;
}
Bool_t RooStreamParser::convertToInteger(const TString& token, Int_t& value)
{
// Convert given string to an Int_t
char* endptr = 0;
const char* data=token.Data() ;
value = strtol(data,&endptr,10) ;
Bool_t error = (endptr-data!=token.Length()) ;
if (error && !_prefix.IsNull()) {
cout << _prefix << ": parse error, cannot convert '"
<< token << "'" << " to integer" << endl ;
}
return error ;
}
Bool_t RooStreamParser::readString(TString& value, Bool_t /*zapOnError*/)
{
// Read a string token
TString token(readToken()) ;
if (token.IsNull()) return kTRUE ;
return convertToString(token,value) ;
}
Bool_t RooStreamParser::convertToString(const TString& token, TString& string)
{
// Convert given token to a string (i.e. remove eventual quotation marks)
// Transport to buffer
char buffer[10240],*ptr ;
strncpy(buffer,token.Data(),10239) ;
if (token.Length()>=10239) {
cout << "RooStreamParser::convertToString: token length exceeds 1023, truncated" << endl ;
buffer[10239]=0 ;
}
int len = strlen(buffer) ;
// Remove trailing quote if any
if ((len) && (buffer[len-1]=='"'))
buffer[len-1]=0 ;
// Skip leading quote, if present
ptr=(buffer[0]=='"') ? buffer+1 : buffer ;
string = ptr ;
return kFALSE ;
}
ROOT page - Class index - Class Hierarchy - Top of the page
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.