Пример #1
0
ReaderObject
FileReader::parse(std::istream& stream)
{
  int c = stream.get();
  stream.unget();
  if (c == '{')
  {
    Json::Reader reader;
    Json::Value root;
    if (reader.parse(stream, root))
    {
      return ReaderObject(std::make_shared<JsonReaderObjectImpl>(root));
    }
    else
    {
      log_error("json parse error: %1%", reader.getFormattedErrorMessages());
      return ReaderObject();
    }
  }
  else
  {
    std::shared_ptr<lisp::Lisp> sexpr = lisp::Parser::parse(stream, "<stream>");
    if (sexpr)
    {
      return ReaderObject(std::make_shared<SExprReaderObjectImpl>(sexpr->get_list_elem(0)));
    }
    else
    {
      log_error("sexpr parse error");
      return ReaderObject();
    }
  }
}
Пример #2
0
char SplineGeometry::TestComment(std::istream& infile)
{
    bool comment = true;
    char ch = '\0';
    while (comment && !infile.eof()) {
        infile >> ch;
        if (ch == '#') {
            // skip comments
            while (ch != '\n' && !infile.eof()) {
                infile.get(ch);
            }
        } else if (ch == '\n') {
            // skip empty lines
        } else if (isblank(ch)) {
            // skip whitespaces
        } else if (ch == '-') {
            // do not unget '-'
            comment = false;
        } else {
            // end of comment
            infile.unget();
            comment = false;
        }
    }
    return ch;
}
Пример #3
0
int Midi::Event::Parse(std::istream &f, int running)
{
	delta = read_vl(f);
	int p = f.get();
	type = p >> 4;
	if(!(type & 0x8))
	{
		type = running;
		f.unget();
	}
	if(type == Midi::Event::Extra)
	{
		f.ignore(1);
		int length = f.get();
		f.ignore(length);
	}
	else
	{
		param1 = f.get();
		param2 = f.get();
	}
	if(f.eof())
		throw std::runtime_error("Cannot read event: file truncated");
	return type;
}
Пример #4
0
/**
 * Method rolls back in passed std::istream-e by passed number of read characters.
 *
 * @param stream reference to stream which will be rolled back.
 * @param size the value representing number of characters we want to roll back.
 */
void CiscoInputParser::rollbackStream(std::istream& stream, std::streamsize size)
{
    for ( streamsize i = 0; i < size; ++i )
    {
        stream.unget();
    }
}
Пример #5
0
// helper function: skip commment lines in the header of ppm image
void PPM_Image::skip_comment(std::istream &is) {
    char c; is >> c;
    while (c == '#') { // skipping comment lines
        is.ignore(256, '\n');
        is >> c;
    }
    is.unget();
}
Пример #6
0
void trim_whitespaces(std::istream& is) {
	while( is.good() ) {
		if(! std::isspace( is.get() ) ) {
			// When not space, go to previous character and break
			is.unget();
			return;
		}
	}
}std::istream& operator>>(std::istream& is, Matrix& m)
Пример #7
0
int asn_object::read(std::istream& istr){
	char c1, c2;
	if(!(istr>>c1)){
		//istr.unget();
		return -1;
	}
	if(!(istr>>c2)){
		//istr.unget();
		istr.unget();
		return -1;
	}
	if(!isxdigit(c1) || !isxdigit(c2)){
		istr.unget();
		istr.unget();
		return -1;
	}
	return hex2int(c1)*16 + hex2int(c2);
}
Пример #8
0
Token lex_name(std::istream& stream) {
    char c;
    std::string name;
    while (stream.get(c) && std::isalpha(c))
        name.push_back(c);

    if (stream)
        stream.unget();

    return {name_token, name};
}
Пример #9
0
Token lex_number(std::istream& stream) {
    char c;
    std::string number;
    while (stream.get(c) && std::isdigit(c))
        number.push_back(c);

    if (stream)
        stream.unget();

    return {number_token, number};
}
Пример #10
0
Token lex_operator(std::istream& stream) {
    char c;
    std::string op;
    while (stream.get(c) && isoperator(c))
        op.push_back(c);

    if (stream)
        stream.unget();

    return {name_token, op};
}
Пример #11
0
	int getContinuousChar(std::istream& is, char c)
	{
		int count = 1;
		char p;
		while (is >> p) {
			if (p != c) break;
			count++;
		}
		is.unget();
		return count;
	}
