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>
28 //! Converts the given string to lowercase
29 //! @param theString the string to be converted
30 //! @return a converted string (a string in lowercase)
31 static std::string toLowerCase (std::string theString)
33 std::transform (theString.begin(), theString.end(), theString.begin(), ::LowerCase);
37 //! Converts the vector of std::strings to a vector of pointers to its data
38 //! @param theStringList the vector of strings to be converted
39 //! @return a vector of pointers to the data of given strings
40 static std::vector<const char*> convertToRawStringList (const std::vector<std::string>& theStringList)
42 const std::size_t aListSize = theStringList.size();
43 std::vector<const char*> aRawStringList (aListSize);
44 for (std::size_t anIndex = 0; anIndex < aListSize; ++anIndex)
46 aRawStringList[anIndex] = theStringList[anIndex].c_str();
48 return aRawStringList;
53 const std::size_t ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY = (std::numeric_limits<std::size_t>::max)();
55 const std::size_t ViewerTest_CmdParser::THE_HELP_COMMAND_OPTION_KEY = 0;
57 //===============================================================================================
58 // function : ViewerTest_CmdParser
60 //===============================================================================================
61 ViewerTest_CmdParser::ViewerTest_CmdParser (const std::string& theDescription) : myDescription (theDescription)
63 AddOption ("help|h", "Prints a short description of the command and its options.");
66 //===============================================================================================
67 // function : AddOption
69 //===============================================================================================
70 ViewerTest_CommandOptionKey ViewerTest_CmdParser::AddOption (const std::string& theOptionNames,
71 const std::string& theOptionDescription)
73 CommandOption aNewOption;
75 // extract option names
76 std::vector<std::string> aNames;
77 std::stringstream aStream (theOptionNames);
79 while (std::getline (aStream, anItem, '|'))
83 aNames.push_back (anItem);
87 aNewOption.Name = aNames.front();
88 if (aNames.size() > 1)
90 const std::size_t aNumberOfAliases = aNames.size() - 1;
92 aNewOption.Aliases.reserve (aNumberOfAliases);
93 std::copy (aNames.begin() + 1, aNames.end(), std::back_inserter (aNewOption.Aliases));
95 aNewOption.Description = theOptionDescription;
97 const ViewerTest_CommandOptionKey aNewOptionKey = myOptionStorage.size();
99 myOptionStorage.push_back (aNewOption);
101 std::vector<std::string>::const_iterator anIt = aNames.begin();
102 for (; anIt != aNames.end(); ++anIt)
104 const std::string aNameInLowerCase = toLowerCase (*anIt);
106 myOptionMap[aNameInLowerCase] = aNewOptionKey;
109 return aNewOptionKey;
112 //===============================================================================================
113 // function : PrintHelp
115 //===============================================================================================
116 void ViewerTest_CmdParser::PrintHelp() const
118 std::cout << myDescription << std::endl;
119 std::vector<CommandOption>::const_iterator anIt = myOptionStorage.begin();
120 for (++anIt; anIt != myOptionStorage.end(); ++anIt)
122 const CommandOption& aCommandOption = *anIt;
123 std::cout << "\n\t-" << aCommandOption.Name;
124 const OptionAliases& anAliases = aCommandOption.Aliases;
125 if (!anAliases.empty())
127 std::cout << " (-" << anAliases.front();
128 for (OptionAliases::const_iterator anAliasIterator = anAliases.begin() + 1; anAliasIterator != anAliases.end();
131 std::cout << ", -" << *anAliasIterator;
135 std::cout << " : " << aCommandOption.Description;
137 std::cout << std::endl;
140 //===============================================================================================
143 //===============================================================================================
144 void ViewerTest_CmdParser::Parse (const Standard_Integer theArgsNb, const char* const* const theArgVec)
146 std::size_t aCurrentUsedOptionIndex = 0;
147 for (Standard_Integer anIter = 1; anIter < theArgsNb; ++anIter)
149 const char* const anArgument = theArgVec[anIter];
150 if (anArgument[0] == '-' && !std::isdigit (anArgument[1]))
152 const std::string anOptionName = toLowerCase (anArgument + 1);
153 OptionMap::iterator aMapIter = myOptionMap.find (anOptionName);
154 if (aMapIter != myOptionMap.end())
156 const ViewerTest_CommandOptionKey aCurrentUsedOptionKey = aMapIter->second;
157 aCurrentUsedOptionIndex = addUsedOption (aCurrentUsedOptionKey);
161 Message::SendFail() << "Error: unknown argument '" << anOptionName << "'";
169 aCurrentUsedOptionIndex = addUsedOption (THE_UNNAMED_COMMAND_OPTION_KEY);
171 myOptionArgumentStorage[aCurrentUsedOptionIndex].push_back (anArgument);
176 //===============================================================================================
177 // function : GetOptionNameByKey
179 //===============================================================================================
180 std::string ViewerTest_CmdParser::GetOptionNameByKey (const ViewerTest_CommandOptionKey theOptionKey) const
182 if (theOptionKey == THE_UNNAMED_COMMAND_OPTION_KEY)
186 return myOptionStorage[theOptionKey].Name;
189 //===============================================================================================
190 // function : GetUsedOptions
192 //===============================================================================================
193 ViewerTest_CommandOptionKeySet ViewerTest_CmdParser::GetUsedOptions() const
195 ViewerTest_CommandOptionKeySet aUsedOptions;
196 for (UsedOptionMap::const_iterator aUsedOptionMapIterator = myUsedOptionMap.begin();
197 aUsedOptionMapIterator != myUsedOptionMap.end();
198 ++aUsedOptionMapIterator)
200 aUsedOptions.insert (aUsedOptionMapIterator->first);
205 //===============================================================================================
206 // function : HasNoOption
208 //===============================================================================================
209 bool ViewerTest_CmdParser::HasNoOption() const
211 return myUsedOptionMap.empty();
214 //===============================================================================================
215 // function : HasUnnamedOption
217 //===============================================================================================
218 bool ViewerTest_CmdParser::HasUnnamedOption() const
220 return myUsedOptionMap.find (THE_UNNAMED_COMMAND_OPTION_KEY) != myUsedOptionMap.end();
223 //===============================================================================================
224 // function : HasNoUnnamedOption
226 //===============================================================================================
227 bool ViewerTest_CmdParser::HasOnlyUnnamedOption() const
229 return HasUnnamedOption() && (myUsedOptionMap.size() == 1);
232 //===============================================================================================
233 // function : HasOption
235 //===============================================================================================
236 bool ViewerTest_CmdParser::HasOption (const std::string& theOptionName,
237 const std::size_t theMandatoryArgsNb /* = 0 */,
238 const bool isFatal /* = false */) const
240 ViewerTest_CommandOptionKey anOptionKey;
241 if (!findOptionKey (theOptionName, anOptionKey))
245 return HasOption (anOptionKey, theMandatoryArgsNb, isFatal);
248 //===============================================================================================
249 // function : HasOption
251 //===============================================================================================
252 bool ViewerTest_CmdParser::HasOption (const ViewerTest_CommandOptionKey theOptionKey,
253 const std::size_t theMandatoryArgsNb /* = 0 */,
254 const bool isFatal /* = false */) const
256 std::size_t aUsedOptionIndex = 0;
257 if (!findUsedOptionIndex (theOptionKey, aUsedOptionIndex))
261 const OptionArguments& anOptionArguments = myOptionArgumentStorage[aUsedOptionIndex];
262 const bool aResult = (anOptionArguments.size() >= theMandatoryArgsNb);
263 if (isFatal && !aResult)
265 Message::SendFail() << "Error: wrong syntax at option '" << myOptionStorage[theOptionKey].Name << "'\n"
266 << "At least " << theMandatoryArgsNb << "expected, but only " << anOptionArguments.size()
272 //===============================================================================================
273 // function : GetNumberOfOptionArguments
275 //===============================================================================================
276 Standard_Integer ViewerTest_CmdParser::GetNumberOfOptionArguments (const std::string& theOptionName) const
278 ViewerTest_CommandOptionKey anOptionKey = THE_UNNAMED_COMMAND_OPTION_KEY;
279 if (!findOptionKey (theOptionName, anOptionKey))
283 return GetNumberOfOptionArguments (anOptionKey);
286 //===============================================================================================
287 // function : GetNumberOfOptionArguments
289 //===============================================================================================
290 Standard_Integer ViewerTest_CmdParser::GetNumberOfOptionArguments (const ViewerTest_CommandOptionKey theOptionKey) const
292 std::size_t aUsedOptionIndex = 0;
293 if (!findUsedOptionIndex (theOptionKey, aUsedOptionIndex))
297 return static_cast<Standard_Integer> (myOptionArgumentStorage[aUsedOptionIndex].size());
300 //===============================================================================================
303 //===============================================================================================
304 bool ViewerTest_CmdParser::Arg (const std::string& theOptionName,
305 const Standard_Integer theArgumentIndex,
306 std::string& theOptionArgument) const
308 Standard_ASSERT_RETURN (theArgumentIndex >= 0,
309 "'theArgumentIndex' must be greater than or equal to zero.",
311 ViewerTest_CommandOptionKey anOptionKey = THE_UNNAMED_COMMAND_OPTION_KEY;
312 if (!theOptionName.empty() && !findOptionKey (theOptionName, anOptionKey))
316 return Arg (anOptionKey, theArgumentIndex, theOptionArgument);
319 //===============================================================================================
322 //===============================================================================================
323 bool ViewerTest_CmdParser::Arg (const ViewerTest_CommandOptionKey theOptionKey,
324 const Standard_Integer theArgumentIndex,
325 std::string& theOptionArgument) const
327 Standard_ASSERT_RETURN (theArgumentIndex >= 0,
328 "'theArgumentIndex' must be greater than or equal to zero.",
330 std::size_t aUsedOptionIndex = 0;
331 if (!findUsedOptionIndex (theOptionKey, aUsedOptionIndex))
335 const OptionArguments& anOptionArguments = myOptionArgumentStorage[aUsedOptionIndex];
336 if (static_cast<std::size_t> (theArgumentIndex) >= anOptionArguments.size())
340 theOptionArgument = anOptionArguments[theArgumentIndex];
344 //===============================================================================================
347 //===============================================================================================
348 std::string ViewerTest_CmdParser::Arg (const std::string& theOptionName, const Standard_Integer theArgumentIndex) const
350 Standard_ASSERT_RETURN (theArgumentIndex >= 0,
351 "'theArgumentIndex' must be greater than or equal to zero.",
353 std::string anOptionArgument;
354 if (!Arg (theOptionName, theArgumentIndex, anOptionArgument))
356 return std::string();
358 return anOptionArgument;
361 //===============================================================================================
364 //===============================================================================================
365 std::string ViewerTest_CmdParser::Arg (const ViewerTest_CommandOptionKey theOptionKey,
366 const Standard_Integer theArgumentIndex) const
368 std::string anOptionArgument;
369 if (!Arg (theOptionKey, theArgumentIndex, anOptionArgument))
371 return std::string();
373 return anOptionArgument;
376 //===============================================================================================
377 // function : ArgVec3f
379 //===============================================================================================
380 Graphic3d_Vec3 ViewerTest_CmdParser::ArgVec3f (const std::string& theOptionName,
381 Standard_Integer theArgumentIndex) const
383 return Graphic3d_Vec3 (
384 static_cast<Standard_ShortReal> (Draw::Atof (Arg (theOptionName, theArgumentIndex).c_str())),
385 static_cast<Standard_ShortReal> (Draw::Atof (Arg (theOptionName, theArgumentIndex + 1).c_str())),
386 static_cast<Standard_ShortReal> (Draw::Atof (Arg (theOptionName, theArgumentIndex + 2).c_str())));
389 //===============================================================================================
390 // function : ArgVec3d
392 //===============================================================================================
393 Graphic3d_Vec3d ViewerTest_CmdParser::ArgVec3d (const std::string& theOptionName,
394 Standard_Integer theArgumentIndex) const
396 return Graphic3d_Vec3d (Draw::Atof (Arg (theOptionName, theArgumentIndex).c_str()),
397 Draw::Atof (Arg (theOptionName, theArgumentIndex + 1).c_str()),
398 Draw::Atof (Arg (theOptionName, theArgumentIndex + 2).c_str()));
401 //===============================================================================================
404 //===============================================================================================
405 gp_Vec ViewerTest_CmdParser::ArgVec (const std::string& theOptionName, Standard_Integer theArgumentIndex) const
407 return gp_Vec (Draw::Atof (Arg (theOptionName, theArgumentIndex).c_str()),
408 Draw::Atof (Arg (theOptionName, theArgumentIndex + 1).c_str()),
409 Draw::Atof (Arg (theOptionName, theArgumentIndex + 2).c_str()));
412 //===============================================================================================
415 //===============================================================================================
416 gp_Pnt ViewerTest_CmdParser::ArgPnt (const std::string& theOptionName, Standard_Integer theArgumentIndex) const
418 return gp_Pnt (Draw::Atof (Arg (theOptionName, theArgumentIndex).c_str()),
419 Draw::Atof (Arg (theOptionName, theArgumentIndex + 1).c_str()),
420 Draw::Atof (Arg (theOptionName, theArgumentIndex + 2).c_str()));
423 //===============================================================================================
424 // function : ArgDouble
426 //===============================================================================================
427 Standard_Real ViewerTest_CmdParser::ArgDouble (const std::string& theOptionName,
428 Standard_Integer theArgumentIndex) const
430 return Draw::Atof (Arg (theOptionName, theArgumentIndex).c_str());
433 //===============================================================================================
434 // function : ArgFloat
436 //===============================================================================================
437 Standard_ShortReal ViewerTest_CmdParser::ArgFloat (const std::string& theOptionName,
438 Standard_Integer theArgumentIndex) const
440 return static_cast<Standard_ShortReal> (Draw::Atof (Arg (theOptionName, theArgumentIndex).c_str()));
443 //===============================================================================================
446 //===============================================================================================
447 Standard_Integer ViewerTest_CmdParser::ArgInt (const std::string& theOptionName,
448 const Standard_Integer theArgumentIndex) const
450 return static_cast<Standard_Integer> (Draw::Atoi (Arg (theOptionName, theArgumentIndex).c_str()));
453 //===============================================================================================
454 // function : ArgBool
456 //===============================================================================================
457 bool ViewerTest_CmdParser::ArgBool (const std::string& theOptionName, const Standard_Integer theArgumentIndex) const
459 return Draw::Atoi (Arg (theOptionName, theArgumentIndex).c_str()) != 0;
462 //===============================================================================================
463 // function : ArgColor
465 //===============================================================================================
466 template <typename TheColor>
467 bool ViewerTest_CmdParser::ArgColor (const std::string& theOptionName,
468 Standard_Integer& theArgumentIndex,
469 TheColor& theColor) const
471 ViewerTest_CommandOptionKey anOptionKey;
472 if (!findOptionKey (theOptionName, anOptionKey))
476 return ArgColor (anOptionKey, theArgumentIndex, theColor);
479 //! ViewerTest_CmdParser::ArgColor() explicit template instantiation definitions
480 template bool ViewerTest_CmdParser::ArgColor (const std::string& theOptionName,
481 Standard_Integer& theArgumentIndex,
482 Quantity_Color& theColor) const;
484 template bool ViewerTest_CmdParser::ArgColor (const std::string& theOptionName,
485 Standard_Integer& theArgumentIndex,
486 Quantity_ColorRGBA& theColor) const;
488 //===============================================================================================
489 // function : ArgColor
491 //===============================================================================================
492 template <typename TheColor>
493 bool ViewerTest_CmdParser::ArgColor (const ViewerTest_CommandOptionKey theOptionKey,
494 Standard_Integer& theArgumentIndex,
495 TheColor& theColor) const
497 std::size_t aUsedOptionIndex = 0;
498 if (!findUsedOptionIndex (theOptionKey, aUsedOptionIndex))
502 const RawStringArguments aRawStringArguments = getRawStringArguments (aUsedOptionIndex);
503 const Standard_Integer aNumberOfArguments = static_cast<Standard_Integer> (aRawStringArguments.size());
504 Standard_ASSERT_RETURN (theArgumentIndex < aNumberOfArguments,
505 "'theArgumentIndex' must be less than the number of command-line arguments "
506 "passed with the option which access key is 'theOptionKey'.",
508 const Standard_Integer aNumberOfAvailableArguments = aNumberOfArguments - theArgumentIndex;
510 const Standard_Integer aNumberOfParsedArguments = Draw::ParseColor (aNumberOfAvailableArguments,
511 &aRawStringArguments[theArgumentIndex],
513 if (aNumberOfParsedArguments == 0)
517 theArgumentIndex += aNumberOfParsedArguments;
522 //! ViewerTest_CmdParser::ArgColor() explicit template instantiation definitions
523 template bool ViewerTest_CmdParser::ArgColor (ViewerTest_CommandOptionKey theOptionKey,
524 Standard_Integer& theArgumentIndex,
525 Quantity_Color& theColor) const;
527 template bool ViewerTest_CmdParser::ArgColor (ViewerTest_CommandOptionKey theOptionKey,
528 Standard_Integer& theArgumentIndex,
529 Quantity_ColorRGBA& theColor) const;
531 //===============================================================================================
532 // function : findUsedOptionKey
534 //===============================================================================================
535 bool ViewerTest_CmdParser::findOptionKey (const std::string& theOptionName,
536 ViewerTest_CommandOptionKey& theOptionKey) const
538 const std::string anOptionNameInLowercase = toLowerCase (theOptionName);
539 const OptionMap::const_iterator aMapIter = myOptionMap.find (anOptionNameInLowercase);
540 if (aMapIter == myOptionMap.end())
544 theOptionKey = aMapIter->second;
548 //===============================================================================================
549 // function : findUsedOptionKey
551 //===============================================================================================
552 bool ViewerTest_CmdParser::findUsedOptionIndex (const ViewerTest_CommandOptionKey theOptionKey,
553 std::size_t& theUsedOptionIndex) const
555 const UsedOptionMap::const_iterator aUsedOptionIterator = myUsedOptionMap.find (theOptionKey);
556 if (aUsedOptionIterator == myUsedOptionMap.end())
560 theUsedOptionIndex = aUsedOptionIterator->second;
564 //===============================================================================================
565 // function : findUsedOptionIndex
567 //===============================================================================================
568 bool ViewerTest_CmdParser::findUsedOptionIndex (const std::string& theOptionName, std::size_t& theUsedOptionIndex) const
570 ViewerTest_CommandOptionKey anOptionKey = THE_UNNAMED_COMMAND_OPTION_KEY;
571 if (!findOptionKey (theOptionName, anOptionKey))
575 std::size_t aUsedOptionIndex = 0;
576 if (!findUsedOptionIndex (anOptionKey, aUsedOptionIndex))
580 theUsedOptionIndex = aUsedOptionIndex;
584 //===============================================================================================
585 // function : addUsedOption
587 //===============================================================================================
588 std::size_t ViewerTest_CmdParser::addUsedOption (const ViewerTest_CommandOptionKey theNewUsedOptionKey)
590 const std::size_t aNewUsedOptionIndex = myOptionArgumentStorage.size();
591 myOptionArgumentStorage.push_back (OptionArguments());
592 myUsedOptionMap[theNewUsedOptionKey] = aNewUsedOptionIndex;
593 return aNewUsedOptionIndex;
596 //===============================================================================================
597 // function : getRawStringArguments
599 //===============================================================================================
600 ViewerTest_CmdParser::RawStringArguments ViewerTest_CmdParser::getRawStringArguments (
601 const std::size_t theUsedOptionIndex) const
603 Standard_ASSERT_RETURN (
604 theUsedOptionIndex < myOptionArgumentStorage.size(),
605 "'theUsedOptionIndex' must be less than the size of 'myOptionArgumentStorage'.",
606 RawStringArguments());
607 const OptionArguments& anOptionArguments = myOptionArgumentStorage[theUsedOptionIndex];
608 return convertToRawStringList (anOptionArguments);