gen: scape string function in gen/str.v (#6452)
							parent
							
								
									be2ac0ba89
								
							
						
					
					
						commit
						60fbcc37fc
					
				|  | @ -619,7 +619,7 @@ fn test_for_loop_two() { | |||
| 
 | ||||
| fn test_quote() { | ||||
| 	a := `'` | ||||
| 	println("testing double quotes") | ||||
| 	println("testing double quotes \"") | ||||
| 	b := "hi" | ||||
| 	assert b == 'hi' | ||||
| 	assert a.str() == '\'' | ||||
|  |  | |||
							
								
								
									
										100
									
								
								vlib/v/gen/str.v
								
								
								
								
							
							
						
						
									
										100
									
								
								vlib/v/gen/str.v
								
								
								
								
							|  | @ -5,6 +5,97 @@ module gen | |||
| import v.ast | ||||
| import v.table | ||||
| 
 | ||||
| fn smart_quote(str string, raw bool) string { | ||||
| 	len := str.len | ||||
| 	if len == 0 { | ||||
| 		return str | ||||
| 	} | ||||
| 	mut result := '' | ||||
| 	mut pos := -1 | ||||
| 	mut last := '' | ||||
| 	mut next := '' | ||||
| 	mut skip_next := false | ||||
| 	for { | ||||
| 		pos = pos + 1 | ||||
| 		if skip_next { | ||||
| 			skip_next = false | ||||
| 			pos = pos + 1 | ||||
| 		} | ||||
| 		if pos >= len { | ||||
| 			break | ||||
| 		} | ||||
| 		if pos + 1 < len { | ||||
| 			unsafe { | ||||
| 				next = str.str[pos + 1].str() | ||||
| 			} | ||||
| 		} | ||||
| 		mut current := str | ||||
| 		mut toadd := str | ||||
| 		if len > 1 { | ||||
| 			unsafe { | ||||
| 				current = str.str[pos].str() | ||||
| 			} | ||||
| 			toadd = current | ||||
| 		} | ||||
| 		// double quote
 | ||||
| 		if current == '"' { | ||||
| 			toadd = '\\"' | ||||
| 			current = '' | ||||
| 		} | ||||
| 		if raw && current == '\\' { | ||||
| 			toadd = '\\\\' | ||||
| 		} | ||||
| 		// keep newlines in string
 | ||||
| 		if current == '\n' { | ||||
| 			toadd = '\\n' | ||||
| 			current = '' | ||||
| 		} | ||||
| 		if current == '\r' && next == '\n' { | ||||
| 			toadd = '\r\n' | ||||
| 			current = '' | ||||
| 			skip_next = true | ||||
| 		} | ||||
| 		// backslash
 | ||||
| 		if !raw && current == '\\' { | ||||
| 			// escaped backslash - keep as is
 | ||||
| 			if next == '\\' { | ||||
| 				toadd = '\\\\' | ||||
| 				skip_next = true | ||||
| 			} | ||||
| 			// keep raw escape squence
 | ||||
| 			else { | ||||
| 				if next != '' { | ||||
| 					if raw { | ||||
| 						toadd = '\\\\' + next | ||||
| 						skip_next = true | ||||
| 					} | ||||
| 					// escape it
 | ||||
| 					else { | ||||
| 						toadd = '\\' + next | ||||
| 						skip_next = true | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		// Dolar sign
 | ||||
| 		if !raw && current == '$' { | ||||
| 			if last == '\\' { | ||||
| 				toadd = '\\$' | ||||
| 			} | ||||
| 		} | ||||
| 		// Windows style new line \r\n
 | ||||
| 		if !raw && current == '\r' { | ||||
| 			if next == '\n' { | ||||
| 				skip_next = true | ||||
| 				toadd = '\\n' | ||||
| 			} | ||||
| 		} | ||||
| 		result = result + toadd | ||||
| 		last = current | ||||
| 	} | ||||
| 	return result | ||||
| } | ||||
| 
 | ||||
| fn (mut g Gen) write_str_fn_definitions() { | ||||
| 	// _STR function can't be defined in vlib
 | ||||
| 	g.writeln(" | ||||
|  | @ -118,11 +209,11 @@ string _STR_TMP(const char *fmt, ...) { | |||
| 
 | ||||
| fn (mut g Gen) string_literal(node ast.StringLiteral) { | ||||
| 	if node.is_raw { | ||||
| 		escaped_val := node.val.replace_each(['"', '\\"', '\\', '\\\\']) | ||||
| 		escaped_val := smart_quote(node.val, true) | ||||
| 		g.write('tos_lit("$escaped_val")') | ||||
| 		return | ||||
| 	} | ||||
| 	escaped_val := node.val.replace_each(['"', '\\"', '\r\n', '\\n', '\n', '\\n']) | ||||
| 	escaped_val := smart_quote(node.val, false) | ||||
| 	if g.is_c_call || node.language == .c { | ||||
| 		// In C calls we have to generate C strings
 | ||||
| 		// `C.printf("hi")` => `printf("hi");`
 | ||||
|  | @ -149,7 +240,7 @@ fn (mut g Gen) string_inter_literal_sb_optimized(call_expr ast.CallExpr) { | |||
| 	is_nl := call_expr.name == 'writeln' | ||||
| 	// println('optimize sb $call_expr.name')
 | ||||
| 	for i, val in node.vals { | ||||
| 		escaped_val := val.replace_each(['"', '\\"', '\r\n', '\\n', '\n', '\\n', '%', '%%']) | ||||
| 		escaped_val := smart_quote(val, false) | ||||
| 		// if val == '' {
 | ||||
| 		// break
 | ||||
| 		// continue
 | ||||
|  | @ -220,7 +311,8 @@ fn (mut g Gen) string_inter_literal(node ast.StringInterLiteral) { | |||
| 	// Build the string with %
 | ||||
| 	mut end_string := false | ||||
| 	for i, val in node.vals { | ||||
| 		escaped_val := val.replace_each(['"', '\\"', '\r\n', '\\n', '\n', '\\n', '%', '%%']) | ||||
| 		mut escaped_val := val.replace_each(['%', '%%']) | ||||
| 		escaped_val = smart_quote(escaped_val, false) | ||||
| 		if i >= node.exprs.len { | ||||
| 			if escaped_val.len > 0 { | ||||
| 				end_string = true | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue