1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #include "utils.h"
17 
18 #include <sstream>
19 
20 #include "parse_string.h"
21 
22 namespace android::vintf::details {
23 
24 bool canConvertToFqInstance(const std::string& package, const Version& version,
25                             const std::string& interface, const std::string& instance,
26                             HalFormat format, std::string* appendedError) {
27     if (FqInstance::from(package, version.majorVer, version.minorVer, interface, instance)
28             .has_value()) {
29         return true;
30     }
31     if (appendedError == nullptr) {
32         return false;
33     }
34 
35     // Attempt to construct a good error message.
36     std::stringstream ss;
37     ss << "Invalid instance: '";
38     if (format == HalFormat::AIDL) {
39         ss << toAidlFqnameString(package, interface, instance) << " (@" << version.minorVer << ")";
40     } else {
41         ss << toFQNameString(package, version, interface, instance);
42     }
43     ss << "'. ";
44 
45     // Attempt to guess the source of error.
46     bool foundError = false;
47     if (!FqInstance::from(package).has_value()) {
48         ss << "Package '" << package
49            << "' should have the format [a-zA-Z_][a-zA-Z0-9_]*(\\.[a-zA-Z_][a-zA-Z0-9_]*)*";
50         foundError = true;
51     }
52 
53     std::optional<FqInstance> convertedInterface = FqInstance::from(interface);
54     if (!convertedInterface.has_value() || !convertedInterface->hasInterface()) {
55         ss << "Interface '" << interface << "' should have the format I[a-zA-Z0-9_]*";
56         foundError = true;
57     }
58 
59     if (!foundError) {
60         ss << "Unknown error.";
61     }
62     ss << "\n";
63 
64     *appendedError += ss.str();
65     return false;
66 }
67 
68 }  // namespace android::vintf::details
69