0033661: Data Exchange, Step Import - Tessellated GDTs are not imported
[occt.git] / src / ViewerTest / ViewerTest_CmdParser.cxx
1 // Created on: 2015-03-15
2 // Created by: Danila ULYANOV
3 // Copyright (c) 2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
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.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #include <ViewerTest_CmdParser.hxx>
17
18 #include <Draw.hxx>
19 #include <Message.hxx>
20 #include <ViewerTest.hxx>
21
22 #include <algorithm>
23 #include <iostream>
24 #include <limits>
25
26 namespace
27 {
28
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)
33   {
34     std::transform (theString.begin(), theString.end(), theString.begin(), ::LowerCase);
35     return theString;
36   }
37
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)
42   {
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)
46     {
47       aRawStringList[anIndex] = theStringList[anIndex].c_str();
48     }
49     return aRawStringList;
50   }
51
52 } // namespace
53
54 const std::size_t ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY = (std::numeric_limits<std::size_t>::max)();
55
56 const std::size_t ViewerTest_CmdParser::THE_HELP_COMMAND_OPTION_KEY = 0;
57
58 //===============================================================================================
59 // function : ViewerTest_CmdParser
60 // purpose  :
61 //===============================================================================================
62 ViewerTest_CmdParser::ViewerTest_CmdParser (const std::string& theDescription) : myDescription (theDescription)
63 {
64   AddOption ("help|h", "Prints a short description of the command and its options.");
65 }
66
67 //===============================================================================================
68 // function : AddOption
69 // purpose  :
70 //===============================================================================================
71 ViewerTest_CommandOptionKey ViewerTest_CmdParser::AddOption (const std::string& theOptionNames,
72                                                              const std::string& theOptionDescription)
73 {
74   CommandOption aNewOption;
75
76   // extract option names
77   std::vector<std::string> aNames;
78   std::stringstream        aStream (theOptionNames);
79   std::string              anItem;
80   while (std::getline (aStream, anItem, '|'))
81   {
82     if (!anItem.empty())
83     {
84       aNames.push_back (anItem);
85     }
86   }
87
88   aNewOption.Name = aNames.front();
89   if (aNames.size() > 1)
90   {
91     const std::size_t aNumberOfAliases = aNames.size() - 1;
92
93     aNewOption.Aliases.reserve (aNumberOfAliases);
94     std::copy (aNames.begin() + 1, aNames.end(), std::back_inserter (aNewOption.Aliases));
95   }
96   aNewOption.Description = theOptionDescription;
97
98   const ViewerTest_CommandOptionKey aNewOptionKey = myOptionStorage.size();
99
100   myOptionStorage.push_back (aNewOption);
101
102   std::vector<std::string>::const_iterator anIt = aNames.begin();
103   for (; anIt != aNames.end(); ++anIt)
104   {
105     const std::string aNameInLowerCase = toLowerCase (*anIt);
106
107     myOptionMap[aNameInLowerCase] = aNewOptionKey;
108   }
109
110   return aNewOptionKey;
111 }
112
113 //===============================================================================================
114 // function : PrintHelp
115 // purpose  :
116 //===============================================================================================
117 void ViewerTest_CmdParser::PrintHelp() const
118 {
119   std::cout << myDescription << std::endl;
120   std::vector<CommandOption>::const_iterator anIt = myOptionStorage.begin();
121   for (++anIt; anIt != myOptionStorage.end(); ++anIt)
122   {
123     const CommandOption& aCommandOption = *anIt;
124     std::cout << "\n\t-" << aCommandOption.Name;
125     const OptionAliases& anAliases = aCommandOption.Aliases;
126     if (!anAliases.empty())
127     {
128       std::cout << " (-" << anAliases.front();
129       for (OptionAliases::const_iterator anAliasIterator = anAliases.begin() + 1; anAliasIterator != anAliases.end();
130            ++anAliasIterator)
131       {
132         std::cout << ", -" << *anAliasIterator;
133       }
134       std::cout << ")";
135     }
136     std::cout << " : " << aCommandOption.Description;
137   }
138   std::cout << std::endl;
139 }
140
141 //===============================================================================================
142 // function : Parse
143 // purpose  :
144 //===============================================================================================
145 void ViewerTest_CmdParser::Parse (const Standard_Integer theArgsNb, const char* const* const theArgVec)
146 {
147   std::size_t aCurrentUsedOptionIndex = 0;
148   for (Standard_Integer anIter = 1; anIter < theArgsNb; ++anIter)
149   {
150     const char* const anArgument = theArgVec[anIter];
151     if (anArgument[0] == '-' && !std::isdigit (anArgument[1]))
152     {
153       const std::string   anOptionName = toLowerCase (anArgument + 1);
154       OptionMap::iterator aMapIter     = myOptionMap.find (anOptionName);
155       if (aMapIter != myOptionMap.end())
156       {
157         const ViewerTest_CommandOptionKey aCurrentUsedOptionKey = aMapIter->second;
158         aCurrentUsedOptionIndex                                 = addUsedOption (aCurrentUsedOptionKey);
159       }
160       else
161       {
162         Message::SendFail() << "Error: unknown argument '" << anOptionName << "'";
163         return;
164       }
165     }
166     else
167     {
168       if (anIter == 1)
169       {
170         aCurrentUsedOptionIndex = addUsedOption (THE_UNNAMED_COMMAND_OPTION_KEY);
171       }
172       myOptionArgumentStorage[aCurrentUsedOptionIndex].push_back (anArgument);
173     }
174   }
175 }
176
177 //===============================================================================================
178 // function : GetOptionNameByKey
179 // purpose  :
180 //===============================================================================================
181 std::string ViewerTest_CmdParser::GetOptionNameByKey (const ViewerTest_CommandOptionKey theOptionKey) const
182 {
183   if (theOptionKey == THE_UNNAMED_COMMAND_OPTION_KEY)
184   {
185     return "Unnamed";
186   }
187   return myOptionStorage[theOptionKey].Name;
188 }
189
190 //===============================================================================================
191 // function : GetUsedOptions
192 // purpose  :
193 //===============================================================================================
194 ViewerTest_CommandOptionKeySet ViewerTest_CmdParser::GetUsedOptions() const
195 {
196   ViewerTest_CommandOptionKeySet aUsedOptions;
197   for (UsedOptionMap::const_iterator aUsedOptionMapIterator = myUsedOptionMap.begin();
198        aUsedOptionMapIterator != myUsedOptionMap.end();
199        ++aUsedOptionMapIterator)
200   {
201     aUsedOptions.insert (aUsedOptionMapIterator->first);
202   }
203   return aUsedOptions;
204 }
205
206 //===============================================================================================
207 // function : HasNoOption
208 // purpose  :
209 //===============================================================================================
210 bool ViewerTest_CmdParser::HasNoOption() const
211 {
212   return myUsedOptionMap.empty();
213 }
214
215 //===============================================================================================
216 // function : HasUnnamedOption
217 // purpose  :
218 //===============================================================================================
219 bool ViewerTest_CmdParser::HasUnnamedOption() const
220 {
221   return myUsedOptionMap.find (THE_UNNAMED_COMMAND_OPTION_KEY) != myUsedOptionMap.end();
222 }
223
224 //===============================================================================================
225 // function : HasNoUnnamedOption
226 // purpose  :
227 //===============================================================================================
228 bool ViewerTest_CmdParser::HasOnlyUnnamedOption() const
229 {
230   return HasUnnamedOption() && (myUsedOptionMap.size() == 1);
231 }
232
233 //===============================================================================================
234 // function : HasOption
235 // purpose  :
236 //===============================================================================================
237 bool ViewerTest_CmdParser::HasOption (const std::string& theOptionName,
238                                       const std::size_t  theMandatoryArgsNb /* = 0 */,
239                                       const bool         isFatal /* = false */) const
240 {
241   ViewerTest_CommandOptionKey anOptionKey;
242   if (!findOptionKey (theOptionName, anOptionKey))
243   {
244     return false;
245   }
246   return HasOption (anOptionKey, theMandatoryArgsNb, isFatal);
247 }
248
249 //===============================================================================================
250 // function : HasOption
251 // purpose  :
252 //===============================================================================================
253 bool ViewerTest_CmdParser::HasOption (const ViewerTest_CommandOptionKey theOptionKey,
254                                       const std::size_t                 theMandatoryArgsNb /* = 0 */,
255                                       const bool                        isFatal /* = false */) const
256 {
257   std::size_t aUsedOptionIndex = 0;
258   if (!findUsedOptionIndex (theOptionKey, aUsedOptionIndex))
259   {
260     return false;
261   }
262   const OptionArguments& anOptionArguments = myOptionArgumentStorage[aUsedOptionIndex];
263   const bool             aResult           = (anOptionArguments.size() >= theMandatoryArgsNb);
264   if (isFatal && !aResult)
265   {
266     Message::SendFail() << "Error: wrong syntax at option '" << myOptionStorage[theOptionKey].Name << "'\n"
267                         << "At least " << theMandatoryArgsNb << "expected, but only " << anOptionArguments.size()
268                         << "provided.";
269   }
270   return aResult;
271 }
272
273 //===============================================================================================
274 // function : GetNumberOfOptionArguments
275 // purpose  :
276 //===============================================================================================
277 Standard_Integer ViewerTest_CmdParser::GetNumberOfOptionArguments (const std::string& theOptionName) const
278 {
279   ViewerTest_CommandOptionKey anOptionKey = THE_UNNAMED_COMMAND_OPTION_KEY;
280   if (!findOptionKey (theOptionName, anOptionKey))
281   {
282     return 0;
283   }
284   return GetNumberOfOptionArguments (anOptionKey);
285 }
286
287 //===============================================================================================
288 // function : GetNumberOfOptionArguments
289 // purpose  :
290 //===============================================================================================
291 Standard_Integer ViewerTest_CmdParser::GetNumberOfOptionArguments (const ViewerTest_CommandOptionKey theOptionKey) const
292 {
293   std::size_t aUsedOptionIndex = 0;
294   if (!findUsedOptionIndex (theOptionKey, aUsedOptionIndex))
295   {
296     return false;
297   }
298   return static_cast<Standard_Integer> (myOptionArgumentStorage[aUsedOptionIndex].size());
299 }
300
301 //===============================================================================================
302 // function : Arg
303 // purpose  :
304 //===============================================================================================
305 bool ViewerTest_CmdParser::Arg (const std::string&     theOptionName,
306                                 const Standard_Integer theArgumentIndex,
307                                 std::string&           theOptionArgument) const
308 {
309   Standard_ASSERT_RETURN (theArgumentIndex >= 0,
310                           "'theArgumentIndex' must be greater than or equal to zero.",
311                           false);
312   ViewerTest_CommandOptionKey anOptionKey = THE_UNNAMED_COMMAND_OPTION_KEY;
313   if (!theOptionName.empty() && !findOptionKey (theOptionName, anOptionKey))
314   {
315     return false;
316   }
317   return Arg (anOptionKey, theArgumentIndex, theOptionArgument);
318 }
319
320 //===============================================================================================
321 // function : Arg
322 // purpose  :
323 //===============================================================================================
324 bool ViewerTest_CmdParser::Arg (const ViewerTest_CommandOptionKey theOptionKey,
325                                 const Standard_Integer            theArgumentIndex,
326                                 std::string&                      theOptionArgument) const
327 {
328   Standard_ASSERT_RETURN (theArgumentIndex >= 0,
329                           "'theArgumentIndex' must be greater than or equal to zero.",
330                           false);
331   std::size_t aUsedOptionIndex = 0;
332   if (!findUsedOptionIndex (theOptionKey, aUsedOptionIndex))
333   {
334     return false;
335   }
336   const OptionArguments& anOptionArguments = myOptionArgumentStorage[aUsedOptionIndex];
337   if (static_cast<std::size_t> (theArgumentIndex) >= anOptionArguments.size())
338   {
339     return false;
340   }
341   theOptionArgument = anOptionArguments[theArgumentIndex];
342   return true;
343 }
344
345 //===============================================================================================
346 // function : Arg
347 // purpose  :
348 //===============================================================================================
349 std::string ViewerTest_CmdParser::Arg (const std::string& theOptionName, const Standard_Integer theArgumentIndex) const
350 {
351   Standard_ASSERT_RETURN (theArgumentIndex >= 0,
352                           "'theArgumentIndex' must be greater than or equal to zero.",
353                           std::string());
354   std::string anOptionArgument;
355   if (!Arg (theOptionName, theArgumentIndex, anOptionArgument))
356   {
357     return std::string();
358   }
359   return anOptionArgument;
360 }
361
362 //===============================================================================================
363 // function : Arg
364 // purpose  :
365 //===============================================================================================
366 std::string ViewerTest_CmdParser::Arg (const ViewerTest_CommandOptionKey theOptionKey,
367                                        const Standard_Integer            theArgumentIndex) const
368 {
369   std::string anOptionArgument;
370   if (!Arg (theOptionKey, theArgumentIndex, anOptionArgument))
371   {
372     return std::string();
373   }
374   return anOptionArgument;
375 }
376
377 //===============================================================================================
378 // function : ArgVec3f
379 // purpose  :
380 //===============================================================================================
381 Graphic3d_Vec3 ViewerTest_CmdParser::ArgVec3f (const std::string& theOptionName,
382                                                Standard_Integer   theArgumentIndex) const
383 {
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())));
388 }
389
390 //===============================================================================================
391 // function : ArgVec3d
392 // purpose  :
393 //===============================================================================================
394 Graphic3d_Vec3d ViewerTest_CmdParser::ArgVec3d (const std::string& theOptionName,
395                                                 Standard_Integer   theArgumentIndex) const
396 {
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()));
400 }
401
402 //===============================================================================================
403 // function : ArgVec
404 // purpose  :
405 //===============================================================================================
406 gp_Vec ViewerTest_CmdParser::ArgVec (const std::string& theOptionName, Standard_Integer theArgumentIndex) const
407 {
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()));
411 }
412
413 //===============================================================================================
414 // function : ArgPnt
415 // purpose  :
416 //===============================================================================================
417 gp_Pnt ViewerTest_CmdParser::ArgPnt (const std::string& theOptionName, Standard_Integer theArgumentIndex) const
418 {
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()));
422 }
423
424 //===============================================================================================
425 // function : ArgDouble
426 // purpose  :
427 //===============================================================================================
428 Standard_Real ViewerTest_CmdParser::ArgDouble (const std::string& theOptionName,
429                                                Standard_Integer   theArgumentIndex) const
430 {
431   return Draw::Atof (Arg (theOptionName, theArgumentIndex).c_str());
432 }
433
434 //===============================================================================================
435 // function : ArgFloat
436 // purpose  :
437 //===============================================================================================
438 Standard_ShortReal ViewerTest_CmdParser::ArgFloat (const std::string& theOptionName,
439                                                    Standard_Integer   theArgumentIndex) const
440 {
441   return static_cast<Standard_ShortReal> (Draw::Atof (Arg (theOptionName, theArgumentIndex).c_str()));
442 }
443
444 //===============================================================================================
445 // function : ArgInt
446 // purpose  :
447 //===============================================================================================
448 Standard_Integer ViewerTest_CmdParser::ArgInt (const std::string&     theOptionName,
449                                                const Standard_Integer theArgumentIndex) const
450 {
451   return static_cast<Standard_Integer> (Draw::Atoi (Arg (theOptionName, theArgumentIndex).c_str()));
452 }
453
454 //===============================================================================================
455 // function : ArgBool
456 // purpose  :
457 //===============================================================================================
458 bool ViewerTest_CmdParser::ArgBool (const std::string& theOptionName, const Standard_Integer theArgumentIndex) const
459 {
460   return Draw::Atoi (Arg (theOptionName, theArgumentIndex).c_str()) != 0;
461 }
462
463 //===============================================================================================
464 // function : ArgColor
465 // purpose  :
466 //===============================================================================================
467 template <typename TheColor>
468 bool ViewerTest_CmdParser::ArgColor (const std::string& theOptionName,
469                                      Standard_Integer&  theArgumentIndex,
470                                      TheColor&          theColor) const
471 {
472   ViewerTest_CommandOptionKey anOptionKey;
473   if (!findOptionKey (theOptionName, anOptionKey))
474   {
475     return false;
476   }
477   return ArgColor (anOptionKey, theArgumentIndex, theColor);
478 }
479
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;
484
485 template bool ViewerTest_CmdParser::ArgColor (const std::string&  theOptionName,
486                                               Standard_Integer&   theArgumentIndex,
487                                               Quantity_ColorRGBA& theColor) const;
488
489 //===============================================================================================
490 // function : ArgColor
491 // purpose  :
492 //===============================================================================================
493 template <typename TheColor>
494 bool ViewerTest_CmdParser::ArgColor (const ViewerTest_CommandOptionKey theOptionKey,
495                                      Standard_Integer&                 theArgumentIndex,
496                                      TheColor&                         theColor) const
497 {
498   std::size_t aUsedOptionIndex = 0;
499   if (!findUsedOptionIndex (theOptionKey, aUsedOptionIndex))
500   {
501     return false;
502   }
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'.",
508                           false);
509   const Standard_Integer aNumberOfAvailableArguments = aNumberOfArguments - theArgumentIndex;
510   TheColor               aColor;
511   const Standard_Integer aNumberOfParsedArguments = Draw::ParseColor (aNumberOfAvailableArguments,
512                                                                       &aRawStringArguments[theArgumentIndex],
513                                                                       aColor);
514   if (aNumberOfParsedArguments == 0)
515   {
516     return false;
517   }
518   theArgumentIndex += aNumberOfParsedArguments;
519   theColor = aColor;
520   return true;
521 }
522
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;
527
528 template bool ViewerTest_CmdParser::ArgColor (ViewerTest_CommandOptionKey theOptionKey,
529                                               Standard_Integer&           theArgumentIndex,
530                                               Quantity_ColorRGBA&         theColor) const;
531
532 //===============================================================================================
533 // function : findUsedOptionKey
534 // purpose  :
535 //===============================================================================================
536 bool ViewerTest_CmdParser::findOptionKey (const std::string&           theOptionName,
537                                           ViewerTest_CommandOptionKey& theOptionKey) const
538 {
539   const std::string               anOptionNameInLowercase = toLowerCase (theOptionName);
540   const OptionMap::const_iterator aMapIter                = myOptionMap.find (anOptionNameInLowercase);
541   if (aMapIter == myOptionMap.end())
542   {
543     return false;
544   }
545   theOptionKey = aMapIter->second;
546   return true;
547 }
548
549 //===============================================================================================
550 // function : findUsedOptionKey
551 // purpose  :
552 //===============================================================================================
553 bool ViewerTest_CmdParser::findUsedOptionIndex (const ViewerTest_CommandOptionKey theOptionKey,
554                                                 std::size_t&                      theUsedOptionIndex) const
555 {
556   const UsedOptionMap::const_iterator aUsedOptionIterator = myUsedOptionMap.find (theOptionKey);
557   if (aUsedOptionIterator == myUsedOptionMap.end())
558   {
559     return false;
560   }
561   theUsedOptionIndex = aUsedOptionIterator->second;
562   return true;
563 }
564
565 //===============================================================================================
566 // function : findUsedOptionIndex
567 // purpose  :
568 //===============================================================================================
569 bool ViewerTest_CmdParser::findUsedOptionIndex (const std::string& theOptionName, std::size_t& theUsedOptionIndex) const
570 {
571   ViewerTest_CommandOptionKey anOptionKey = THE_UNNAMED_COMMAND_OPTION_KEY;
572   if (!findOptionKey (theOptionName, anOptionKey))
573   {
574     return false;
575   }
576   std::size_t aUsedOptionIndex = 0;
577   if (!findUsedOptionIndex (anOptionKey, aUsedOptionIndex))
578   {
579     return false;
580   }
581   theUsedOptionIndex = aUsedOptionIndex;
582   return true;
583 }
584
585 //===============================================================================================
586 // function : addUsedOption
587 // purpose  :
588 //===============================================================================================
589 std::size_t ViewerTest_CmdParser::addUsedOption (const ViewerTest_CommandOptionKey theNewUsedOptionKey)
590 {
591   const std::size_t aNewUsedOptionIndex = myOptionArgumentStorage.size();
592   myOptionArgumentStorage.push_back (OptionArguments());
593   myUsedOptionMap[theNewUsedOptionKey] = aNewUsedOptionIndex;
594   return aNewUsedOptionIndex;
595 }
596
597 //===============================================================================================
598 // function : getRawStringArguments
599 // purpose  :
600 //===============================================================================================
601 ViewerTest_CmdParser::RawStringArguments ViewerTest_CmdParser::getRawStringArguments (
602   const std::size_t theUsedOptionIndex) const
603 {
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);
610 }