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 <Message.hxx>
20 #include <ViewerTest.hxx>
29 //! Converts the given string to lowercase
30 //! @param theString the string to be converted
31 //! @return a converted string (a string in lowercase)
32 static std::string toLowerCase (std::string theString)
34 std::transform (theString.begin(), theString.end(), theString.begin(), ::LowerCase);
38 //! Converts the vector of std::strings to a vector of pointers to its data
39 //! @param theStringList the vector of strings to be converted
40 //! @return a vector of pointers to the data of given strings
41 static std::vector<const char*> convertToRawStringList (const std::vector<std::string>& theStringList)
43 const std::size_t aListSize = theStringList.size();
44 std::vector<const char*> aRawStringList (aListSize);
45 for (std::size_t anIndex = 0; anIndex < aListSize; ++anIndex)
47 aRawStringList[anIndex] = theStringList[anIndex].c_str();
49 return aRawStringList;
54 const std::size_t ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY = (std::numeric_limits<std::size_t>::max)();
56 const std::size_t ViewerTest_CmdParser::THE_HELP_COMMAND_OPTION_KEY = 0;
58 //===============================================================================================
59 // function : ViewerTest_CmdParser
61 //===============================================================================================
62 ViewerTest_CmdParser::ViewerTest_CmdParser (const std::string& theDescription) : myDescription (theDescription)
64 AddOption ("help|h", "Prints a short description of the command and its options.");
67 //===============================================================================================
68 // function : AddOption
70 //===============================================================================================
71 ViewerTest_CommandOptionKey ViewerTest_CmdParser::AddOption (const std::string& theOptionNames,
72 const std::string& theOptionDescription)
74 CommandOption aNewOption;
76 // extract option names
77 std::vector<std::string> aNames;
78 std::stringstream aStream (theOptionNames);
80 while (std::getline (aStream, anItem, '|'))
84 aNames.push_back (anItem);
88 aNewOption.Name = aNames.front();
89 if (aNames.size() > 1)
91 const std::size_t aNumberOfAliases = aNames.size() - 1;
93 aNewOption.Aliases.reserve (aNumberOfAliases);
94 std::copy (aNames.begin() + 1, aNames.end(), std::back_inserter (aNewOption.Aliases));
96 aNewOption.Description = theOptionDescription;
98 const ViewerTest_CommandOptionKey aNewOptionKey = myOptionStorage.size();
100 myOptionStorage.push_back (aNewOption);
102 std::vector<std::string>::const_iterator anIt = aNames.begin();
103 for (; anIt != aNames.end(); ++anIt)
105 const std::string aNameInLowerCase = toLowerCase (*anIt);
107 myOptionMap[aNameInLowerCase] = aNewOptionKey;
110 return aNewOptionKey;
113 //===============================================================================================
114 // function : PrintHelp
116 //===============================================================================================
117 void ViewerTest_CmdParser::PrintHelp() const
119 std::cout << myDescription << std::endl;
120 std::vector<CommandOption>::const_iterator anIt = myOptionStorage.begin();
121 for (++anIt; anIt != myOptionStorage.end(); ++anIt)
123 const CommandOption& aCommandOption = *anIt;
124 std::cout << "\n\t-" << aCommandOption.Name;
125 const OptionAliases& anAliases = aCommandOption.Aliases;
126 if (!anAliases.empty())
128 std::cout << " (-" << anAliases.front();
129 for (OptionAliases::const_iterator anAliasIterator = anAliases.begin() + 1; anAliasIterator != anAliases.end();
132 std::cout << ", -" << *anAliasIterator;
136 std::cout << " : " << aCommandOption.Description;
138 std::cout << std::endl;
141 //===============================================================================================
144 //===============================================================================================
145 void ViewerTest_CmdParser::Parse (const Standard_Integer theArgsNb, const char* const* const theArgVec)
147 std::size_t aCurrentUsedOptionIndex = 0;
148 for (Standard_Integer anIter = 1; anIter < theArgsNb; ++anIter)
150 const char* const anArgument = theArgVec[anIter];
151 if (anArgument[0] == '-' && !std::isdigit (anArgument[1]))
153 const std::string anOptionName = toLowerCase (anArgument + 1);
154 OptionMap::iterator aMapIter = myOptionMap.find (anOptionName);
155 if (aMapIter != myOptionMap.end())
157 const ViewerTest_CommandOptionKey aCurrentUsedOptionKey = aMapIter->second;
158 aCurrentUsedOptionIndex = addUsedOption (aCurrentUsedOptionKey);
162 Message::SendFail() << "Error: unknown argument '" << anOptionName << "'";
170 aCurrentUsedOptionIndex = addUsedOption (THE_UNNAMED_COMMAND_OPTION_KEY);
172 myOptionArgumentStorage[aCurrentUsedOptionIndex].push_back (anArgument);
177 //===============================================================================================
178 // function : GetOptionNameByKey
180 //===============================================================================================
181 std::string ViewerTest_CmdParser::GetOptionNameByKey (const ViewerTest_CommandOptionKey theOptionKey) const
183 if (theOptionKey == THE_UNNAMED_COMMAND_OPTION_KEY)
187 return myOptionStorage[theOptionKey].Name;
190 //===============================================================================================
191 // function : GetUsedOptions
193 //===============================================================================================
194 ViewerTest_CommandOptionKeySet ViewerTest_CmdParser::GetUsedOptions() const
196 ViewerTest_CommandOptionKeySet aUsedOptions;
197 for (UsedOptionMap::const_iterator aUsedOptionMapIterator = myUsedOptionMap.begin();
198 aUsedOptionMapIterator != myUsedOptionMap.end();
199 ++aUsedOptionMapIterator)
201 aUsedOptions.insert (aUsedOptionMapIterator->first);
206 //===============================================================================================
207 // function : HasNoOption
209 //===============================================================================================
210 bool ViewerTest_CmdParser::HasNoOption() const
212 return myUsedOptionMap.empty();
215 //===============================================================================================
216 // function : HasUnnamedOption
218 //===============================================================================================
219 bool ViewerTest_CmdParser::HasUnnamedOption() const
221 return myUsedOptionMap.find (THE_UNNAMED_COMMAND_OPTION_KEY) != myUsedOptionMap.end();
224 //===============================================================================================
225 // function : HasNoUnnamedOption
227 //===============================================================================================
228 bool ViewerTest_CmdParser::HasOnlyUnnamedOption() const
230 return HasUnnamedOption() && (myUsedOptionMap.size() == 1);
233 //===============================================================================================
234 // function : HasOption
236 //===============================================================================================
237 bool ViewerTest_CmdParser::HasOption (const std::string& theOptionName,
238 const std::size_t theMandatoryArgsNb /* = 0 */,
239 const bool isFatal /* = false */) const
241 ViewerTest_CommandOptionKey anOptionKey;
242 if (!findOptionKey (theOptionName, anOptionKey))
246 return HasOption (anOptionKey, theMandatoryArgsNb, isFatal);
249 //===============================================================================================
250 // function : HasOption
252 //===============================================================================================
253 bool ViewerTest_CmdParser::HasOption (const ViewerTest_CommandOptionKey theOptionKey,
254 const std::size_t theMandatoryArgsNb /* = 0 */,
255 const bool isFatal /* = false */) const
257 std::size_t aUsedOptionIndex = 0;
258 if (!findUsedOptionIndex (theOptionKey, aUsedOptionIndex))
262 const OptionArguments& anOptionArguments = myOptionArgumentStorage[aUsedOptionIndex];
263 const bool aResult = (anOptionArguments.size() >= theMandatoryArgsNb);
264 if (isFatal && !aResult)
266 Message::SendFail() << "Error: wrong syntax at option '" << myOptionStorage[theOptionKey].Name << "'\n"
267 << "At least " << theMandatoryArgsNb << "expected, but only " << anOptionArguments.size()
273 //===============================================================================================
274 // function : GetNumberOfOptionArguments
276 //===============================================================================================
277 Standard_Integer ViewerTest_CmdParser::GetNumberOfOptionArguments (const std::string& theOptionName) const
279 ViewerTest_CommandOptionKey anOptionKey = THE_UNNAMED_COMMAND_OPTION_KEY;
280 if (!findOptionKey (theOptionName, anOptionKey))
284 return GetNumberOfOptionArguments (anOptionKey);
287 //===============================================================================================
288 // function : GetNumberOfOptionArguments
290 //===============================================================================================
291 Standard_Integer ViewerTest_CmdParser::GetNumberOfOptionArguments (const ViewerTest_CommandOptionKey theOptionKey) const
293 std::size_t aUsedOptionIndex = 0;
294 if (!findUsedOptionIndex (theOptionKey, aUsedOptionIndex))
298 return static_cast<Standard_Integer> (myOptionArgumentStorage[aUsedOptionIndex].size());
301 //===============================================================================================
304 //===============================================================================================
305 bool ViewerTest_CmdParser::Arg (const std::string& theOptionName,
306 const Standard_Integer theArgumentIndex,
307 std::string& theOptionArgument) const
309 Standard_ASSERT_RETURN (theArgumentIndex >= 0,
310 "'theArgumentIndex' must be greater than or equal to zero.",
312 ViewerTest_CommandOptionKey anOptionKey = THE_UNNAMED_COMMAND_OPTION_KEY;
313 if (!theOptionName.empty() && !findOptionKey (theOptionName, anOptionKey))
317 return Arg (anOptionKey, theArgumentIndex, theOptionArgument);
320 //===============================================================================================
323 //===============================================================================================
324 bool ViewerTest_CmdParser::Arg (const ViewerTest_CommandOptionKey theOptionKey,
325 const Standard_Integer theArgumentIndex,
326 std::string& theOptionArgument) const
328 Standard_ASSERT_RETURN (theArgumentIndex >= 0,
329 "'theArgumentIndex' must be greater than or equal to zero.",
331 std::size_t aUsedOptionIndex = 0;
332 if (!findUsedOptionIndex (theOptionKey, aUsedOptionIndex))
336 const OptionArguments& anOptionArguments = myOptionArgumentStorage[aUsedOptionIndex];
337 if (static_cast<std::size_t> (theArgumentIndex) >= anOptionArguments.size())
341 theOptionArgument = anOptionArguments[theArgumentIndex];
345 //===============================================================================================
348 //===============================================================================================
349 std::string ViewerTest_CmdParser::Arg (const std::string& theOptionName, const Standard_Integer theArgumentIndex) const
351 Standard_ASSERT_RETURN (theArgumentIndex >= 0,
352 "'theArgumentIndex' must be greater than or equal to zero.",
354 std::string anOptionArgument;
355 if (!Arg (theOptionName, theArgumentIndex, anOptionArgument))
357 return std::string();
359 return anOptionArgument;
362 //===============================================================================================
365 //===============================================================================================
366 std::string ViewerTest_CmdParser::Arg (const ViewerTest_CommandOptionKey theOptionKey,
367 const Standard_Integer theArgumentIndex) const
369 std::string anOptionArgument;
370 if (!Arg (theOptionKey, theArgumentIndex, anOptionArgument))
372 return std::string();
374 return anOptionArgument;
377 //===============================================================================================
378 // function : ArgVec3f
380 //===============================================================================================
381 Graphic3d_Vec3 ViewerTest_CmdParser::ArgVec3f (const std::string& theOptionName,
382 Standard_Integer theArgumentIndex) const
384 return Graphic3d_Vec3 (
385 static_cast<Standard_ShortReal> (Draw::Atof (Arg (theOptionName, theArgumentIndex).c_str())),
386 static_cast<Standard_ShortReal> (Draw::Atof (Arg (theOptionName, theArgumentIndex + 1).c_str())),
387 static_cast<Standard_ShortReal> (Draw::Atof (Arg (theOptionName, theArgumentIndex + 2).c_str())));
390 //===============================================================================================
391 // function : ArgVec3d
393 //===============================================================================================
394 Graphic3d_Vec3d ViewerTest_CmdParser::ArgVec3d (const std::string& theOptionName,
395 Standard_Integer theArgumentIndex) const
397 return Graphic3d_Vec3d (Draw::Atof (Arg (theOptionName, theArgumentIndex).c_str()),
398 Draw::Atof (Arg (theOptionName, theArgumentIndex + 1).c_str()),
399 Draw::Atof (Arg (theOptionName, theArgumentIndex + 2).c_str()));
402 //===============================================================================================
405 //===============================================================================================
406 gp_Vec ViewerTest_CmdParser::ArgVec (const std::string& theOptionName, Standard_Integer theArgumentIndex) const
408 return gp_Vec (Draw::Atof (Arg (theOptionName, theArgumentIndex).c_str()),
409 Draw::Atof (Arg (theOptionName, theArgumentIndex + 1).c_str()),
410 Draw::Atof (Arg (theOptionName, theArgumentIndex + 2).c_str()));
413 //===============================================================================================
416 //===============================================================================================
417 gp_Pnt ViewerTest_CmdParser::ArgPnt (const std::string& theOptionName, Standard_Integer theArgumentIndex) const
419 return gp_Pnt (Draw::Atof (Arg (theOptionName, theArgumentIndex).c_str()),
420 Draw::Atof (Arg (theOptionName, theArgumentIndex + 1).c_str()),
421 Draw::Atof (Arg (theOptionName, theArgumentIndex + 2).c_str()));
424 //===============================================================================================
425 // function : ArgDouble
427 //===============================================================================================
428 Standard_Real ViewerTest_CmdParser::ArgDouble (const std::string& theOptionName,
429 Standard_Integer theArgumentIndex) const
431 return Draw::Atof (Arg (theOptionName, theArgumentIndex).c_str());
434 //===============================================================================================
435 // function : ArgFloat
437 //===============================================================================================
438 Standard_ShortReal ViewerTest_CmdParser::ArgFloat (const std::string& theOptionName,
439 Standard_Integer theArgumentIndex) const
441 return static_cast<Standard_ShortReal> (Draw::Atof (Arg (theOptionName, theArgumentIndex).c_str()));
444 //===============================================================================================
447 //===============================================================================================
448 Standard_Integer ViewerTest_CmdParser::ArgInt (const std::string& theOptionName,
449 const Standard_Integer theArgumentIndex) const
451 return static_cast<Standard_Integer> (Draw::Atoi (Arg (theOptionName, theArgumentIndex).c_str()));
454 //===============================================================================================
455 // function : ArgBool
457 //===============================================================================================
458 bool ViewerTest_CmdParser::ArgBool (const std::string& theOptionName, const Standard_Integer theArgumentIndex) const
460 return Draw::Atoi (Arg (theOptionName, theArgumentIndex).c_str()) != 0;
463 //===============================================================================================
464 // function : ArgColor
466 //===============================================================================================
467 template <typename TheColor>
468 bool ViewerTest_CmdParser::ArgColor (const std::string& theOptionName,
469 Standard_Integer& theArgumentIndex,
470 TheColor& theColor) const
472 ViewerTest_CommandOptionKey anOptionKey;
473 if (!findOptionKey (theOptionName, anOptionKey))
477 return ArgColor (anOptionKey, theArgumentIndex, theColor);
480 //! ViewerTest_CmdParser::ArgColor() explicit template instantiation definitions
481 template bool ViewerTest_CmdParser::ArgColor (const std::string& theOptionName,
482 Standard_Integer& theArgumentIndex,
483 Quantity_Color& theColor) const;
485 template bool ViewerTest_CmdParser::ArgColor (const std::string& theOptionName,
486 Standard_Integer& theArgumentIndex,
487 Quantity_ColorRGBA& theColor) const;
489 //===============================================================================================
490 // function : ArgColor
492 //===============================================================================================
493 template <typename TheColor>
494 bool ViewerTest_CmdParser::ArgColor (const ViewerTest_CommandOptionKey theOptionKey,
495 Standard_Integer& theArgumentIndex,
496 TheColor& theColor) const
498 std::size_t aUsedOptionIndex = 0;
499 if (!findUsedOptionIndex (theOptionKey, aUsedOptionIndex))
503 const RawStringArguments aRawStringArguments = getRawStringArguments (aUsedOptionIndex);
504 const Standard_Integer aNumberOfArguments = static_cast<Standard_Integer> (aRawStringArguments.size());
505 Standard_ASSERT_RETURN (theArgumentIndex < aNumberOfArguments,
506 "'theArgumentIndex' must be less than the number of command-line arguments "
507 "passed with the option which access key is 'theOptionKey'.",
509 const Standard_Integer aNumberOfAvailableArguments = aNumberOfArguments - theArgumentIndex;
511 const Standard_Integer aNumberOfParsedArguments = Draw::ParseColor (aNumberOfAvailableArguments,
512 &aRawStringArguments[theArgumentIndex],
514 if (aNumberOfParsedArguments == 0)
518 theArgumentIndex += aNumberOfParsedArguments;
523 //! ViewerTest_CmdParser::ArgColor() explicit template instantiation definitions
524 template bool ViewerTest_CmdParser::ArgColor (ViewerTest_CommandOptionKey theOptionKey,
525 Standard_Integer& theArgumentIndex,
526 Quantity_Color& theColor) const;
528 template bool ViewerTest_CmdParser::ArgColor (ViewerTest_CommandOptionKey theOptionKey,
529 Standard_Integer& theArgumentIndex,
530 Quantity_ColorRGBA& theColor) const;
532 //===============================================================================================
533 // function : findUsedOptionKey
535 //===============================================================================================
536 bool ViewerTest_CmdParser::findOptionKey (const std::string& theOptionName,
537 ViewerTest_CommandOptionKey& theOptionKey) const
539 const std::string anOptionNameInLowercase = toLowerCase (theOptionName);
540 const OptionMap::const_iterator aMapIter = myOptionMap.find (anOptionNameInLowercase);
541 if (aMapIter == myOptionMap.end())
545 theOptionKey = aMapIter->second;
549 //===============================================================================================
550 // function : findUsedOptionKey
552 //===============================================================================================
553 bool ViewerTest_CmdParser::findUsedOptionIndex (const ViewerTest_CommandOptionKey theOptionKey,
554 std::size_t& theUsedOptionIndex) const
556 const UsedOptionMap::const_iterator aUsedOptionIterator = myUsedOptionMap.find (theOptionKey);
557 if (aUsedOptionIterator == myUsedOptionMap.end())
561 theUsedOptionIndex = aUsedOptionIterator->second;
565 //===============================================================================================
566 // function : findUsedOptionIndex
568 //===============================================================================================
569 bool ViewerTest_CmdParser::findUsedOptionIndex (const std::string& theOptionName, std::size_t& theUsedOptionIndex) const
571 ViewerTest_CommandOptionKey anOptionKey = THE_UNNAMED_COMMAND_OPTION_KEY;
572 if (!findOptionKey (theOptionName, anOptionKey))
576 std::size_t aUsedOptionIndex = 0;
577 if (!findUsedOptionIndex (anOptionKey, aUsedOptionIndex))
581 theUsedOptionIndex = aUsedOptionIndex;
585 //===============================================================================================
586 // function : addUsedOption
588 //===============================================================================================
589 std::size_t ViewerTest_CmdParser::addUsedOption (const ViewerTest_CommandOptionKey theNewUsedOptionKey)
591 const std::size_t aNewUsedOptionIndex = myOptionArgumentStorage.size();
592 myOptionArgumentStorage.push_back (OptionArguments());
593 myUsedOptionMap[theNewUsedOptionKey] = aNewUsedOptionIndex;
594 return aNewUsedOptionIndex;
597 //===============================================================================================
598 // function : getRawStringArguments
600 //===============================================================================================
601 ViewerTest_CmdParser::RawStringArguments ViewerTest_CmdParser::getRawStringArguments (
602 const std::size_t theUsedOptionIndex) const
604 Standard_ASSERT_RETURN (
605 theUsedOptionIndex < myOptionArgumentStorage.size(),
606 "'theUsedOptionIndex' must be less than the size of 'myOptionArgumentStorage'.",
607 RawStringArguments());
608 const OptionArguments& anOptionArguments = myOptionArgumentStorage[theUsedOptionIndex];
609 return convertToRawStringList (anOptionArguments);