hare

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

join.ha (1858B)


      1 // License: MPL-2.0
      2 // (c) 2021-2022 Drew DeVault <sir@cmpwn.com>
      3 use bytes;
      4 use errors;
      5 use strings;
      6 
      7 // Joins several path elements together and copies them into a path buffer.
      8 // Returns the new string value of the path.
      9 export fn add(buf: *buffer, items: str...) (str | errors::overflow) = {
     10 	for (let i = 0z; i < len(items); i += 1) {
     11 		const elem = strings::toutf8(items[i]);
     12 		const tok = bytes::tokenize(elem, pathsep);
     13 		for (let j = 0z; true; j += 1) {
     14 			const next = match (bytes::next_token(&tok)) {
     15 			case let tok: []u8 =>
     16 				yield tok;
     17 			case void =>
     18 				break;
     19 			};
     20 			if (len(next) == 0 && j == 0) {
     21 				// Handles the add("/foo") case as
     22 				// add("/", "foo");
     23 				appendnorm(buf, pathsepstr)?;
     24 			};
     25 			appendnorm(buf, next)?;
     26 		};
     27 	};
     28 	return string(buf);
     29 };
     30 
     31 @test fn add() void = {
     32 	let buf = init();
     33 	add(&buf, "foo", "bar", "baz")!;
     34 	let s = strings::join(pathsepstr, "foo", "bar", "baz");
     35 	assert(string(&buf) == s);
     36 	free(s);
     37 
     38 	reset(&buf);
     39 	s = strings::join(pathsepstr, "", "foo", "bar");
     40 	add(&buf, s, "baz")!;
     41 	free(s);
     42 	s = strings::join(pathsepstr, "", "foo", "bar", "baz");
     43 	assert(string(&buf) == s);
     44 	free(s);
     45 
     46 	reset(&buf);
     47 	s = strings::join(pathsepstr, "foo", "bar");
     48 	add(&buf, pathsepstr, s, "baz")!;
     49 	free(s);
     50 	s = strings::join(pathsepstr, "", "foo", "bar", "baz");
     51 	assert(string(&buf) == s);
     52 	free(s);
     53 
     54 	reset(&buf);
     55 	s = strings::join(pathsepstr, ".", "foo", "bar");
     56 	add(&buf, s)!;
     57 	free(s);
     58 	s = strings::join(pathsepstr, "foo", "bar");
     59 	assert(string(&buf) == s);
     60 	free(s);
     61 };
     62 
     63 // Joins a list of path components together, normalizes it, and returns the
     64 // resulting string. The caller must free the return value. If the resulting
     65 // path would exceed [[PATH_MAX]], the program aborts.
     66 export fn join(items: str...) str = {
     67 	static let buf = buffer { ... };
     68 	return strings::dup(set(&buf, items...)!);
     69 };