v

Зеркало из https://github.com/vlang/v
Форк
0
/
txtar.v 
94 строки · 2.7 Кб
1
module txtar
2

3
// Ported from https://cs.opensource.google/go/x/tools/+/master:txtar/archive.go
4
import strings
5

6
// Archive is a collection of files
7
pub struct Archive {
8
pub mut:
9
	comment string // the start of the archive; contains potentially multiple lines, before the files
10
	files   []File // a series of files
11
}
12

13
// File is a single file in an Archive. Each starting with a `-- FILENAME --` line.
14
pub struct File {
15
pub mut:
16
	path    string // 'abc/def.v' from the `-- abc/def.v --` header
17
	content string // everything after that, till the next `-- name --` line.
18
}
19

20
// str returns a string representation of the `a` Archive.
21
// It is suitable for storing in a text file.
22
// It is also in the same format, that txtar.parse/1 expects.
23
pub fn (a &Archive) str() string {
24
	mut sb := strings.new_builder(a.comment.len + 200 * a.files.len)
25
	sb.write_string(fix_nl(a.comment))
26
	for f in a.files {
27
		sb.write_string('-- ${f.path} --\n')
28
		sb.write_string(fix_nl(f.content))
29
	}
30
	return sb.str()
31
}
32

33
// parse parses the serialized form of an Archive.
34
// The returned Archive holds slices of data.
35
pub fn parse(content string) Archive {
36
	mut a := Archive{}
37
	comment, mut name, mut data := find_file_marker(content)
38
	a.comment = comment
39
	for name != '' {
40
		mut f := File{name, ''}
41
		f.content, name, data = find_file_marker(data)
42
		a.files << f
43
	}
44
	return a
45
}
46

47
const nlm = '\n-- '
48
const mstart = '-- '
49
const mend = ' --'
50

51
// find_file_marker finds the next file marker in data, extracts the file name,
52
// and returns the data before the marker, the file name, and the data after the marker.
53
// If there is no next marker, find_file_marker returns fixNL(data), '', ''.
54
fn find_file_marker(data string) (string, string, string) {
55
	mut i := 0
56
	for i < data.len {
57
		name, after := is_marker(data[i..])
58
		if name != '' {
59
			return data[..i], name, after
60
		}
61
		j := data[i..].index(nlm) or { return fix_nl(data), '', '' }
62
		i += j + 1 // positioned at start of new possible marker
63
	}
64
	return '', '', ''
65
}
66

67
// is_marker checks whether the data begins with a file marker line.
68
// If so, it returns the name from the line, and the data after the line.
69
// Otherwise it returns name == "".
70
fn is_marker(data string) (string, string) {
71
	if !data.starts_with(mstart) {
72
		return '', ''
73
	}
74
	mut ndata := data
75
	mut after := ''
76
	i := data.index_u8(`\n`)
77
	if i >= 0 {
78
		ndata, after = data[..i], data[i + 1..]
79
	}
80
	if !(ndata.ends_with(mend) && ndata.len >= mstart.len + mend.len) {
81
		return '', ''
82
	}
83
	name := ndata[mstart.len..ndata.len - mend.len].trim_space()
84
	return name, after
85
}
86

87
// fix_nl returns the data, if it is empty, or if it ends in \n.
88
// Otherwise it returns data + a final \n added.
89
fn fix_nl(data string) string {
90
	if data.len == 0 || data[data.len - 1] == `\n` {
91
		return data
92
	}
93
	return '${data}\n'
94
}
95

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.