1 // Created on: 2015-03-15
2 // Created by: Danila ULYANOV
3 // Copyright (c) 2014 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 #include <ViewerTest_CmdParser.hxx>
19 #include <ViewerTest.hxx>
27 //! Converts the given string to lowercase
28 //! @param theString the string to be converted
29 //! @return a converted string (a string in lowercase)
30 static std::string toLowerCase (std::string theString)
32 std::transform (theString.begin(), theString.end(), theString.begin(), ::LowerCase);
36 //! Converts the vector of std::strings to a vector of pointers to its data
37 //! @param theStringList the vector of strings to be converted
38 //! @return a vector of pointers to the data of given strings
39 static std::vector<const char*> convertToRawStringList (const std::vector<std::string>& theStringList)
41 const std::size_t aListSize = theStringList.size();
42 std::vector<const char*> aRawStringList (aListSize);
43 for (std::size_t anIndex = 0; anIndex < aListSize; ++anIndex)
45 aRawStringList[anIndex] = theStringList[anIndex].c_str();
47 return aRawStringList;
52 const std::size_t ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY = (std::numeric_limits<std::size_t>::max)();
54 const std::size_t ViewerTest_CmdParser::THE_HELP_COMMAND_OPTION_KEY = 0;
56 //===============================================================================================
57 // function : ViewerTest_CmdParser
59 //===============================================================================================
60 ViewerTest_CmdParser::ViewerTest_CmdParser (const std::string& theDescription) : myDescription (theDescription)
62 AddOption ("help|h", "Prints a short description of the command and its options.");
65 //===============================================================================================
66 // function : AddOption
68 //===============================================================================================
69 ViewerTest_CommandOptionKey ViewerTest_CmdParser::AddOption (const std::string& theOptionNames,
70 const std::string& theOptionDescription)
72 CommandOption aNewOption;
74 // extract option names
75 std::vector<std::string> aNames;
76 std::stringstream aStream (theOptionNames);
78 while (std::getline (aStream, anItem, '|'))
82 aNames.push_back (anItem);
86 aNewOption.Name = aNames.front();
87 if (aNames.size() > 1)
89 const std::size_t aNumberOfAliases = aNames.size() - 1;
91 aNewOption.Aliases.reserve (aNumberOfAliases);
92 std::copy (aNames.begin() + 1, aNames.end(), std::back_inserter (aNewOption.Aliases));
94 aNewOption.Description = theOptionDescription;
96 const ViewerTest_CommandOptionKey aNewOptionKey = myOptionStorage.size();
98 myOptionStorage.push_back (aNewOption);
100 std::vector<std::string>::const_iterator anIt = aNames.begin();
101 for (; anIt != aNames.end(); ++anIt)
103 const std::string aNameInLowerCase = toLowerCase (*anIt);
105 myOptionMap[aNameInLowerCase] = aNewOptionKey;
108 return aNewOptionKey;
111 //===============================================================================================
112 // function : PrintHelp
114 //===============================================================================================
115 void ViewerTest_CmdParser::PrintHelp() const
117 std::cout << myDescription << std::endl;
118 std::vector<CommandOption>::const_iterator anIt = myOptionStorage.begin();
119 for (++anIt; anIt != myOptionStorage.end(); ++anIt)
121 const CommandOption& aCommandOption = *anIt;
122 std::cout << "\n\t-" << aCommandOption.Name;
123 const OptionAliases& anAliases = aCommandOption.Aliases;
124 if (!anAliases.empty())
126 std::cout << " (-" << anAliases.front();
127 for (OptionAliases::const_iterator anAliasIterator = anAliases.begin() + 1; anAliasIterator != anAliases.end();
130 std::cout << ", -" << *anAliasIterator;
134 std::cout << " : " << aCommandOption.Description;
136 std::cout << std::endl;
139 //===============================================================================================
142 //===============================================================================================
143 void ViewerTest_CmdParser::Parse (const Standard_Integer theArgsNb, const char* const* const theArgVec)
145 std::size_t aCurrentUsedOptionIndex = 0;
146 for (Standard_Integer anIter = 1; anIter < theArgsNb; ++anIter)
148 const char* const anArgument = theArgVec[anIter];
149 if (anArgument[0] == '-' && !std::isdigit (anArgument[1]))
151 const std::string anOptionName = toLowerCase (anArgument + 1);
152 OptionMap::iterator aMapIter = myOptionMap.find (anOptionName);
153 if (aMapIter != myOptionMap.end())
155 const ViewerTest_CommandOptionKey aCurrentUsedOptionKey = aMapIter->second;
156 aCurrentUsedOptionIndex = addUsedOption (aCurrentUsedOptionKey);
160 std::cerr << "Error: unknown argument '" << anOptionName << "'\n";
168 aCurrentUsedOptionIndex = addUsedOption (THE_UNNAMED_COMMAND_OPTION_KEY);
170 myOptionArgumentStorage[aCurrentUsedOptionIndex].push_back (anArgument);
175 //===============================================================================================
176 // function : GetOptionNameByKey
178 //===============================================================================================
179 std::string ViewerTest_CmdParser::GetOptionNameByKey (const ViewerTest_CommandOptionKey theOptionKey) const
181 if (theOptionKey == THE_UNNAMED_COMMAND_OPTION_KEY)
185 return myOptionStorage[theOptionKey].Name;
188 //===============================================================================================
189 // function : GetUsedOptions
191 //===============================================================================================
192 ViewerTest_CommandOptionKeySet ViewerTest_CmdParser::GetUsedOptions() const
194 ViewerTest_CommandOptionKeySet aUsedOptions;
195 for (UsedOptionMap::const_iterator aUsedOptionMapIterator = myUsedOptionMap.begin();
196 aUsedOptionMapIterator != myUsedOptionMap.end();
197 ++aUsedOptionMapIterator)
199 aUsedOptions.insert (aUsedOptionMapIterator->first);
204 //===============================================================================================
205 // function : HasNoOption
207 //===============================================================================================
208 bool ViewerTest_CmdParser::HasNoOption() const
210 return myUsedOptionMap.empty();
213 //===============================================================================================
214 // function : HasUnnamedOption
216 //===============================================================================================
217 bool ViewerTest_CmdParser::HasUnnamedOption() const
219 return myUsedOptionMap.find (THE_UNNAMED_COMMAND_OPTION_KEY) != myUsedOptionMap.end();
222 //===============================================================================================
223 // function : HasNoUnnamedOption
225 //===============================================================================================
226 bool ViewerTest_CmdParser::HasOnlyUnnamedOption() const
228 return HasUnnamedOption() && (myUsedOptionMap.size() == 1);
231 //===============================================================================================
232 // function : HasOption
234 //===============================================================================================
235 bool ViewerTest_CmdParser::HasOption (const std::string& theOptionName,
236 const std::size_t theMandatoryArgsNb /* = 0 */,
237 const bool isFatal /* = false */) const
239 ViewerTest_CommandOptionKey anOptionKey;
240 if (!findOptionKey (theOptionName, anOptionKey))
244 return HasOption (anOptionKey, theMandatoryArgsNb, isFatal);
247 //===============================================================================================
248 // function : HasOption
250 //===============================================================================================
251 bool ViewerTest_CmdParser::HasOption (const ViewerTest_CommandOptionKey theOptionKey,
252 const std::size_t theMandatoryArgsNb /* = 0 */,
253 const bool isFatal /* = false */) const
255 std::size_t aUsedOptionIndex = 0;
256 if (!findUsedOptionIndex (theOptionKey, aUsedOptionIndex))
260 const OptionArguments& anOptionArguments = myOptionArgumentStorage[aUsedOptionIndex];
261 const bool aResult = (anOptionArguments.size() >= theMandatoryArgsNb);
262 if (isFatal && !aResult)
264 std::cerr << "Error: wrong syntax at option '" << myOptionStorage[theOptionKey].Name << "'\n"
265 << "At least " << theMandatoryArgsNb << "expected, but only " << anOptionArguments.size()
271 //===============================================================================================
272 // function : GetNumberOfOptionArguments
274 //===============================================================================================
275 Standard_Integer ViewerTest_CmdParser::GetNumberOfOptionArguments (const std::string& theOptionName) const
277 ViewerTest_CommandOptionKey anOptionKey = THE_UNNAMED_COMMAND_OPTION_KEY;
278 if (!findOptionKey (theOptionName, anOptionKey))
282 return GetNumberOfOptionArguments (anOptionKey);
285 //===============================================================================================
286 // function : GetNumberOfOptionArguments
288 //===============================================================================================
289 Standard_Integer ViewerTest_CmdParser::GetNumberOfOptionArguments (const ViewerTest_CommandOptionKey theOptionKey) const
291 std::size_t aUsedOptionIndex = 0;
292 if (!findUsedOptionIndex (theOptionKey, aUsedOptionIndex))
296 return static_cast<Standard_Integer> (myOptionArgumentStorage[aUsedOptionIndex].size());
299 //===============================================================================================
302 //===============================================================================================
303 bool ViewerTest_CmdParser::Arg (const std::string& theOptionName,
304 const Standard_Integer theArgumentIndex,
305 std::string& theOptionArgument) const
307 Standard_ASSERT_RETURN (theArgumentIndex >= 0,
308 __FUNCTION__ ": 'theArgumentIndex' must be greater than or equal to zero.",
310 ViewerTest_CommandOptionKey anOptionKey = THE_UNNAMED_COMMAND_OPTION_KEY;
311 if (!theOptionName.empty() && !findOptionKey (theOptionName, anOptionKey))
315 return Arg (anOptionKey, theArgumentIndex, theOptionArgument);
318 //===============================================================================================
321 //===============================================================================================
322 bool ViewerTest_CmdParser::Arg (const ViewerTest_CommandOptionKey theOptionKey,
323 const Standard_Integer theArgumentIndex,
324 std::string& theOptionArgument) const
326 Standard_ASSERT_RETURN (theArgumentIndex >= 0,
327 __FUNCTION__ ": 'theArgumentIndex' must be greater than or equal to zero.",
329 std::size_t aUsedOptionIndex = 0;
330 if (!findUsedOptionIndex (theOptionKey, aUsedOptionIndex))
334 const OptionArguments& anOptionArguments = myOptionArgumentStorage[aUsedOptionIndex];
335 if (static_cast<std::size_t> (theArgumentIndex) >= anOptionArguments.size())
339 theOptionArgument = anOptionArguments[theArgumentIndex];
343 //===============================================================================================
346 //===============================================================================================
347 std::string ViewerTest_CmdParser::Arg (const std::string& theOptionName, const Standard_Integer theArgumentIndex) const
349 Standard_ASSERT_RETURN (theArgumentIndex >= 0,
350 __FUNCTION__ ": 'theArgumentIndex' must be greater than or equal to zero.",
352 std::string anOptionArgument;
353 if (!Arg (theOptionName, theArgumentIndex, anOptionArgument))
355 return std::string();
357 return anOptionArgument;
360 //===============================================================================================
363 //===============================================================================================
364 std::string ViewerTest_CmdParser::Arg (const ViewerTest_CommandOptionKey theOptionKey,
365 const Standard_Integer theArgumentIndex) const
367 std::string anOptionArgument;
368 if (!Arg (theOptionKey, theArgumentIndex, anOptionArgument))
370 return std::string();
372 return anOptionArgument;
375 //===============================================================================================
376 // function : ArgVec3f
378 //===============================================================================================
379 Graphic3d_Vec3 ViewerTest_CmdParser::ArgVec3f (const std::string& theOptionName,
380 Standard_Integer theArgumentIndex) const
382 return Graphic3d_Vec3 (
383 static_cast<Standard_ShortReal> (Draw::Atof (Arg (theOptionName, theArgumentIndex).c_str())),
384 static_cast<Standard_ShortReal> (Draw::Atof (Arg (theOptionName, theArgumentIndex + 1).c_str())),
385 static_cast<Standard_ShortReal> (Draw::Atof (Arg (theOptionName, theArgumentIndex + 2).c_str())));
388 //===============================================================================================
389 // function : ArgVec3d
391 //===============================================================================================
392 Graphic3d_Vec3d ViewerTest_CmdParser::ArgVec3d (const std::string& theOptionName,
393 Standard_Integer theArgumentIndex) const
395 return Graphic3d_Vec3d (Draw::Atof (Arg (theOptionName, theArgumentIndex).c_str()),
396 Draw::Atof (Arg (theOptionName, theArgumentIndex + 1).c_str()),
397 Draw::Atof (Arg (theOptionName, theArgumentIndex + 2).c_str()));
400 //===============================================================================================
403 //===============================================================================================
404 gp_Vec ViewerTest_CmdParser::ArgVec (const std::string& theOptionName, Standard_Integer theArgumentIndex) const
406 return gp_Vec (Draw::Atof (Arg (theOptionName, theArgumentIndex).c_str()),
407 Draw::Atof (Arg (theOptionName, theArgumentIndex + 1).c_str()),
408 Draw::Atof (Arg (theOptionName, theArgumentIndex + 2).c_str()));
411 //===============================================================================================
414 //===============================================================================================
415 gp_Pnt ViewerTest_CmdParser::ArgPnt (const std::string& theOptionName, Standard_Integer theArgumentIndex) const
417 return gp_Pnt (Draw::Atof (Arg (theOptionName, theArgumentIndex).c_str()),
418 Draw::Atof (Arg (theOptionName, theArgumentIndex + 1).c_str()),
419 Draw::Atof (Arg (theOptionName, theArgumentIndex + 2).c_str()));
422 //===============================================================================================
423 // function : ArgDouble
425 //===============================================================================================
426 Standard_Real ViewerTest_CmdParser::ArgDouble (const std::string& theOptionName,
427 Standard_Integer theArgumentIndex) const
429 return Draw::Atof (Arg (theOptionName, theArgumentIndex).c_str());
432 //===============================================================================================
433 // function : ArgFloat
435 //===============================================================================================
436 Standard_ShortReal ViewerTest_CmdParser::ArgFloat (const std::string& theOptionName,
437 Standard_Integer theArgumentIndex) const
439 return static_cast<Standard_ShortReal> (Draw::Atof (Arg (theOptionName, theArgumentIndex).c_str()));
442 //===============================================================================================
445 //===============================================================================================
446 Standard_Integer ViewerTest_CmdParser::ArgInt (const std::string& theOptionName,
447 const Standard_Integer theArgumentIndex) const
449 return static_cast<Standard_Integer> (Draw::Atoi (Arg (theOptionName, theArgumentIndex).c_str()));
452 //===============================================================================================
453 // function : ArgBool
455 //===============================================================================================
456 bool ViewerTest_CmdParser::ArgBool (const std::string& theOptionName, const Standard_Integer theArgumentIndex) const
458 return Draw::Atoi (Arg (theOptionName, theArgumentIndex).c_str()) != 0;
461 //===============================================================================================
462 // function : ArgColor
464 //===============================================================================================
465 template <typename TheColor>
466 bool ViewerTest_CmdParser::ArgColor (const std::string& theOptionName,
467 Standard_Integer& theArgumentIndex,
468 TheColor& theColor) const
470 ViewerTest_CommandOptionKey anOptionKey;
471 if (!findOptionKey (theOptionName, anOptionKey))
475 return ArgColor (anOptionKey, theArgumentIndex, theColor);
478 //! ViewerTest_CmdParser::ArgColor() explicit template instantiation definitions
479 template bool ViewerTest_CmdParser::ArgColor (const std::string& theOptionName,
480 Standard_Integer& theArgumentIndex,
481 Quantity_Color& theColor) const;
483 template bool ViewerTest_CmdParser::ArgColor (const std::string& theOptionName,
484 Standard_Integer& theArgumentIndex,
485 Quantity_ColorRGBA& theColor) const;
487 //===============================================================================================
488 // function : ArgColor
490 //===============================================================================================
491 template <typename TheColor>
492 bool ViewerTest_CmdParser::ArgColor (const ViewerTest_CommandOptionKey theOptionKey,
493 Standard_Integer& theArgumentIndex,
494 TheColor& theColor) const
496 std::size_t aUsedOptionIndex = 0;
497 if (!findUsedOptionIndex (theOptionKey, aUsedOptionIndex))
501 const RawStringArguments aRawStringArguments = getRawStringArguments (aUsedOptionIndex);
502 const Standard_Integer aNumberOfArguments = static_cast<Standard_Integer> (aRawStringArguments.size());
503 Standard_ASSERT_RETURN (theArgumentIndex < aNumberOfArguments,
504 __FUNCTION__ ": 'theArgumentIndex' must be less than the number of command-line arguments "
505 "passed with the option which access key is 'theOptionKey'.",
507 const Standard_Integer aNumberOfAvailableArguments = aNumberOfArguments - theArgumentIndex;
509 const Standard_Integer aNumberOfParsedArguments = ViewerTest::ParseColor (aNumberOfAvailableArguments,
510 &aRawStringArguments[theArgumentIndex],
512 if (aNumberOfParsedArguments == 0)
516 theArgumentIndex += aNumberOfParsedArguments;
521 //! ViewerTest_CmdParser::ArgColor() explicit template instantiation definitions
522 template bool ViewerTest_CmdParser::ArgColor (ViewerTest_CommandOptionKey theOptionKey,
523 Standard_Integer& theArgumentIndex,
524 Quantity_Color& theColor) const;
526 template bool ViewerTest_CmdParser::ArgColor (ViewerTest_CommandOptionKey theOptionKey,
527 Standard_Integer& theArgumentIndex,
528 Quantity_ColorRGBA& theColor) const;
530 //===============================================================================================
531 // function : findUsedOptionKey
533 //===============================================================================================
534 bool ViewerTest_CmdParser::findOptionKey (const std::string& theOptionName,
535 ViewerTest_CommandOptionKey& theOptionKey) const
537 const std::string anOptionNameInLowercase = toLowerCase (theOptionName);
538 const OptionMap::const_iterator aMapIter = myOptionMap.find (anOptionNameInLowercase);
539 if (aMapIter == myOptionMap.end())
543 theOptionKey = aMapIter->second;
547 //===============================================================================================
548 // function : findUsedOptionKey
550 //===============================================================================================
551 bool ViewerTest_CmdParser::findUsedOptionIndex (const ViewerTest_CommandOptionKey theOptionKey,
552 std::size_t& theUsedOptionIndex) const
554 const UsedOptionMap::const_iterator aUsedOptionIterator = myUsedOptionMap.find (theOptionKey);
555 if (aUsedOptionIterator == myUsedOptionMap.end())
559 theUsedOptionIndex = aUsedOptionIterator->second;
563 //===============================================================================================
564 // function : findUsedOptionIndex
566 //===============================================================================================
567 bool ViewerTest_CmdParser::findUsedOptionIndex (const std::string& theOptionName, std::size_t& theUsedOptionIndex) const
569 ViewerTest_CommandOptionKey anOptionKey = THE_UNNAMED_COMMAND_OPTION_KEY;
570 if (!findOptionKey (theOptionName, anOptionKey))
574 std::size_t aUsedOptionIndex = 0;
575 if (!findUsedOptionIndex (anOptionKey, aUsedOptionIndex))
579 theUsedOptionIndex = aUsedOptionIndex;
583 //===============================================================================================
584 // function : addUsedOption
586 //===============================================================================================
587 std::size_t ViewerTest_CmdParser::addUsedOption (const ViewerTest_CommandOptionKey theNewUsedOptionKey)
589 const std::size_t aNewUsedOptionIndex = myOptionArgumentStorage.size();
590 myOptionArgumentStorage.push_back (OptionArguments());
591 myUsedOptionMap[theNewUsedOptionKey] = aNewUsedOptionIndex;
592 return aNewUsedOptionIndex;
595 //===============================================================================================
596 // function : getRawStringArguments
598 //===============================================================================================
599 ViewerTest_CmdParser::RawStringArguments ViewerTest_CmdParser::getRawStringArguments (
600 const std::size_t theUsedOptionIndex) const
602 Standard_ASSERT_RETURN (
603 theUsedOptionIndex < myOptionArgumentStorage.size(),
604 __FUNCTION__ ": 'theUsedOptionIndex' must be less than the size of 'myOptionArgumentStorage'.",
605 RawStringArguments());
606 const OptionArguments& anOptionArguments = myOptionArgumentStorage[theUsedOptionIndex];
607 return convertToRawStringList (anOptionArguments);