2013-05-20 19:34:15 -04:00
# include "StringReader.h"
2013-10-25 02:04:22 -07:00
# include <cassert>
2013-05-20 19:34:15 -04:00
StringReader : : StringReader ( )
{
str_pos = 0 ;
}
StringReader : : StringReader ( std : : string inputString )
{
str_pos = 0 ;
setString ( inputString ) ;
}
StringReader : : ~ StringReader ( )
{
//dtor
}
void StringReader : : setString ( std : : string inputString )
{
rd_string = inputString ;
end_reached = false ;
}
std : : string StringReader : : word ( bool truncateEnd )
{
2013-10-25 02:26:31 -07:00
std : : string result = getTokens ( " \n \t " , truncateEnd ) ;
2013-05-20 19:34:15 -04:00
while ( result = = " " | | result = = " \n " | | result = = " \t " )
{
2013-10-25 02:26:31 -07:00
result = getTokens ( " \n \t " , truncateEnd ) ;
2013-05-20 19:34:15 -04:00
}
return ( result ) ;
}
std : : string StringReader : : line ( bool truncateEnd )
{
2013-10-25 02:26:31 -07:00
return getTokens ( " \n " , truncateEnd ) ;
2013-05-20 19:34:15 -04:00
}
2013-10-25 02:26:31 -07:00
std : : string StringReader : : getTokens ( const char * stop_chars , bool truncateEnd )
2013-05-20 19:34:15 -04:00
{
2015-03-23 14:35:28 -04:00
if ( str_pos > = rd_string . size ( ) )
return " " ;
2013-10-25 02:26:31 -07:00
size_t found_pos = rd_string . find_first_of ( stop_chars , str_pos ) ;
2013-05-20 19:34:15 -04:00
2013-07-02 13:14:40 -04:00
if ( rd_string [ str_pos ] = = ' \" ' ) {
2013-10-25 02:32:39 -07:00
//Find the next quote
found_pos = rd_string . find ( " \" " , str_pos + 1 ) ;
//Check to see if the quote is escaped
2013-07-10 23:50:53 -04:00
int numBackslashes = 0 ;
int countBack = 1 ;
2013-10-25 02:32:39 -07:00
while ( found_pos > = countBack & & rd_string [ found_pos - countBack ] = = ' \\ ' ) {
2013-07-10 23:50:53 -04:00
numBackslashes + + ;
countBack + + ;
}
2013-10-25 02:32:39 -07:00
//While the quote is escaped
while ( numBackslashes % 2 = = 1 ) {
//find the next quote
found_pos = rd_string . find ( " \" " , found_pos + 1 ) ;
//Check to see if it's escaped
2013-07-10 23:50:53 -04:00
numBackslashes = 0 ;
countBack = 1 ;
2013-10-25 02:26:31 -07:00
while ( found_pos > = countBack & & rd_string [ found_pos - countBack ] = = ' \\ ' ) {
2013-07-10 23:50:53 -04:00
numBackslashes + + ;
countBack + + ;
}
}
2013-07-02 13:14:40 -04:00
}
2013-05-20 19:34:15 -04:00
if ( found_pos = = str_pos ) //We are at the endline
{
2013-10-25 02:26:31 -07:00
std : : string stop_char ( 1 , rd_string [ str_pos ] ) ;
2013-05-20 19:34:15 -04:00
str_pos + + ;
return stop_char ;
} else if ( found_pos = = std : : string : : npos ) //We are at the end of the file
{
//End of String
end_reached = true ;
2014-01-01 17:29:19 -06:00
//std::cout << "Reached end of file!\n";
2013-05-20 19:34:15 -04:00
return " " ;
} else {
if ( truncateEnd ) //If we want to get rid of the delimiting character, which is the default, don't add the last char. Note we have to increase str_pos by one manually later
found_pos - = 1 ;
2013-07-02 13:14:40 -04:00
if ( rd_string [ str_pos ] = = ' \" ' )
found_pos + + ;
2013-10-25 02:42:12 -07:00
std : : string string_section = rd_string . substr ( str_pos , found_pos - str_pos + 1 ) ;
str_pos = found_pos + 1 ;
2013-07-02 13:14:40 -04:00
2013-05-20 19:34:15 -04:00
if ( truncateEnd ) //Ok, we didn't add the last char, but str_pos now points at that char. So we move it one ahead.
str_pos + + ;
return string_section ;
}
}
2013-10-25 02:04:22 -07:00
void StringReader : : test ( )
{
{
StringReader reader ( " \" x \" " ) ;
assert ( reader . word ( ) = = " \" x \" " ) ;
assert ( reader . word ( ) = = " " ) ;
}
{
StringReader reader ( " \" y \" ; \n " ) ;
assert ( reader . word ( ) = = " \" y \" " ) ;
assert ( reader . word ( ) = = " ; " ) ;
assert ( reader . word ( ) = = " " ) ;
}
{
StringReader reader ( " Goal = greeting ; \n "
" greeting = \" hello \" | greeting \" world \" ; \n " ) ;
assert ( reader . word ( ) = = " Goal " ) ;
assert ( reader . word ( ) = = " = " ) ;
assert ( reader . word ( ) = = " greeting " ) ;
assert ( reader . word ( ) = = " ; " ) ;
assert ( reader . word ( ) = = " greeting " ) ;
assert ( reader . word ( ) = = " = " ) ;
assert ( reader . word ( ) = = " \" hello \" " ) ;
assert ( reader . word ( ) = = " | " ) ;
assert ( reader . word ( ) = = " greeting " ) ;
assert ( reader . word ( ) = = " \" world \" " ) ;
assert ( reader . word ( ) = = " ; " ) ;
assert ( reader . word ( ) = = " " ) ;
}
{
StringReader reader ( " one # pretend this is a comment \n "
" two \n " ) ;
assert ( reader . word ( ) = = " one " ) ;
assert ( reader . word ( ) = = " # " ) ;
assert ( reader . line ( ) = = " pretend this is a comment " ) ;
assert ( reader . word ( ) = = " two " ) ;
assert ( reader . word ( ) = = " " ) ;
}
2013-10-25 02:17:02 -07:00
{
// Quoted strings can span lines.
StringReader reader ( " x = \" \n \" ; \n " ) ;
assert ( reader . word ( ) = = " x " ) ;
assert ( reader . word ( ) = = " = " ) ;
assert ( reader . word ( ) = = " \" \n \" " ) ;
assert ( reader . word ( ) = = " ; " ) ;
assert ( reader . word ( ) = = " " ) ;
}
{
// Strings may contain backslash-escaped quote characters.
StringReader reader ( " \" abc \\ \" def \\ \\ \\ \\ \\ \" \" \n " ) ;
assert ( reader . word ( ) = = " \" abc \\ \" def \\ \\ \\ \\ \\ \" \" " ) ;
assert ( reader . word ( ) = = " " ) ;
}
{
// A backslash-escaped backslash can be the last character in a string.
StringReader reader ( " \" \\ \\ \" \n " ) ;
assert ( reader . word ( ) = = " \" \\ \\ \" " ) ;
assert ( reader . word ( ) = = " " ) ;
}
2013-10-25 02:04:22 -07:00
std : : cout < < " StringReader tests pass \n " ;
}