src/postgres/src/backend/utils/adt/jsonapi.c
/*
 * Lex one token from the input stream.
 */
Lex one token from the input stream.
Lex one token from the input stream .
void
json_lex(JsonLexContext *lex)
{
	char	   *s;
	int			len;
	s = lex->token_terminator;
	len = s - lex->input;
	while (len < lex->input_length &&
		   (*s == ' ' || *s == '\t' || *s == '\n' || *s == '\r'))
	{
		if (*s == '\n')
			++lex->line_number;
		++s;
		++len;
	}
	lex->token_start = s;
	if (len >= lex->input_length)
	{
		lex->token_start = NULL;
		lex->prev_token_terminator = lex->token_terminator;
		lex->token_terminator = s;
		lex->token_type = JSON_TOKEN_END;
	}
	else
		switch (*s)
		{
			case '{':
				lex->prev_token_terminator = lex->token_terminator;
				lex->token_terminator = s + 1;
				lex->token_type = JSON_TOKEN_OBJECT_START;
				break;
			case '}':
				lex->prev_token_terminator = lex->token_terminator;
				lex->token_terminator = s + 1;
				lex->token_type = JSON_TOKEN_OBJECT_END;
				break;
			case '[':
				lex->prev_token_terminator = lex->token_terminator;
				lex->token_terminator = s + 1;
				lex->token_type = JSON_TOKEN_ARRAY_START;
				break;
			case ']':
				lex->prev_token_terminator = lex->token_terminator;
				lex->token_terminator = s + 1;
				lex->token_type = JSON_TOKEN_ARRAY_END;
				break;
			case ',':
				lex->prev_token_terminator = lex->token_terminator;
				lex->token_terminator = s + 1;
				lex->token_type = JSON_TOKEN_COMMA;
				break;
			case ':':
				lex->prev_token_terminator = lex->token_terminator;
				lex->token_terminator = s + 1;
				lex->token_type = JSON_TOKEN_COLON;
				break;
			case '"':
				json_lex_string(lex);
				lex->token_type = JSON_TOKEN_STRING;
				break;
			case '-':
				json_lex_number(lex, s + 1, NULL, NULL);
				lex->token_type = JSON_TOKEN_NUMBER;
				break;
			case '0':
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
			case '8':
			case '9':
				json_lex_number(lex, s, NULL, NULL);
				lex->token_type = JSON_TOKEN_NUMBER;
				break;
			default:
				{
					char	   *p;
					for (p = s; p - s < lex->input_length - len && JSON_ALPHANUMERIC_CHAR(*p); p++)
						  ;
					if (p == s)
					{
						lex->prev_token_terminator = lex->token_terminator;
						lex->token_terminator = s + 1;
						report_invalid_token(lex);
					}
					lex->prev_token_terminator = lex->token_terminator;
					lex->token_terminator = p;
					if (p - s == 4)
					{
						if (memcmp(s, "true", 4) == 0)
							lex->token_type = JSON_TOKEN_TRUE;
						else if (memcmp(s, "null", 4) == 0)
							lex->token_type = JSON_TOKEN_NULL;
						else
							report_invalid_token(lex);
					}
					else if (p - s == 5 && memcmp(s, "false", 5) == 0)
						lex->token_type = JSON_TOKEN_FALSE;
					else
						report_invalid_token(lex);
				}
		}						
}
void json_lex ( JsonLexContext * lex ) { char * s ; int len ; s = lex -> token_terminator ; len = s - lex -> input ; while ( len < lex -> input_length && ( * s == ' ' || * s == ' \t ' || * s == ' \n ' || * s == ' \r ' ) ) { if ( * s == ' \n ' ) ++ lex -> line_number ; ++ s ; ++ len ; } lex -> token_start = s ; if ( len >= lex -> input_length ) { lex -> token_start = NULL ; lex -> prev_token_terminator = lex -> token_terminator ; lex -> token_terminator = s ; lex -> token_type = JSON_TOKEN_END ; } else switch ( * s ) { case ' ' : lex -> prev_token_terminator = lex -> token_terminator ; lex -> token_terminator = s + 1 ; lex -> token_type = JSON_TOKEN_OBJECT_START ; break ; case ' ' : lex -> prev_token_terminator = lex -> token_terminator ; lex -> token_terminator = s + 1 ; lex -> token_type = JSON_TOKEN_OBJECT_END ; break ; case ' ' : lex -> prev_token_terminator = lex -> token_terminator ; lex -> token_terminator = s + 1 ; lex -> token_type = JSON_TOKEN_ARRAY_START ; break ; case ' ' : lex -> prev_token_terminator = lex -> token_terminator ; lex -> token_terminator = s + 1 ; lex -> token_type = JSON_TOKEN_ARRAY_END ; break ; case ' ' : lex -> prev_token_terminator = lex -> token_terminator ; lex -> token_terminator = s + 1 ; lex -> token_type = JSON_TOKEN_COMMA ; break ; case ' ' : lex -> prev_token_terminator = lex -> token_terminator ; lex -> token_terminator = s + 1 ; lex -> token_type = JSON_TOKEN_COLON ; break ; case ' ' : json_lex_string ( lex ) ; lex -> token_type = JSON_TOKEN_STRING ; break ; case ' ' : json_lex_number ( lex , s + 1 , NULL , NULL ) ; lex -> token_type = JSON_TOKEN_NUMBER ; break ; case ' ' : case ' ' : case ' ' : case ' ' : case ' ' : case ' ' : case ' ' : case ' ' : case ' ' : case ' ' : json_lex_number ( lex , s , NULL , NULL ) ; lex -> token_type = JSON_TOKEN_NUMBER ; break ; default : { char * p ; for ( p = s ; p - s < lex -> input_length - len && JSON_ALPHANUMERIC_CHAR ( * p ) ; p ++ ) ; if ( p == s ) { lex -> prev_token_terminator = lex -> token_terminator ; lex -> token_terminator = s + 1 ; report_invalid_token ( lex ) ; } lex -> prev_token_terminator = lex -> token_terminator ; lex -> token_terminator = p ; if ( p - s == 4 ) { if ( memcmp ( s , " " , 4 ) == 0 ) lex -> token_type = JSON_TOKEN_TRUE ; else if ( memcmp ( s , " " , 4 ) == 0 ) lex -> token_type = JSON_TOKEN_NULL ; else report_invalid_token ( lex ) ; } else if ( p - s == 5 && memcmp ( s , " " , 5 ) == 0 ) lex -> token_type = JSON_TOKEN_FALSE ; else report_invalid_token ( lex ) ; } } }
Lex one token from the input stream.
Lex one token from the input stream .
/* Skip leading whitespace. */ /* Determine token type. */ /* Single-character token, some kind of punctuation mark. */ /* string */ /* Negative number. */ /* Positive number. */ /*
					 * We're not dealing with a string, number, legal
					 * punctuation mark, or end of string.  The only legal
					 * tokens we might find here are true, false, and null,
					 * but for error reporting purposes we scan until we see a
					 * non-alphanumeric character.  That way, we can report
					 * the whole word as an unexpected token, rather than just
					 * some unintuitive prefix thereof.
					 */ /* skip */ /*
					 * We got some sort of unexpected punctuation or an
					 * otherwise unexpected character, so just complain about
					 * that one character.
					 */ /*
					 * We've got a real alphanumeric token here.  If it
					 * happens to be true, false, or null, all is well.  If
					 * not, error out.
					 */ /* end of switch */