Path: blob/master/thirdparty/embree/common/lexers/stream.h
9913 views
// Copyright 2009-2021 Intel Corporation1// SPDX-License-Identifier: Apache-2.023#pragma once45#include "../sys/platform.h"6#include "../sys/ref.h"7#include "../sys/filename.h"8#include "../sys/estring.h"910#include <vector>11#include <iostream>12#include <cstdio>13#include <string.h>1415namespace embree16{17/*! stores the location of a stream element in the source */18class ParseLocation19{20public:21ParseLocation () : lineNumber(-1), colNumber(-1) {}22ParseLocation (std::shared_ptr<std::string> fileName, ssize_t lineNumber, ssize_t colNumber, ssize_t /*charNumber*/)23: fileName(fileName), lineNumber(lineNumber), colNumber(colNumber) {}2425std::string str() const26{27std::string str = "unknown";28if (fileName) str = *fileName;29if (lineNumber >= 0) str += " line " + toString(lineNumber);30if (lineNumber >= 0 && colNumber >= 0) str += " character " + toString(colNumber);31return str;32}3334private:35std::shared_ptr<std::string> fileName; /// name of the file (or stream) the token is from36ssize_t lineNumber; /// the line number the token is from37ssize_t colNumber; /// the character number in the current line38};3940/*! a stream class templated over the stream elements */41template<typename T> class Stream : public RefCount42{43enum { BUF_SIZE = 1024 };4445private:46virtual T next() = 0;47virtual ParseLocation location() = 0;48__forceinline std::pair<T,ParseLocation> nextHelper() {49ParseLocation l = location();50T v = next();51return std::pair<T,ParseLocation>(v,l);52}53__forceinline void push_back(const std::pair<T,ParseLocation>& v) {54if (past+future == BUF_SIZE) pop_front();55size_t end = (start+past+future++)%BUF_SIZE;56buffer[end] = v;57}58__forceinline void pop_front() {59if (past == 0) THROW_RUNTIME_ERROR("stream buffer empty");60start = (start+1)%BUF_SIZE; past--;61}62public:63Stream () : start(0), past(0), future(0), buffer(BUF_SIZE) {}64virtual ~Stream() {}6566public:6768const ParseLocation& loc() {69if (future == 0) push_back(nextHelper());70return buffer[(start+past)%BUF_SIZE].second;71}72T get() {73if (future == 0) push_back(nextHelper());74T t = buffer[(start+past)%BUF_SIZE].first;75past++; future--;76return t;77}78const T& peek() {79if (future == 0) push_back(nextHelper());80return buffer[(start+past)%BUF_SIZE].first;81}82const T& unget(size_t n = 1) {83if (past < n) THROW_RUNTIME_ERROR ("cannot unget that many items");84past -= n; future += n;85return peek();86}87void drop() {88if (future == 0) push_back(nextHelper());89past++; future--;90}91private:92size_t start,past,future;93std::vector<std::pair<T,ParseLocation> > buffer;94};9596/*! warps an iostream stream */97class StdStream : public Stream<int>98{99public:100StdStream (std::istream& cin, const std::string& name = "std::stream")101: cin(cin), lineNumber(1), colNumber(0), charNumber(0), name(std::shared_ptr<std::string>(new std::string(name))) {}102~StdStream() {}103ParseLocation location() {104return ParseLocation(name,lineNumber,colNumber,charNumber);105}106int next() {107int c = cin.get();108if (c == '\n') { lineNumber++; colNumber = 0; } else if (c != '\r') colNumber++;109charNumber++;110return c;111}112private:113std::istream& cin;114ssize_t lineNumber; /// the line number the token is from115ssize_t colNumber; /// the character number in the current line116ssize_t charNumber; /// the character in the file117std::shared_ptr<std::string> name; /// name of buffer118};119120/*! creates a stream from a file */121class FileStream : public Stream<int>122{123public:124FileStream (const FileName& fileName)125: lineNumber(1), colNumber(0), charNumber(0), name(std::shared_ptr<std::string>(new std::string(fileName.str())))126{127if (ifs) ifs.close();128ifs.open(fileName.str());129if (!ifs.is_open()) THROW_RUNTIME_ERROR("cannot open file " + fileName.str());130}131~FileStream() {132if (ifs) ifs.close();133}134135public:136ParseLocation location() {137return ParseLocation(name,lineNumber,colNumber,charNumber);138}139140int next() {141int c = ifs.get();142if (c == '\n') { lineNumber++; colNumber = 0; } else if (c != '\r') colNumber++;143charNumber++;144return c;145}146147148private:149std::ifstream ifs;150ssize_t lineNumber; /// the line number the token is from151ssize_t colNumber; /// the character number in the current line152ssize_t charNumber; /// the character in the file153std::shared_ptr<std::string> name; /// name of buffer154};155156/*! creates a stream from a string */157class StrStream : public Stream<int>158{159public:160161StrStream (const char* str)162: str(str), lineNumber(1), colNumber(0), charNumber(0) {}163164public:165ParseLocation location() {166return ParseLocation(std::shared_ptr<std::string>(),lineNumber,colNumber,charNumber);167}168169int next() {170int c = str[charNumber];171if (c == 0) return EOF;172if (c == '\n') { lineNumber++; colNumber = 0; } else if (c != '\r') colNumber++;173charNumber++;174return c;175}176177private:178const char* str;179ssize_t lineNumber; /// the line number the token is from180ssize_t colNumber; /// the character number in the current line181ssize_t charNumber; /// the character in the file182};183184/*! creates a character stream from a command line */185class CommandLineStream : public Stream<int>186{187public:188CommandLineStream (int argc, char** argv, const std::string& name = "command line")189: i(0), j(0), charNumber(0), name(std::shared_ptr<std::string>(new std::string(name)))190{191if (argc > 0) {192for (size_t i=0; argv[0][i] && i<1024; i++) charNumber++;193charNumber++;194}195for (ssize_t k=1; k<argc; k++) args.push_back(argv[k]);196}197~CommandLineStream() {}198public:199ParseLocation location() {200return ParseLocation(name,0,charNumber,charNumber);201}202int next() {203if (i == args.size()) return EOF;204if (j == args[i].size()) { i++; j=0; charNumber++; return ' '; }205charNumber++;206return args[i][j++];207}208private:209size_t i,j;210std::vector<std::string> args;211ssize_t charNumber; /// the character in the file212std::shared_ptr<std::string> name; /// name of buffer213};214}215216217