Пример #12
0
std::shared_ptr<Object> read_character(std::istream &in) {
  std::stringstream buf;
  int c = in.get();
  if (in.eof()) {
    throw "EOF while reading character";
  }
  buf.put(c);
  for (; ;) {
    c = in.get();
    if (in.eof() || iswhitespace(c) || isterminator(c)) {
      in.unget();
      break;
    }
    buf.put(c);    
  }
  std::string token = buf.str();
  if (token.size() == 1) {
    return std::make_shared<Character>( token[0] );
  } else if (token == "newline") {
    return std::make_shared<Character>( '\n' );
  } else if (token == "space") {
    return std::make_shared<Character>( ' ' );
  } else if (token == "tab") {
    return std::make_shared<Character>( '\t' );
  } else if (token == "backspace") {
    return std::make_shared<Character>( '\b' );
  } else if (token == "formfeed") {
    return std::make_shared<Character>( '\f' );
  } else if (token == "return") {
    return std::make_shared<Character>( '\r' );
  } else if (token[0] == 'u') {
    long uc = read_unicode_char(token, 1, 4, 16);
    if (c >= 0xD800 && c <= 0xDFFF) {
      // TODO: java clojure actually prints u + the hex value of uc
      // is this any different than token?
      throw "Invalid character constant: \\" + token;
    }
    return std::make_shared<Character>( uc );
  } else if (token[0] == 'o') {
    int len = token.size() - 1;
    if (len > 3) {
      throw "Invalid octal escape sequence length: " + std::to_string(len);
    }
    long uc = read_unicode_char(token, 1, len, 8);
    if (uc > 0377) {
      throw "Octal escape sequence mst be in range [0, 377].";
    }
    return std::make_shared<Character>( uc );
  }
  throw "Unsupported character: \\" + token;
}
Пример #13
0
  double readBranchLength(std::istream &iss)
  {
    bool foundNext = false; 
    while(not foundNext)
      {
	int ch = iss.get(); 

	foundNext = ( ch == ')'
		      || ch == ';'
		      || ch == ',' ) ; 
      }
    iss.unget();
    return nan("");
  }
Пример #14
0
static bool goto_first_not_of(std::istream& s, const std::string& str)
{
	char c;
	while (s.get(c))
	{
		if (str.find(c) == std::string::npos)
		{
			s.unget();
			return true;
		}
	}
	
	return false;
}
Пример #15
0
	void Scanner::undoScan(std::istream& stream, int character_count)
	{
		for ( int i = 0; i < character_count; i++ )
		{
			stream.unget();
			if ( stream.fail() == true )
			{
				stream.clear();
				this->end_of_file = false;
				stream.seekg(-(--character_count), std::ios::end);
				return;
			}
		}
	}
