1 /// Copyright: Copyright (c) 2017-2019 Andrey Penechko.
2 /// License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0).
3 /// Authors: Andrey Penechko.
4 
5 /// Parses HAR - Human Archive Format: https://github.com/marler8997/har
6 module vox.utils.har;
7 
8 import vox.context : CompilationContext;
9 import vox.fe.ast.source_file : SourceFileInfo;
10 
11 void parseHar(
12 	ref CompilationContext context,
13 	string harFilename,
14 	const(char)[] harData,
15 	void delegate(SourceFileInfo fileInfo) onFile)
16 {
17 	import std.string : indexOf, lineSplitter;
18 	import std.algorithm : startsWith;
19 	auto lines = harData.lineSplitter;
20 	size_t lineNumber = 1;
21 	auto line = lines.front;
22 
23 	auto spaceIndex = line.indexOf(' ');
24 	if (spaceIndex <= 0) {
25 		context.error("HAR file error `%s`: First line must start with delimiter ending with space", harFilename);
26 		return;
27 	}
28 
29 	auto delimiter = line[0 .. spaceIndex + 1];
30 
31 	outer:
32 	while (true)
33 	{
34 		if (line.length == 0) {
35 			context.error("HAR file error `%s`: Missing filename on line %s", harFilename, lineNumber);
36 			return;
37 		}
38 
39 		string filename = cast(string)line[delimiter.length .. $];
40 		lines.popFront();
41 
42 		if (lines.empty) break;
43 		const(char)* fileStart = lines.front.ptr;
44 		const(char)* fileEnd = lines.front.ptr + lines.front.length;
45 
46 		while (true)
47 		{
48 			if (lines.empty) {
49 				onFile(SourceFileInfo(filename, fileStart[0..fileEnd-fileStart]));
50 				break outer;
51 			}
52 
53 			lineNumber++;
54 			line = lines.front;
55 
56 			if (line.startsWith(delimiter)) {
57 				onFile(SourceFileInfo(filename, fileStart[0..line.ptr-fileStart]));
58 				break;
59 			}
60 
61 			fileEnd = lines.front.ptr + lines.front.length;
62 			lines.popFront();
63 		}
64 	}
65 }