json2: unescape characters (#6836)
							parent
							
								
									c8b7cfc297
								
							
						
					
					
						commit
						fe3d2a9aba
					
				|  | @ -223,8 +223,6 @@ fn (mut p Parser) decode_value() ?Any { | |||
| fn (mut p Parser) decode_string() ?Any { | ||||
| 	mut strwr := strings.new_builder(200) | ||||
| 	for i := 0; i < p.tok.lit.len; i++ { | ||||
| 		// s := p.tok.lit[i].str()
 | ||||
| 		// println('$i $s')
 | ||||
| 		if ((i-1 >= 0 && p.tok.lit[i-1] != `/`) || i == 0) && int(p.tok.lit[i]) in [9, 10, 0] { | ||||
| 			return error('character must be escaped with a backslash.') | ||||
| 		} | ||||
|  | @ -235,8 +233,33 @@ fn (mut p Parser) decode_string() ?Any { | |||
| 
 | ||||
| 		if i+1 < p.tok.lit.len && p.tok.lit[i] == 92 { | ||||
| 			peek := p.tok.lit[i+1] | ||||
| 			if peek in [`b`, `f`, `n`, `r`, `t`, `u`, `\\`, `"`, `/`] { | ||||
| 				if peek == `u` { | ||||
| 			match peek{ | ||||
| 				`b` { | ||||
| 					i++ | ||||
| 					strwr.write_b(`\b`) | ||||
| 					continue | ||||
| 				} | ||||
| 				`f` { | ||||
| 					i++ | ||||
| 					strwr.write_b(`\f`) | ||||
| 					continue | ||||
| 				} | ||||
| 				`n` { | ||||
| 					i++ | ||||
| 					strwr.write_b(`\n`) | ||||
| 					continue | ||||
| 				} | ||||
| 				`r` { | ||||
| 					i++ | ||||
| 					strwr.write_b(`\r`) | ||||
| 					continue | ||||
| 				} | ||||
| 				`t` { | ||||
| 					i++ | ||||
| 					strwr.write_b(`\t`) | ||||
| 					continue | ||||
| 				} | ||||
| 				`u` { | ||||
| 					if i+5 < p.tok.lit.len { | ||||
| 						codepoint := p.tok.lit[i+2..i+6] | ||||
| 						check_valid_hex(codepoint)? | ||||
|  | @ -248,13 +271,23 @@ fn (mut p Parser) decode_string() ?Any { | |||
| 						return error('incomplete unicode escape.') | ||||
| 					} | ||||
| 				} | ||||
| 
 | ||||
| 				i++ | ||||
| 				strwr.write_b(p.tok.lit[i]) | ||||
| 				continue | ||||
| 			} else { | ||||
| 				return error('invalid backslash escape.') | ||||
| 			} | ||||
| 				`\\` { | ||||
| 					i++ | ||||
| 					strwr.write_b(`\\`) | ||||
| 					continue | ||||
| 				} | ||||
| 				`"` { | ||||
| 					i++ | ||||
| 					strwr.write_b(`\"`) | ||||
| 					continue | ||||
| 				} | ||||
| 				`/` { | ||||
| 					i++ | ||||
| 					strwr.write_b(`/`) | ||||
| 					continue | ||||
| 				} | ||||
| 				else { return error('invalid backslash escape.') } | ||||
| 			}  | ||||
| 
 | ||||
| 			if int(peek) == 85 { | ||||
| 				return error('unicode endpoints must be in lowercase `u`.') | ||||
|  |  | |||
|  | @ -7,7 +7,11 @@ import strings | |||
| 
 | ||||
| fn write_value(v Any, i int, len int, mut wr strings.Builder) { | ||||
| 	str := v.str() | ||||
| 	wr.write(if v is string { '"$str"' } else { str }) | ||||
| 	if v is string {  | ||||
| 		wr.write('"$str"')  | ||||
| 	} else {  | ||||
| 		wr.write(str) | ||||
| 	} | ||||
| 	if i >= len-1 { return } | ||||
| 	wr.write_b(`,`) | ||||
| } | ||||
|  |  | |||
|  | @ -69,6 +69,28 @@ fn test_fast_raw_decode() { | |||
| 	assert str == '{"name":"Peter","age":"28","salary":"95000.5","title":"2"}' | ||||
| } | ||||
| 
 | ||||
| fn test_character_unescape() { | ||||
| 	// Need to test `\r`, `\b`, `\f` ??
 | ||||
| 	message := '{ | ||||
| 		"newline":"new\\nline",  | ||||
| 		"tab":"\\ttab",  | ||||
| 		"backslash": "back\\\\slash",  | ||||
| 		"quotes": "\\"quotes\\"",  | ||||
| 		"slash":"\/dev\/null" | ||||
| 	}' | ||||
| 	mut obj := json2.raw_decode(message) or { | ||||
| 		assert false | ||||
| 		json2.Any{} | ||||
| 	} | ||||
| 	lines := obj.as_map() | ||||
| 	eprintln("$lines") | ||||
| 	assert lines['newline'].str() == 'new\nline' | ||||
| 	assert lines['tab'].str() == '\ttab' | ||||
| 	assert lines['backslash'].str() == 'back\\slash' | ||||
| 	assert lines['quotes'].str() == '\"quotes\"' | ||||
| 	assert lines['slash'].str() == '/dev/null' | ||||
| } | ||||
| 
 | ||||
| /* | ||||
| struct User2 { | ||||
| 	age  int | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue