44import java .io .Reader ;
55import java .util .Objects ;
66import java .util .Spliterators ;
7- import java .util .function .BiFunction ;
7+ import java .util .concurrent .atomic .AtomicBoolean ;
8+ import java .util .concurrent .atomic .AtomicInteger ;
89import java .util .function .Consumer ;
10+ import java .util .function .Function ;
911import java .util .stream .Stream ;
1012import java .util .stream .StreamSupport ;
1113
@@ -211,31 +213,36 @@ public Token nextToken() throws IOException {
211213 if (isEof (ch )) {
212214 return null ;
213215 }
214- int oldch = -1 ;
215- BiFunction <Integer , Integer , Boolean > isValid = (c , oldc ) -> false ;
216+ Function <Integer , Boolean > isValid = (c ) -> false ;
216217 Type nextState = null ;
217218 if (state == null ) {
218219 if (isCommentChar (ch )) {
219220 state = Type .COMMENT ;
220- isValid = (c , oldc ) -> !isEol (c ) && !isEof (c );
221- } else if (isWhitespaceChar (ch )) {
221+ isValid = (c ) -> !isEol (c ) && !isEof (c );
222+ } else if (isWhitespaceEolChar (ch )) {
222223 state = Type .WHITESPACE ;
223- isValid = (c , oldc ) -> isWhitespaceChar (c ) && !isEol (oldc );
224+ final AtomicInteger oldc = new AtomicInteger (-1 );
225+ isValid = (c ) -> isWhitespaceEolChar (c ) && !isEol (oldc .getAndSet (c ));
224226 } else {
225227 state = Type .KEY ;
226- isValid = (c , oldc ) -> !isSeparatorChar (c );
228+ isValid =
229+ (c ) ->
230+ !isSeparatorChar (c )
231+ && !isWhitespaceChar (c )
232+ && !isEol (c )
233+ && !isEof (c );
227234 nextState = Type .SEPARATOR ;
228235 }
229236 } else if (state == Type .SEPARATOR ) {
230- isValid = (c , oldc ) -> isSeparatorChar (c );
237+ final AtomicBoolean once = new AtomicBoolean (true );
238+ isValid = (c ) -> isWhitespaceChar (c ) || (isSeparatorChar (c ) && once .getAndSet (false ));
231239 nextState = Type .VALUE ;
232240 } else if (state == Type .VALUE ) {
233- isValid = (c , oldc ) -> !isEol (c ) && !isEof (c );
241+ isValid = (c ) -> !isEol (c ) && !isEof (c );
234242 }
235243 while (true ) {
236- if (isValid .apply (ch , oldch )) {
244+ if (isValid .apply (ch )) {
237245 addChar (readChar ());
238- oldch = ch ;
239246 ch = peekChar ();
240247 } else {
241248 String text = string ();
@@ -336,8 +343,7 @@ static String unescape(String escape) {
336343 case '\n' :
337344 // Skip any leading whitespace
338345 while (i < (escape .length () - 1 )
339- && isWhitespaceChar (ch = escape .charAt (i + 1 ))
340- && !isEol (ch )) {
346+ && isWhitespaceChar (ch = escape .charAt (i + 1 ))) {
341347 i ++;
342348 }
343349 break ;
@@ -353,11 +359,15 @@ && isWhitespaceChar(ch = escape.charAt(i + 1))
353359 }
354360
355361 private static boolean isSeparatorChar (int ch ) {
356- return ch == ' ' || ch == '\t' || ch == ' =' || ch == ':' ;
362+ return ch == '=' || ch == ':' ;
357363 }
358364
359365 private static boolean isWhitespaceChar (int ch ) {
360- return ch == ' ' || ch == '\t' || ch == '\f' || isEol (ch );
366+ return ch == ' ' || ch == '\t' || ch == '\f' ;
367+ }
368+
369+ private static boolean isWhitespaceEolChar (int ch ) {
370+ return isWhitespaceChar (ch ) || isEol (ch );
361371 }
362372
363373 private static boolean isCommentChar (int ch ) {
0 commit comments