1 // Copyright (C) 2018 The Android Open Source Project 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #ifndef FIXED_ARGV_H_ 16 #define FIXED_ARGV_H_ 17 18 #include <array> 19 #include <tuple> 20 #include <utility> 21 #include <vector> 22 23 #include <assert.h> 24 #include <string.h> 25 26 27 namespace header_checker { 28 namespace dumper { 29 30 31 class FixedArgvAccess; 32 33 34 class FixedArgv { 35 friend FixedArgvAccess; 36 37 private: 38 std::vector<const char *> argv_; 39 40 public: FixedArgv(int argc,const char ** argv)41 FixedArgv(int argc, const char **argv) : argv_(argv, argv + argc) {} 42 GetArgc()43 int GetArgc() const { 44 return argv_.size(); 45 } 46 GetArgv()47 const char *const *GetArgv() const { 48 return argv_.data(); 49 } 50 Resize(int argc)51 void Resize(int argc) { 52 assert(argc <= argv_.size()); 53 argv_.resize(argc); 54 } 55 56 template <typename... T> GetLastArg(T &&...options)57 const char *GetLastArg(T&& ...options) const { 58 std::array<const char *, sizeof...(options)> opts{ 59 std::forward<T&&>(options)...}; 60 for (std::vector<const char *>::const_reverse_iterator it = argv_.rbegin(), 61 end = argv_.rend(); it != end; ++it) { 62 for (const char *opt : opts) { 63 if (::strcmp(*it, opt) == 0) { 64 return opt; 65 } 66 } 67 } 68 return nullptr; 69 } 70 71 template <typename... T> IsLastArgEqualFirstOption(const char * expected,T &&...others)72 bool IsLastArgEqualFirstOption(const char *expected, T&& ...others) const { 73 const char *last = GetLastArg(expected, others...); 74 // Since GetLastArg() returns the address in {expected, others...}, pointer 75 // comparison is sufficient. 76 return last == expected; 77 } 78 79 template<typename... T> PushForwardArgs(T &&...arguments)80 void PushForwardArgs(T&& ...arguments) { 81 std::array<const char *, sizeof...(arguments)> args{ 82 std::forward<T&&>(arguments)...}; 83 if (!GetLastArg("--")) { 84 argv_.push_back("--"); 85 } 86 argv_.insert(argv_.end(), args.begin(), args.end()); 87 } 88 }; 89 90 91 class FixedArgvAccess { 92 private: 93 FixedArgv &fixed_argv_; 94 95 public: 96 int argc_; 97 const char **argv_; 98 99 public: FixedArgvAccess(FixedArgv & fixed_argv)100 explicit FixedArgvAccess(FixedArgv &fixed_argv) 101 : fixed_argv_(fixed_argv), argc_(fixed_argv.GetArgc()), 102 argv_(fixed_argv.argv_.data()) { 103 } 104 ~FixedArgvAccess()105 ~FixedArgvAccess() { 106 fixed_argv_.Resize(argc_); 107 } 108 109 private: 110 FixedArgvAccess(const FixedArgvAccess &) = delete; 111 FixedArgvAccess& operator=(const FixedArgvAccess &rhs) = delete; 112 }; 113 114 115 class FixedArgvRegistry { 116 public: 117 typedef void (Function)(FixedArgv &); 118 119 private: 120 static FixedArgvRegistry *head_; 121 122 Function *func_; 123 FixedArgvRegistry *next_; 124 125 public: FixedArgvRegistry(Function * func)126 FixedArgvRegistry(Function *func) : func_(func), next_(head_) { 127 head_ = this; 128 } 129 Apply(FixedArgv & fixed_argv)130 static void Apply(FixedArgv &fixed_argv) { 131 for (FixedArgvRegistry *ptr = head_; ptr; ptr = ptr->next_) { 132 ptr->func_(fixed_argv); 133 } 134 } 135 }; 136 137 138 } // namespace dumper 139 } // namespace header_checker 140 141 142 #endif // FIXED_ARGV_H_ 143