1 /* $Id: cidtool.cpp 457251 2015-01-21 17:47:30Z kazimird $
2 * ===========================================================================
3 *
4 * PUBLIC DOMAIN NOTICE
5 * National Center for Biotechnology Information
6 *
7 * This software/database is a "United States Government Work" under the
8 * terms of the United States Copyright Act. It was written as part of
9 * the author's official duties as a United States Government employee and
10 * thus cannot be copyrighted. This software/database is freely available
11 * to the public for use. The National Library of Medicine and the U.S.
12 * Government have not placed any restriction on its use or reproduction.
13 *
14 * Although all reasonable efforts have been taken to ensure the accuracy
15 * and reliability of the software and data, the NLM and the U.S.
16 * Government do not and cannot warrant the performance or results that
17 * may be obtained by using this software or data. The NLM and the U.S.
18 * Government disclaim all warranties, express or implied, including
19 * warranties of performance, merchantability or fitness for any particular
20 * purpose.
21 *
22 * Please cite the author in any work or product based on this material.
23 *
24 * ===========================================================================
25 *
26 * Authors: Dmitry Kazimirov
27 *
28 * File Description: Entry point and command line parsing
29 * of the cidtool application.
30 *
31 */
32
33 #include <ncbi_pch.hpp>
34
35 #include "cidtool.hpp"
36
37 #include <connect/services/clparser.hpp>
38 #include <connect/services/grid_app_version_info.hpp>
39
40 #include <corelib/ncbistre.hpp>
41 #include <corelib/ncbi_config.hpp>
42
43
44 USING_NCBI_SCOPE;
45
CComponentIDToolApp(int argc,const char * argv[])46 CComponentIDToolApp::CComponentIDToolApp(int argc, const char* argv[]) :
47 m_ArgC(argc),
48 m_ArgV(argv)
49 {
50 }
51
52 #ifdef _DEBUG
53 #define OPT_DEF(opt_type, opt_id) CCommandLineParser::opt_type, opt_id
54 #else
55 #define OPT_DEF(opt_type, opt_id) CCommandLineParser::opt_type
56 #endif
57
58 struct SOptionDefinition {
59 CCommandLineParser::EOptionType type;
60 #ifdef _DEBUG
61 int opt_id;
62 #endif
63 const char* name_variants;
64 const char* description;
65 int required_options[2];
66 } static const s_OptionDefinitions[eNumberOfOptions] = {
67
68 {OPT_DEF(ePositionalArgument, eCID), "CID", NULL, {-1}},
69
70 {OPT_DEF(eOptionWithParameter, eInputFile),
71 INPUT_FILE_OPTION, "Read input from the specified file.", {-1}},
72
73 {OPT_DEF(eOptionWithParameter, eOutputFile),
74 "o|" OUTPUT_FILE_OPTION, "Save output to the specified file.", {-1}},
75 };
76
77 struct SCommandDefinition {
78 int (CComponentIDToolApp::*cmd_proc)();
79 const char* name_variants;
80 const char* synopsis;
81 const char* usage;
82 int options[eNumberOfOptions + 1];
83 } static const s_CommandDefinitions[] = {
84
85 {&CComponentIDToolApp::Cmd_Dump,
86 "dump", "Dump the contents of a CompoundID.",
87 "Print the contents of the CompoundID specified on the "
88 "command line to the standard output stream (or a file).",
89 {eCID, eOutputFile, -1}},
90
91 {&CComponentIDToolApp::Cmd_Make,
92 "make", "Generate a CompoundID.",
93 "Read CompoundID dump from the standard input stream "
94 "(or the specified file) and print the CompoundID that "
95 "corresponds it.",
96 {eInputFile, -1}},
97 };
98
99 #define TOTAL_NUMBER_OF_COMMANDS int(sizeof(s_CommandDefinitions) / \
100 sizeof(*s_CommandDefinitions))
101
Run()102 int CComponentIDToolApp::Run()
103 {
104 const SCommandDefinition* cmd_def;
105 const int* cmd_opt;
106
107 {
108 CCommandLineParser clparser(GRID_APP_NAME, GRID_APP_VERSION_INFO,
109 "Generate and decode identifiers in CompoundID format.");
110
111 const SOptionDefinition* opt_def = s_OptionDefinitions;
112 int opt_id = 0;
113 do {
114 #ifdef _DEBUG
115 _ASSERT(opt_def->opt_id == opt_id &&
116 "EOption order must match positions in s_OptionDefinitions.");
117 #endif
118 clparser.AddOption(opt_def->type, opt_id,
119 opt_def->name_variants, opt_def->description ?
120 opt_def->description : kEmptyStr);
121 ++opt_def;
122 } while (++opt_id < eNumberOfOptions);
123
124 cmd_def = s_CommandDefinitions;
125 for (int i = 0; i < TOTAL_NUMBER_OF_COMMANDS; ++i, ++cmd_def) {
126 clparser.AddCommand(i, cmd_def->name_variants,
127 cmd_def->synopsis, cmd_def->usage);
128 for (cmd_opt = cmd_def->options; *cmd_opt >= 0; ++cmd_opt)
129 clparser.AddAssociation(i, *cmd_opt);
130 }
131
132 try {
133 int cmd_id = clparser.Parse(m_ArgC, m_ArgV);
134 if (cmd_id < 0)
135 return 0;
136
137 cmd_def = s_CommandDefinitions + cmd_id;
138 }
139 catch (exception& e) {
140 NcbiCerr << e.what();
141 return 1;
142 }
143
144 for (cmd_opt = cmd_def->options; *cmd_opt >= 0; ++cmd_opt)
145 MarkOptionAsAccepted(*cmd_opt);
146
147 const char* opt_value;
148
149 while (clparser.NextOption(&opt_id, &opt_value)) {
150 MarkOptionAsExplicitlySet(opt_id);
151 switch (EOption(opt_id)) {
152 case eCID:
153 m_Opts.cid = opt_value;
154 break;
155 case eInputFile:
156 if ((m_Opts.input_stream = fopen(opt_value, "rb")) == NULL) {
157 fprintf(stderr, "%s: %s\n", opt_value, strerror(errno));
158 return 2;
159 }
160 break;
161 case eOutputFile:
162 if ((m_Opts.output_stream = fopen(opt_value, "wb")) == NULL) {
163 fprintf(stderr, "%s: %s\n", opt_value, strerror(errno));
164 return 2;
165 }
166 break;
167 default: // Just to silence the compiler.
168 break;
169 }
170 }
171
172 opt_id = eNumberOfOptions - 1;
173 do
174 if (IsOptionSet(opt_id))
175 for (const int* required_opt =
176 s_OptionDefinitions[opt_id].required_options;
177 *required_opt != -1; ++required_opt)
178 if (!IsOptionSet(*required_opt)) {
179 fprintf(stderr, GRID_APP_NAME
180 ": option '--%s' requires option '--%s'.\n",
181 s_OptionDefinitions[opt_id].name_variants,
182 s_OptionDefinitions[
183 *required_opt].name_variants);
184 return 2;
185 }
186 while (--opt_id >= 0);
187
188 if (IsOptionAcceptedButNotSet(eInputFile)) {
189 m_Opts.input_stream = stdin;
190 }
191 if (IsOptionAcceptedButNotSet(eOutputFile)) {
192 m_Opts.output_stream = stdout;
193 }
194 }
195
196 try {
197 return (this->*cmd_def->cmd_proc)();
198 }
199 catch (CConfigException& e) {
200 fprintf(stderr, "%s\n", e.GetMsg().c_str());
201 return 2;
202 }
203 catch (CArgException& e) {
204 fprintf(stderr, GRID_APP_NAME " %s: %s\n",
205 cmd_def->name_variants, e.GetMsg().c_str());
206 return 2;
207 }
208 catch (CException& e) {
209 fprintf(stderr, "%s\n", e.what());
210 return 3;
211 }
212 catch (string& s) {
213 fprintf(stderr, "%s\n", s.c_str());
214 return 4;
215 }
216 }
217
~CComponentIDToolApp()218 CComponentIDToolApp::~CComponentIDToolApp()
219 {
220 if (IsOptionSet(eInputFile) && m_Opts.input_stream != NULL)
221 fclose(m_Opts.input_stream);
222 if (IsOptionSet(eOutputFile) && m_Opts.output_stream != NULL)
223 fclose(m_Opts.output_stream);
224 }
225
Cmd_Dump()226 int CComponentIDToolApp::Cmd_Dump()
227 {
228 CCompoundID cid(m_CompoundIDPool.FromString(m_Opts.cid));
229
230 fprintf(m_Opts.output_stream, "%s\n", cid.Dump().c_str());
231
232 return 0;
233 }
234
Cmd_Make()235 int CComponentIDToolApp::Cmd_Make()
236 {
237 string dump;
238
239 char buffer[1024];
240 size_t bytes_read;
241
242 do {
243 bytes_read = fread(buffer, 1, sizeof(buffer), m_Opts.input_stream);
244 dump.append(buffer, bytes_read);
245 } while (bytes_read == sizeof(buffer));
246
247 CCompoundID cid(m_CompoundIDPool.FromDump(dump));
248
249 puts(cid.ToString().c_str());
250
251 return 0;
252 }
253
main(int argc,const char * argv[])254 int main(int argc, const char* argv[])
255 {
256 return CComponentIDToolApp(argc, argv).AppMain(1, argv);
257 }
258