1 // ***************************************************************************
2 // bamtools_options.cpp (c) 2010 Derek Barnett, Erik Garrison
3 // Marth Lab, Department of Biology, Boston College
4 // All rights reserved.
5 // ---------------------------------------------------------------------------
6 // Last modified: 11 June 2011
7 // ---------------------------------------------------------------------------
8 // Parses command line arguments and creates a help menu
9 // ---------------------------------------------------------------------------
11 // The Mosaik suite's command line parser class: COptions
12 // (c) 2006 - 2009 Michael Str�mberg
13 // Marth Lab, Department of Biology, Boston College
14 // Re-licensed under MIT License with author's permission.
16 // * Modified slightly to fit BamTools, otherwise code is same.
17 // * (BamTools namespace, added stdin/stdout) (DB)
18 // ***************************************************************************
20 #include <utils/bamtools_options.h>
21 using namespace BamTools;
30 string Options::m_programName; // the program name
31 string Options::m_description; // the main description
32 string Options::m_exampleArguments; // the example arguments
33 vector<OptionGroup> Options::m_optionGroups; // stores the option groups
34 map<string, OptionValue> Options::m_optionsMap; // stores the options in a map
35 const string Options::m_stdin = "stdin"; // string representation of stdin
36 const string Options::m_stdout = "stdout"; // string representation of stdout
38 // adds a simple option to the parser
39 void Options::AddOption(const string& argument,
40 const string& optionDescription,
45 o.Argument = argument;
46 o.Description = optionDescription;
48 group->Options.push_back(o);
51 ov.pFoundArgument = &foundArgument;
52 ov.StoreValue = false;
54 m_optionsMap[argument] = ov;
57 // creates an option group
58 OptionGroup* Options::CreateOptionGroup(const string& groupName) {
61 m_optionGroups.push_back(og);
62 return &m_optionGroups[m_optionGroups.size() - 1];
65 // displays the help menu
66 void Options::DisplayHelp(void) {
69 char argumentBuffer[ARGUMENT_LENGTH + 1];
72 char indentBuffer[MAX_LINE_LENGTH - DESC_LENGTH + 1];
73 memset(indentBuffer, ' ', MAX_LINE_LENGTH - DESC_LENGTH);
74 indentBuffer[MAX_LINE_LENGTH - DESC_LENGTH] = 0;
77 printf("Description: %s.\n\n", m_description.c_str());
79 printf("%s", m_programName.c_str());
80 printf(" %s\n\n", m_exampleArguments.c_str());
82 vector<Option>::const_iterator optionIter;
83 vector<OptionGroup>::const_iterator groupIter;
84 for (groupIter = m_optionGroups.begin(); groupIter != m_optionGroups.end(); ++groupIter) {
86 printf("%s:\n", groupIter->Name.c_str());
88 for (optionIter = groupIter->Options.begin(); optionIter != groupIter->Options.end(); ++optionIter) {
90 if (optionIter->StoreValue)
91 snprintf(argumentBuffer, ARGUMENT_LENGTH + 1, " %s <%s>", optionIter->Argument.c_str(), optionIter->ValueDescription.c_str());
93 snprintf(argumentBuffer, ARGUMENT_LENGTH + 1, " %s", optionIter->Argument.c_str());
94 printf("%-35s ", argumentBuffer);
96 string description = optionIter->Description;
98 // handle default values
99 if (optionIter->HasDefaultValue) {
102 sb << description << " [";
104 if (optionIter->DefaultValue.is_type<unsigned int>()) {
105 sb << (unsigned int)optionIter->DefaultValue;
106 } else if (optionIter->DefaultValue.is_type<unsigned char>()) {
107 sb << (unsigned short)(unsigned char)optionIter->DefaultValue;
108 } else if (optionIter->DefaultValue.is_type<float>()) {
109 sb << std::fixed << std::setprecision(2) << (float)optionIter->DefaultValue;
110 } else if (optionIter->DefaultValue.is_type<double>()) {
111 sb << std::fixed << std::setprecision(4) << (double)optionIter->DefaultValue;
112 } else if (optionIter->DefaultValue.is_type<std::string>()) {
113 const std::string stringValue = optionIter->DefaultValue;
116 printf("ERROR: Found an unsupported data type for argument %s when casting the default value.\n",
117 optionIter->Argument.c_str());
122 description = sb.str();
125 if ( description.size() <= DESC_LENGTH_FIRST_ROW ) {
126 printf("%s\n", description.c_str());
129 // handle the first row
130 const char* pDescription = description.data();
131 unsigned int cutIndex = DESC_LENGTH_FIRST_ROW;
132 while(pDescription[cutIndex] != ' ')
134 printf("%s\n", description.substr(0, cutIndex).c_str());
135 description = description.substr(cutIndex + 1);
137 // handle subsequent rows
138 while(description.size() > DESC_LENGTH) {
139 pDescription = description.data();
140 cutIndex = DESC_LENGTH;
141 while(pDescription[cutIndex] != ' ')
143 printf("%s%s\n", indentBuffer, description.substr(0, cutIndex).c_str());
144 description = description.substr(cutIndex + 1);
148 printf("%s%s\n", indentBuffer, description.c_str());
156 printf(" --help, -h shows this help text\n");
160 // parses the command line
161 void Options::Parse(int argc, char* argv[], int offset) {
164 map<string, OptionValue>::const_iterator ovMapIter;
165 map<string, OptionValue>::const_iterator checkMapIter;
166 const int LAST_INDEX = argc - 1;
167 ostringstream errorBuilder;
168 bool foundError = false;
169 char* end_ptr = NULL;
170 const string ERROR_SPACER(7, ' ');
172 // check if we should show the help menu
173 bool showHelpMenu = false;
175 for (int i = 1; i < argc; i++) {
176 const std::string argument = argv[i];
177 if ( (argument == "-h") || (argument == "--help") || (argument == "help") )
180 } else showHelpMenu = true;
185 // check each argument
186 for (int i = offset+1; i < argc; i++) {
188 const string argument = argv[i];
189 ovMapIter = m_optionsMap.find(argument);
191 if (ovMapIter == m_optionsMap.end()) {
192 errorBuilder << ERROR_SPACER << "An unrecognized argument was found: " << argument << std::endl;
196 *ovMapIter->second.pFoundArgument = true;
199 if (ovMapIter->second.StoreValue) {
201 if (i < LAST_INDEX) {
203 // check if the next argument is really a command line option
204 const string val = argv[i + 1];
205 checkMapIter = m_optionsMap.find(val);
207 if (checkMapIter == m_optionsMap.end()) {
211 if (ovMapIter->second.VariantValue.is_type<unsigned int>()) {
212 const unsigned int uint32 = (unsigned int)strtoul(val.c_str(), &end_ptr, 10);
213 unsigned int* varValue = (unsigned int*)ovMapIter->second.pValue;
215 } else if (ovMapIter->second.VariantValue.is_type<unsigned char>()) {
216 const unsigned char uint8 = (unsigned char)strtoul(val.c_str(), &end_ptr, 10);
217 unsigned char* varValue = (unsigned char*)ovMapIter->second.pValue;
219 } else if (ovMapIter->second.VariantValue.is_type<uint64_t>()) {
220 const uint64_t uint64 = strtoui64(val.c_str(), &end_ptr, 10);
221 uint64_t* varValue = (uint64_t*)ovMapIter->second.pValue;
223 } else if (ovMapIter->second.VariantValue.is_type<double>()) {
224 const double d = strtod(val.c_str(), &end_ptr);
225 double* varValue = (double*)ovMapIter->second.pValue;
227 } else if (ovMapIter->second.VariantValue.is_type<float>()) {
228 const float f = (float)strtod(val.c_str(), &end_ptr);
229 float* varValue = (float*)ovMapIter->second.pValue;
231 } else if (ovMapIter->second.VariantValue.is_type<string>()) {
232 string* pStringValue = (string*)ovMapIter->second.pValue;
234 } else if (ovMapIter->second.VariantValue.is_type<vector<string> >()) {
235 vector<string>* pVectorValue = (vector<string>*)ovMapIter->second.pValue;
236 pVectorValue->push_back(val);
238 printf("ERROR: Found an unsupported data type for argument %s when parsing the arguments.\n",
243 errorBuilder << ERROR_SPACER << "The argument (" << argument
244 << ") expects a value, but none was found." << endl;
248 errorBuilder << ERROR_SPACER << "The argument (" << argument
249 << ") expects a value, but none was found." << endl;
256 // check if we missed any required parameters
257 for (ovMapIter = m_optionsMap.begin(); ovMapIter != m_optionsMap.end(); ++ovMapIter) {
258 if (ovMapIter->second.IsRequired && !*ovMapIter->second.pFoundArgument) {
259 errorBuilder << ERROR_SPACER << ovMapIter->second.ValueTypeDescription
260 << " was not specified. Please use the " << ovMapIter->first << " parameter." << endl;
265 // print the errors if any were found
267 printf("ERROR: Some problems were encountered when parsing the command line options:\n");
268 printf("%s\n", errorBuilder.str().c_str());
269 printf("For a complete list of command line options, type \"%s help %s\"\n", argv[0], argv[1]);
274 // sets the program info
275 void Options::SetProgramInfo(const string& programName,
276 const string& description,
277 const string& arguments)
279 m_programName = programName;
280 m_description = description;
281 m_exampleArguments = arguments;
284 // return string representations of stdin
285 const string& Options::StandardIn(void) { return m_stdin; }
287 // return string representations of stdout
288 const string& Options::StandardOut(void) { return m_stdout; }