1 /*
2  * Copyright (C) 2015 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 
17 #ifndef _INIT_KEYWORD_MAP_H_
18 #define _INIT_KEYWORD_MAP_H_
19 
20 #include <map>
21 #include <string>
22 
23 #include <android-base/stringprintf.h>
24 
25 #include "result.h"
26 
27 namespace android {
28 namespace init {
29 
30 template <typename Function>
31 class KeywordMap {
32   public:
33     using FunctionInfo = std::tuple<std::size_t, std::size_t, Function>;
34     using Map = std::map<std::string, FunctionInfo>;
35 
~KeywordMap()36     virtual ~KeywordMap() {
37     }
38 
FindFunction(const std::vector<std::string> & args)39     const Result<Function> FindFunction(const std::vector<std::string>& args) const {
40         using android::base::StringPrintf;
41 
42         if (args.empty()) return Error() << "Keyword needed, but not provided";
43 
44         auto& keyword = args[0];
45         auto num_args = args.size() - 1;
46 
47         auto function_info_it = map().find(keyword);
48         if (function_info_it == map().end()) {
49             return Error() << StringPrintf("Invalid keyword '%s'", keyword.c_str());
50         }
51 
52         auto function_info = function_info_it->second;
53 
54         auto min_args = std::get<0>(function_info);
55         auto max_args = std::get<1>(function_info);
56         if (min_args == max_args && num_args != min_args) {
57             return Error() << StringPrintf("%s requires %zu argument%s", keyword.c_str(), min_args,
58                                            (min_args > 1 || min_args == 0) ? "s" : "");
59         }
60 
61         if (num_args < min_args || num_args > max_args) {
62             if (max_args == std::numeric_limits<decltype(max_args)>::max()) {
63                 return Error() << StringPrintf("%s requires at least %zu argument%s",
64                                                keyword.c_str(), min_args, min_args > 1 ? "s" : "");
65             } else {
66                 return Error() << StringPrintf("%s requires between %zu and %zu arguments",
67                                                keyword.c_str(), min_args, max_args);
68             }
69         }
70 
71         return std::get<Function>(function_info);
72     }
73 
74   private:
75     // Map of keyword ->
76     // (minimum number of arguments, maximum number of arguments, function pointer)
77     virtual const Map& map() const = 0;
78 };
79 
80 }  // namespace init
81 }  // namespace android
82 
83 #endif
84