lichao
2021-05-10 77a6c3512a44dfe6540dde71946e6484fe4f173f
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/*
 * =====================================================================================
 *
 *       Filename:  box.cpp
 *
 *    Description:  
 *
 *        Version:  1.0
 *        Created:  2021年04月13日 15时21分44秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Li Chao (), lichao@aiotlink.com
 *   Organization:  
 *
 * =====================================================================================
 */
#include "box.h"
#include <boost/filesystem/path.hpp>
#include <map>
#include <unordered_map>
 
namespace fs = boost::filesystem;
 
namespace
{
 
class Box
{
public:
    bool Install(const std::string &name, MainFunc const &func, const std::string &desc)
    {
        return functions_.emplace(name, FuncInfo{name, func, desc}).second;
    }
    bool Find(const std::string &name, MainFunc &func)
    {
        auto pos = functions_.find(name);
        if (pos != functions_.end()) {
            func = pos->second.func_;
            return true;
        }
        return false;
    }
    void Apply(std::function<void(const std::string &id, const std::string &desc)> f) const
    {
        for (auto &kv : functions_) {
            f(kv.second.id_, kv.second.desc_);
        }
    }
 
private:
    struct FuncInfo {
        std::string id_;
        MainFunc func_;
        std::string desc_;
    };
    std::unordered_map<std::string, FuncInfo> functions_;
};
 
Box &TheBox()
{
    static Box box;
    return box;
}
 
} // namespace
 
bool BoxInstall(const std::string &name, MainFunc const &func, const std::string &desc)
{
    return TheBox().Install(name, func, desc);
}
 
bool BoxFind(const std::string &name, MainFunc &func)
{
    return TheBox().Find(name, func);
}
 
const std::string kOrigName("bhshmqbox");
 
inline void PrintLn() { putchar('\n'); }
 
template <class... Params>
void PrintLn(const char *fmt, Params &&...t)
{
    printf(fmt, std::forward<decltype(t)>(t)...);
    PrintLn();
}
 
void Help()
{
    PrintLn("%s : bhome shared memory message queue box application.", kOrigName.c_str());
    PrintLn("usage:");
    PrintLn("\t1) %s [function [options]...]", kOrigName.c_str());
    PrintLn("\t2) rename or link %s to a function name then run it directly.", kOrigName.c_str());
    PrintLn();
    PrintLn("supported functions:");
    std::map<std::string, std::string> funcs;
    auto getInfo = [&](const std::string &name, const std::string &desc) {
        funcs[name] = desc;
    };
    TheBox().Apply(getInfo);
    auto cmp_name_len = [](auto &a, auto &b) { return a.first.size() < b.first.size(); };
    int max_len = std::max_element(funcs.begin(), funcs.end(), cmp_name_len)->first.size();
    for (auto &kv : funcs) {
        int npad = max_len - kv.first.size();
        PrintLn();
        PrintLn("\t%s%s : %s", kv.first.c_str(), std::string(npad, ' ').c_str(), kv.second.c_str());
    }
    PrintLn();
}
 
int BoxMain(int argc, const char *argv[])
{
    fs::path exe(argv[0]);
    auto name = exe.filename().string();
 
    MainFunc func;
    if (BoxFind(name, func)) {
        return func(argc, argv);
    } else {
        PrintLn("%s : function not found!", name.c_str());
        // Help();
    }
    return 0;
}
 
int main(int argc, const char *argv[])
{
    BoxInstall(
        "help", [](int, const char **) { Help(); return 0; }, "show this help message.");
 
    fs::path exe(argv[0]);
    auto name = exe.filename().string();
    // PrintLn("name: %s", name.c_str());
 
    if (name == kOrigName) {
        if (argc > 1) {
            argc--;
            argv++;
        } else {
            Help();
            return 0;
        }
    }
    return BoxMain(argc, argv);
}