hare

[hare] The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

escape.ha (1240B)


      1 // SPDX-License-Identifier: MPL-2.0
      2 // (c) Hare authors <https://harelang.org>
      3 
      4 use ascii;
      5 use encoding::utf8;
      6 use io;
      7 use memio;
      8 use strings;
      9 
     10 fn is_safe(s: str) bool = {
     11 	const iter = strings::iter(s);
     12 	for (let rn => strings::next(&iter)) {
     13 		switch (rn) {
     14 		case '@', '%', '+', '=', ':', ',', '.', '/', '-' =>
     15 			void;
     16 		case =>
     17 			if (!ascii::isalnum(rn) || ascii::isspace(rn)) {
     18 				return false;
     19 			};
     20 		};
     21 	};
     22 	return true;
     23 };
     24 
     25 // Quotes a shell string and writes it to the provided I/O handle.
     26 export fn quote(sink: io::handle, s: str) (size | io::error) = {
     27 	if (len(s) == 0) {
     28 		return io::writeall(sink, strings::toutf8(`''`))?;
     29 	};
     30 	if (is_safe(s)) {
     31 		return io::writeall(sink, strings::toutf8(s))?;
     32 	};
     33 
     34 	let z = io::writeall(sink, ['\''])?;
     35 
     36 	const iter = strings::iter(s);
     37 	for (let rn => strings::next(&iter)) {
     38 		if (rn == '\'') {
     39 			z += io::writeall(sink, strings::toutf8(`'"'"'`))?;
     40 		} else {
     41 			z += io::writeall(sink, utf8::encoderune(rn))?;
     42 		};
     43 	};
     44 
     45 	z += io::writeall(sink, ['\''])?;
     46 	return z;
     47 };
     48 
     49 // Quotes a shell string and returns a new string. The caller must free the
     50 // return value.
     51 export fn quotestr(s: str) str = {
     52 	const sink = memio::dynamic();
     53 	quote(&sink, s)!;
     54 	return memio::string(&sink)!;
     55 };