1 | // Copyright 2013 The Flutter Authors. All rights reserved. |
---|---|
2 | // Use of this source code is governed by a BSD-style license that can be |
3 | // found in the LICENSE file. |
4 | |
5 | // Spec: https://github.com/lrhn/dep-pkgspec/blob/master/DEP-pkgspec.md |
6 | |
7 | #include "tonic/parsers/packages_map.h" |
8 | |
9 | #include <memory> |
10 | |
11 | namespace tonic { |
12 | namespace { |
13 | |
14 | bool isLineBreak(char c) { |
15 | return c == '\r' || c == '\n'; |
16 | } |
17 | |
18 | } // namespace |
19 | |
20 | PackagesMap::PackagesMap() {} |
21 | |
22 | PackagesMap::~PackagesMap() {} |
23 | |
24 | bool PackagesMap::Parse(const std::string& source, std::string* error) { |
25 | map_.clear(); |
26 | const auto end = source.end(); |
27 | for (auto it = source.begin(); it != end; ++it) { |
28 | const char c = *it; |
29 | |
30 | // Skip blank lines. |
31 | if (isLineBreak(c)) |
32 | continue; |
33 | |
34 | // Skip comments. |
35 | if (c == '#') { |
36 | while (it != end && !isLineBreak(*it)) |
37 | ++it; |
38 | continue; |
39 | } |
40 | |
41 | if (c == ':') { |
42 | map_.clear(); |
43 | *error = "Packages file contains a line that begins with ':'."; |
44 | return false; |
45 | } |
46 | |
47 | auto package_name_begin = it; |
48 | auto package_name_end = end; |
49 | bool found_separator = false; |
50 | for (; it != end; ++it) { |
51 | const char c = *it; |
52 | if (c == ':' && !found_separator) { |
53 | found_separator = true; |
54 | package_name_end = it; |
55 | continue; |
56 | } |
57 | if (isLineBreak(c)) |
58 | break; |
59 | } |
60 | |
61 | if (!found_separator) { |
62 | map_.clear(); |
63 | *error = "Packages file contains non-comment line that lacks a ':'."; |
64 | return false; |
65 | } |
66 | |
67 | std::string package_name(package_name_begin, package_name_end); |
68 | std::string package_path(package_name_end + 1, it); |
69 | |
70 | auto result = map_.emplace(package_name, package_path); |
71 | if (!result.second) { |
72 | map_.clear(); |
73 | *error = |
74 | std::string("Packages file contains multiple entries for package '") + |
75 | package_name + "'."; |
76 | return false; |
77 | } |
78 | } |
79 | |
80 | return true; |
81 | } |
82 | |
83 | std::string PackagesMap::Resolve(const std::string& package_name) { |
84 | return map_[package_name]; |
85 | } |
86 | |
87 | } // namespace tonic |
88 |