Пример #16
0
/// Determine whether the given stream is gzipped.
bool CqRibInputBuffer::isGzippedStream(std::istream& in)
{
	bool isZipped = false;
	TqOutputType c = in.get();
	// Check whether the magic number matches that for a gzip stream
	const TqOutputType gzipMagic[] = {0x1f, 0x8b};
	if(c == gzipMagic[0])
	{
		if(in.peek() == gzipMagic[1])
			isZipped = true;
	}
	in.unget();
	return isZipped;
}
Пример #17
0
void SplineGeometry::LoadData(std::istream& infile)
{
    MESHIT_LOG_INFO("Load 2D Geometry");

    Point2d x;
    char buf[50], ch;

    std::string keyword;
    std::string flag;

    int nb_domains = 0;

    TestComment(infile);
    // refinement factor
    infile >> elto0;

    while (infile.good()) {
        TestComment(infile);
        infile >> keyword;
        ch = TestComment(infile);

        if (keyword == "points") {
            std::vector<GeomPoint> points;
            std::vector<PointIndex> point_ids;
            size_t point_id;
            size_t nb_points = 0;
            while (!isalpha(static_cast<int>(ch))) {
                infile >> point_id;  // point ids are 1-based
                if (point_id > nb_points) nb_points = point_id;
                point_ids.push_back(point_id);

                infile >> x.X() >> x.Y() >> ch;

                Flags flags;
                while (ch == '-') {
                    infile >> flag;
                    flags.SetCommandLineFlag(flag);
                    ch = TestComment(infile);
                }
                infile.unget();
                ch = TestComment(infile);

                points.push_back(GeomPoint(x, flags.GetNumFlag("ref", 1.0), flags.GetNumFlag("maxh", 1e99)));
            }
            geompoints.resize(nb_points);
            for (size_t i = 0; i < nb_points; i++) {
                geompoints[point_ids[i] - 1] = points[i];
            }
        } else if (keyword == "segments") {
Пример #18
0
// Parses a string serialized by serializeJsonStringIfNeeded.
static std::string deSerializeJsonStringIfNeeded(std::istream &is)
{
	std::ostringstream tmp_os;
	bool expect_initial_quote = true;
	bool is_json = false;
	bool was_backslash = false;
	for(;;)
	{
		char c = is.get();
		if(is.eof())
			break;
		if(expect_initial_quote && c == '"')
		{
			tmp_os << c;
			is_json = true;
		}
		else if(is_json)
		{
			tmp_os << c;
			if(was_backslash)
				was_backslash = false;
			else if(c == '\\')
				was_backslash = true;
			else if(c == '"')
				break; // Found end of string
		}
		else
		{
			if(c == ' ')
			{
				// Found end of word
				is.unget();
				break;
			}
			else
			{
				tmp_os << c;
			}
		}
		expect_initial_quote = false;
	}
	if(is_json)
	{
		std::istringstream tmp_is(tmp_os.str(), std::ios::binary);
		return deSerializeJsonString(tmp_is);
	}
	else
		return tmp_os.str();
}
Пример #19
0
 static bool unquote( std::string &t, std::istream &is ) {
     struct scope {
         std::istream &is;
         unsigned counter = 0;
         scope( std::istream &_is ) : is( _is )
         {}
         ~scope() {
             while( counter-- ) {
                 is.unget();
             }
         }
         bool operator >>( char &ch ) {
             return (!is.eof()) && (++counter) && (is >> ch);
         }
     } scoped_is( is );
Пример #20
0
void IConfig::loadFromStream(std::istream& is)
{
    loadDefault();
    std::string entry_name;
    bool read = true;
    while (read) {
        while (char c = is.get()) {
            if (!is.good()) {
                read = false;
                break;
            }

            // trim spaces at the beginning
            if (c == ' ' || c == '\n' || c == '\r') {
                continue;
            }

            // skip comment line
            if (c == '#') {
                is.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
                continue;
            }

            // next config header, finish parsing
            if (c == '[') {
                read = false;
            }

            is.unget();
            break;
        }

        if (!read) {
            break;
        }

        is >> entry_name;

        if (m_strEntryMap.count(entry_name)) {
            m_strEntryMap[entry_name]->readValueFromStream(is);
        } else {
            throw ConfigError("Unrecognized config entry: " + entry_name);
        }
    }

    onLoad();
}
Пример #21
0
Chunks Parser::extract_chunks(std::istream &stream, std::set<ChunkId> const &filter)
{
    Chunks chunks;

    // Need to do this get/unget funky voodoo to detect EOF early.
    char c;
    while (stream.get(c))
    {
        stream.unget();

        auto id_chunk = read_chunk(stream);
        if (filter.empty() || filter.count(id_chunk.first) > 0)
            chunks[id_chunk.first].push_back(id_chunk.second);
    }

    return chunks;
}
Пример #22
0
std::shared_ptr<Object> read_token(std::istream &in) {
  std::stringstream buf;
  std::string ns = "";
  for (; ;) {
    int c = in.get();
    if (in.eof() || iswhitespace(c) || isterminator(c)) {
      in.unget();
      break;
    }
    buf.put(c);
    if (c == '/') {
      ns = buf.str();
    }
  }
  std::string s = buf.str();
  if (s.back() == '/') {
    // TODO: this is the only case i can spot where we have an invalid token
    throw "Invalid token: " + s;
  }
  if (s == "nil") {
    return Object::nil;
  }
  if (s == "true") {
    return Object::T;
  }
  if (s == "false") {
    return Object::F;
  }
  // TODO: / = slash, clojure.core// = slash
  if ((ns != "" && ns.substr(ns.size()-3) == ":/")
      || s.back() == ':'
      || s.find("::", 1) != std::string::npos) {
    return nullptr;
  }
  if (s[0] == ':' && s[1] == ':') {
    auto ks = Symbol::create(s.substr(2));
    // TODO: handle namespace qualified Keywords
    return nullptr;
  }
  bool iskey = s[0] == ':';
  if (iskey) {
    return Keyword::create(s.substr(1));
  }
  return std::make_shared<Symbol>(s);
}
Пример #23
0
void Graph::readAdjacencyList(std::istream& is) {
    reset();
    VertexNumber v1 = 1;
    VertexNumber v2;
    vMax = v1;

    while (is) {
        char c;
        while (isspace(c = is.get())) {
            if (c == '\n') ++v1;
        }
        if (!is) break;
        is.unget();
        is >> v2;
        if (v1 < v2) addArc(v1, v2);
    }

    setup();
}
Пример #24
0
Token extract_next_token(std::istream& stream) {
    char c;
    while (stream.get(c) && std::isspace(c));

    if (!stream)
        return {end_of_file_token, ""};

    if (c == '(')
        return {open_paren_token, "("};
    if (c == ')')
        return {close_paren_token, ")"};

    stream.unget();

    if (std::isalpha(c))
        return lex_name(stream);
    if (std::isdigit(c))
        return lex_number(stream);
    if (isoperator(c))
        return lex_operator(stream);

    throw std::runtime_error{"unrecognised character"};
}
Пример #25
0
bool EclipseGridParser::readKeyword(std::istream& is, std::string& keyword)
{
  char buf[9];
  int i, j;
  char c;
  /* Clear buf */
  for (i=0; i<9; ++i) {
    buf[i] = '\0';
  }

  /* Read first character and check if it is uppercase*/
  //buf[0] = fgetc(fp);
  is.get(buf[0]);
  if ( !isupper( buf[0] ) ) {
    is.unget();
    return false;          /* NOT VALID CHARACTER */
  }

  /* Scan as much as possible possible keyword, 8 characters long */
  i = 1;
  is.get(c);
  while ( (is.good()) &&
          (c != EOF     ) &&
          (!isblank(c)   ) &&
          (isupper(c) || isdigit(c)) &&
          (c != '\n'    ) &&
          (c != '/'     ) &&
          (i < 8        )) {
    buf[i++] = c;
    is.get(c);
  }

  /* Skip rest of line */
  if (c != '\n'){
    is.get(c);
    while ( (is.good()) &&
            (c != EOF     ) &&
            (c != '\n'    )) {
      is.get(c);
    }
  }
  if(c == '\n') {
    is.unget();
  }

  /* Find first non-uppercase or non-digit character */
  for (i=0; i<8; ++i) {
    if ( !(isupper(buf[i]) || isdigit(buf[i])) ) {
      break;
    }
  }

  /* Check if remaining characters are blank */
  for (j = i; j<8; ++j) {
    if(!isspace(buf[j]) && buf[j] != '\0') {
      return false; /* CHARACTER AFTER SPACE OR INVALID CHARACTER */
    }
    buf[j] = '\0';
  }
  keyword = std::string(buf);
  std::string::size_type end = keyword.find_last_of('\0');
  if(end != keyword.npos)
    keyword = keyword.substr(0, end+1);
  return true;
}
Пример #26
0
bool ossimXmlNode::readTextContent(std::istream& in)
{
    if(traceDebug())
    {
        ossimNotify(ossimNotifyLevel_DEBUG)
                << "ossimXmlNode::readTextContent: entered ..." << std::endl;
    }

    //---
    // Parse the text string.  Do it with no peeks, ignores, or putbacks as
    // those seem to have issues on Windows (vs9).
    //---
    bool result = false;

    theText = "";
    theCDataFlag = false;

    xmlskipws(in);

    if ( !in.fail() )
    {
        std::streampos initialPos = in.tellg();

        char c = in.get();

        if ( c != '<' )
        {
            do // Get the text up to the next '<'.
            {
                theText += c;
                c = in.get();
            } while ( (c != '<') && !in.fail() );

            in.unget(); // Put '<' back.
            result = !in.fail();
        }
        else // At "<" see if comment
        {
            c = in.get();

            if ( c != '!' )
            {
                in.seekg(initialPos);
                result = !in.fail();
            }
            else // at "<!"
            {
                c = in.get();
                if ( c == '-' )
                {
                    // Comment section: <!-- some comment -->
                    c = in.get();
                    if ( c == '-' ) // at "<!--"
                    {
                        // Strip comment
                        while( !in.fail() ) // continue until we see a --> pattern
                        {
                            c = in.get();
                            if(c == '-')
                            {
                                c = in.get();
                                if(c == '-')
                                {
                                    c = in.get();
                                    if(c == '>')
                                    {
                                        result = !in.fail();
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
                else if ( c == '[' ) // at "<!["
                {
                    // CDATA section: <![CDATA[something-here]]>
                    c = in.get();
                    if ( c == 'C') // at "<![C:"
                    {
                        c = in.get();
                        if ( c == 'D' )// at "<![CD"
                        {
                            c = in.get();
                            if ( c == 'A' ) // at "<![CDA"
                            {
                                c = in.get();
                                if ( c == 'T' ) // at "<![CDAT"
                                {
                                    c = in.get();
                                    if ( c == 'A' ) // at "<![CDATA"
                                    {
                                        c = in.get();
                                        if ( c == '[' ) // at "<!CDATA["
                                        {
                                            if (readCDataContent(in))
                                            {
                                                theCDataFlag = true;
                                                result = true;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    if(traceDebug())
    {
        ossimNotify(ossimNotifyLevel_DEBUG)
                << "theText: " << theText
                << "\ntheCDataFlag: " << (theCDataFlag?"true":"false")
                << "\nexit status: " << (result?"true":"false")
                << "\nossimXmlNode::readTextContent: leaving ..." << std::endl;
    }

    return result;
}
Пример #27
0
VLA<uint8_t> Extractor::parse(std::istream &input)
{
    /* start code prefix 24/32 bits (reverse order) */
    static const uint8_t scp24[] = {1, 0, 0};
    static const uint8_t scp32[] = {1, 0, 0, 0};

    std::istream_iterator<uint8_t> begin(input), end;
    VLA<uint8_t> output;

    output.reserve(4 * 1024);

    /* search for byte stream NAL Unit start code prefix */
    while(
            !isMatchingAt(output.rbegin(), output.rend(), scp24)
            && !isMatchingAt(output.rbegin(), output.rend(), scp32))
    {
        /* expected syntax element: leading_zero_8bits */
        output.pushBack(*begin);

        if(0 != output.back() && 1 != output.back())
        {
            /* undo unexpected only */
            input.unget();
            runtime_assert(false);
        }
        ++begin;
    }

    /* until next NAL Unit start code prefix is encountered (or end of file),
     * treat all bytes as NAL Unit payload */

    while(begin != end)
    {
        /* NAL Unit payload including syntax element: trailing_zero_8bits */
        output.pushBack(*begin);

        const auto scp24Matched =
            isMatchingAt(output.rbegin(), output.rend(), scp24);
        /* do not search for scp32 if scp24 present */
        const auto scp32Matched =
            scp24Matched
            ? false
            : isMatchingAt(output.rbegin(), output.rend(), scp32);

        if(scp24Matched || scp32Matched)
        {
            const auto scpSize = scp24Matched ? sizeof(scp24) : sizeof(scp32);

            /* revert consumed start code prefix */
            const std::streampos absPos = input.tellg();
            const std::streamoff offset = absPos - static_cast<std::streampos>(scpSize);

            runtime_assert(absPos > static_cast<std::streampos>(sizeof(scpSize)));
            input.seekg(offset, std::ios_base::beg);
            /* truncate next NAL Unit scp from current tail */
            output.resize(output.size() - scpSize);
            break;
        }
        ++begin;
    }

    return output;
}
Пример #28
0
int asn_sequence::readAll(std::istream& istr){
	if(!checkTag(istr))
		return -1;
	if(!readSize(istr))
		return -1;
	int readOctets = 2;
	int charleft = size;
	if(elements.empty()){
		while (charleft > 0){
			int tmptag = read(istr), x;
			if (tmptag < 0) {
				istr.clear();
				istr.seekg(0);
				writeable = 0;
				return -1;
			}
			istr.unget();
			istr.unget();
			if(tmptag==2){
				asn_int *tmpi = new asn_int;
				x = tmpi->readAll(istr);
				if(x <0) return -1;
				charleft = charleft-x;
				readOctets += x;
				addElement(tmpi);
			}
			else if(tmptag==19){
				asn_string *tmps = new asn_string;
				x = tmps->readAll(istr);
				if(x <0) return -1;
				charleft = charleft-x;
				readOctets += x;
				addElement(tmps);
			}
			else if(tmptag==48){
				asn_sequence *tmpss = new asn_sequence;
				x = tmpss->readAll(istr);
				if(x <0) return -1;
				charleft =charleft-x;
				readOctets += x;
				addElement(tmpss);
			}
			else{
				istr.clear();
				istr.seekg(0);
				writeable = 0;
				return -1;
			}
		}
		writeable = 1;
		return readOctets;
	}
	else{
		for (std::vector<asn_object*>::iterator it = elements.begin() ; it != elements.end(); ++it){
			int x = (*it)->readAll(istr);
			if (x<0){
				istr.clear();
				istr.seekg(0);
				/*
				for(int i = 0; i<readOctets; i++){
					istr.unget();
					istr.unget();
				}*/
				return -1;
			}
			readOctets += x;
		}
		writeable = 1;
		return readOctets;
	}
}
Пример #29
0
std::shared_ptr<Object> read_number(std::istream &in) {
  std::stringstream buf;
  std::string start = "";
  bool error = false;
  number_type type = number_type::none;
  int base = 10;

  // lambda to tell if we've reached the end of the number
  std::function<bool (int)> isend = [&in] (int i) -> bool { 
    return iswhitespace(i) || isterminator(i) || in.eof(); 
  };

  int c;
  // process the first few chars
  while (!isend(c = in.get())) {
    if (c == '0') { // if the first character is 0, there's only a few posible options
      c = in.get();
      if (isend(c)) { // check if it's 0
        type = number_type::integer;
        buf.put('0');
        break;
      } else if (c == 'x' || c == 'X') { // check if it's a hex value
        type = number_type::integer;
        base = 16;
        start += "0";
        start += (char)c;
        break;
      } else if (c >= '0' && c <= '7') { // check if it's an oct value
        type = number_type::integer;
        buf.put(c);
        base = 8;
        start = "0";
        break;
      } else if (c == 'e' || c == 'E') {
        type = number_type::scientific;
        buf.put('0');
        buf.put(c);
        break;
      } else {
        error = true;
        buf << "O" << (char)c;
        break;
      }
    } else if (c == '-') { // add the sign to the buf if a -
      buf.put(c);
    } else if (c == '+') {
      // ignore the sign if it's a +
    } else {
      buf.put(c);
      break;
    }
  }
  while (1) {
    c = in.get();
    if (isend(c)) {
      // TODO: process buf and get the value
      in.unget(); // TODO: make sure we want to unget here
      if (error) {
        buf.str("Invalid Number: " + start + buf.str());
        throw buf.str();
      } else {
        if (type == number_type::integer || type == number_type::none) {
          return std::make_shared<Integer>(buf.str(), base);
        } else if (type == number_type::irrational || type == number_type::scientific) {
          return std::make_shared<Irrational>(buf.str());
        } else if (type == number_type::ratio) {
          std::string r = buf.str();
          size_t s = r.find('/');
          return std::make_shared<Ratio>(r.substr(0, s), r.substr(s+1));
        }
      }
      return Object::nil; // should never get here
    }
    if (error) {
      buf.put(c);
    } else if (c == 'r') {
      if (type != number_type::none) { // we already have a base, so this is an invalid number
        error = true;
        buf.put(c);
      } else {
        std::string radix = buf.str();
        buf.str("");
        if (radix.size() > 2) {
          error = true;
          buf.put(c);
        } else {
          base = stoi(radix);
          if (base > 36) {
            // TODO: NumberFormatException
            throw "Radix out of range";
          }
          type = number_type::integer;
        }
      }
    } else if (c == '/') {
      buf.put(c);
      if (type != number_type::none) { // we already have a base, so this is an invalid number
        error = true;
      } else {
        type = number_type::ratio;
        c = in.get();
        if (isend(c)) {
          error = true;
          in.unget();
        } else {
          buf.put(c);
        }
      }
    } else if (c == '.' && type == number_type::none) {
      type = number_type::irrational;
      buf.put(c);
    } else if ((c == 'e' || c == 'E') && 
               (type == number_type::none || type == number_type::irrational)) {
      type = number_type::scientific;
      buf.put(c);
      c = in.get();
      if (isend(c)) {
        error = true;
      } else {
        buf.put(c);
        if (!(c == '-' || c == '+' || (c >= '0' && c <= '9'))) {
          error = true;
        }
      }
    } else if ((c == 'N' || c == 'M') && base == 10) { // M and N endings only possible with base 10
      c = in.get();
      if (!isend(c)) {
        error = true;
        buf.put(c);
      } else {
        in.unget();
      }
    } else if (c >= '0' && ((base < 11 && (c < '0' + base)) || 
                            (base > 10 && (c <= '9' || 
                                           (c >= 'a' && c < 'a' + (base-10)) ||
                                           (c >= 'A' && c < 'A' + (base-10))
                                           )))) {
      buf.put(c);
    } else {
      buf.put(c);
      error = true;
    }
  }
  return Object::nil;
}
Пример #30
0
std::shared_ptr<Object> read_string(std::istream &in) {
  std::stringstream buf;
  // lambda to get the next char, or throw EOF exception
  std::function<int ()> getc = [&in] () -> int { 
    int c = in.get();
    if (in.eof()) {
      throw "EOF while reading string";
    }
    return c;
  };
  while (1) {
    int c = getc();
    if (c == '"') {
      return std::make_shared<String>(buf.str());
    }
    if (c == '\\') {
      c = getc();
      if (octal_digit(c)) {
        int j = 0;
        char eseq[4] = { 0, 0, 0, 0 } ;
        do {
          eseq[j++] = c;
          c = getc();
        } while (octal_digit(c) && j < 3);
        in.unget();
        if (!octal_digit(c) && j < 3) {
          if (c == '\\') {
          } else {
            buf.str("Invalid digit: ");
            buf.put(c);
            throw buf.str();
          }
        }
        u8_wc_toutf8(buf, std::strtol(eseq, 0, 8));
      } else if (c == 'u') {
        int j = 0;
        char eseq[5] = { 0, 0, 0, 0, 0 };
        c = getc();
        while (hex_digit(c) && j < 4) {
          eseq[j++] = c;
          c = getc();
        }
        if (j != 4) {
          buf.str("Invalid character length: ");
          buf << j << ", should be: 4";
          throw buf.str();
        }
        in.unget();
        long uni = std::strtol(eseq, 0, 16);
        u8_wc_toutf8(buf, uni);
      } else {
        if (c == 'b') {
          buf.put('\b');
        } else if (c == 'n') {
          buf.put('\n');
        } else if (c == 't') {
          buf.put('\t');
        } else if (c == 'f') {
          buf.put('\f');
        } else if (c == 'r') {
          buf.put('\r');
        } else if (c == '"') {
          buf.put('\'');
        } else if (c == '\\') {
          buf.put('\\');
        } else {
          buf.str("Unsupported escape character: \\");
          buf.put(c);
          throw buf.str();
        }
      }
    } else {
      buf.put(c);
    }
  }
  return Object::nil;
}