options.cpp 7.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. #include "options.hpp"
  2. int Options::validateStringOption( int argc, char** argv, int argumentIndex ) {
  3. std::string argument = argv[argumentIndex];
  4. unsigned int index = 0;
  5. while( index < validArgumentCount ) {
  6. std::string& check = validStringArguments[index];
  7. for( unsigned int i=0;i<check.length();i++ ) {
  8. if ( check[i] != argument[i+2] ) {
  9. break;
  10. }
  11. if ( i == check.length()-1 ) {
  12. if ( !isFlagArgument[index] && argument.find("=") == std::string::npos ) {
  13. throw new std::invalid_argument("Expected `=` after " + arguments[i]);
  14. }
  15. if ( argument[i+3] != '=' ) {
  16. break;
  17. }
  18. return parseStringOption( argc, argv, argumentIndex, index );
  19. }
  20. }
  21. index++;
  22. }
  23. throw new std::invalid_argument("Invalid argument " + argument);
  24. return 0;
  25. }
  26. int Options::parseCharOption( int argc, char** argv, int argumentIndex, int validIndex ) {
  27. std::string argument = argv[argumentIndex];
  28. // If we're a flag, we take no arguments, nor do we allow = signs or whatever.
  29. if ( isFlagArgument[validIndex] ) {
  30. if ( argument != std::string()+"-"+validCharArguments[validIndex] ) {
  31. throw new std::invalid_argument( std::string()+"Unexpected characters around flag `" + argument + "`." );
  32. return 0;
  33. } else {
  34. arguments.push_back( std::string()+argument[1] );
  35. values.push_back("");
  36. return 1;
  37. }
  38. }
  39. arguments.push_back( std::string()+argument[1] );
  40. // If they supplied the parameters with spaces
  41. if ( argument == std::string()+"-"+validCharArguments[validIndex] ) {
  42. values.push_back(argv[argumentIndex+1]);
  43. return 2;
  44. }
  45. // If they didn't supply the parameters with spaces
  46. if ( argument[2] == '=' ) {
  47. values.push_back(argument.substr(3));
  48. return 1;
  49. }
  50. values.push_back(argument.substr(2));
  51. return 1;
  52. }
  53. int Options::parseStringOption( int argc, char** argv, int argumentIndex, int validIndex ) {
  54. std::string argument = argv[argumentIndex];
  55. if ( isFlagArgument[validIndex] ) {
  56. arguments.push_back( argument.substr(2) );
  57. values.push_back("");
  58. return 1;
  59. }
  60. arguments.push_back( argument.substr(2,argument.find_first_of('=')) );
  61. values.push_back(argument.substr(argument.find_first_of('=')));
  62. return 1;
  63. }
  64. int Options::validateCharOption( int argc, char** argv, int argumentIndex ) {
  65. std::string argument = argv[argumentIndex];
  66. unsigned int index = 0;
  67. while( index < validArgumentCount ) {
  68. char check = validCharArguments[index];
  69. if ( argument.length() < 2 ) {
  70. continue;
  71. }
  72. if ( check == argument[1] && ( argument.find("=") == 2 || argument.find('=') == std::string::npos ) && argument[0] == '-' ) {
  73. return parseCharOption( argc, argv, argumentIndex, index );
  74. }
  75. index++;
  76. }
  77. throw new std::invalid_argument("Invalid argument `" + argument + "`.");
  78. return 0;
  79. }
  80. void Options::validate( int argc, char** argv ) {
  81. for ( int i=1;i<argc;) {
  82. std::string argument = argv[i];
  83. if ( argument[0] != '-' ) {
  84. floatingValues.push_back( argument );
  85. if ( floatingValues.size() > maxFloatingValues ) {
  86. throw new std::invalid_argument("Unexpected floating value `" + argument + "`. Forget to specify an option?" );
  87. }
  88. }
  89. if ( argument[0] == '-' && argument[1] == '-' ) {
  90. i += validateStringOption( argc, argv, i );
  91. continue;
  92. }
  93. i += validateCharOption( argc, argv, i );
  94. }
  95. }
  96. Options::Options( int argc, char** argv ) {
  97. validate( argc, argv );
  98. }
  99. bool Options::getFloat( std::string name, char namec, float& found ) {
  100. for( unsigned int i=0;i<arguments.size();i++ ) {
  101. if ( arguments[i] == name || arguments[i] == std::string("")+namec ) {
  102. std::string::size_type sz;
  103. float retvar;
  104. try {
  105. retvar = std::stof(values[i],&sz);
  106. } catch ( ... ) {
  107. throw new std::invalid_argument("Unable to parse `" + arguments[i] + "`'s value `" + values[i] + "` as a float.");
  108. }
  109. if ( sz != values[i].length() ) {
  110. throw new std::invalid_argument("Unable to parse `" + arguments[i] + "`'s value `" + values[i] + "` as a float.");
  111. }
  112. found = retvar;
  113. return true;
  114. }
  115. }
  116. return false;
  117. }
  118. bool Options::getInt( std::string name, char namec, int& found ) {
  119. for( unsigned int i=0;i<arguments.size();i++ ) {
  120. if ( arguments[i] == name || arguments[i] == std::string("")+namec ) {
  121. if ( arguments[i].size() > 1 && arguments[i].find("=") == std::string::npos ) {
  122. throw new std::invalid_argument("Expected `=` after " + arguments[i]);
  123. }
  124. std::string::size_type sz;
  125. float retvar;
  126. try {
  127. retvar = std::stoi(values[i],&sz);
  128. } catch ( ... ) {
  129. throw new std::invalid_argument("Unable to parse " + arguments[i] + "'s value " + values[i] + " as an integer.");
  130. }
  131. if ( sz != values[i].length() ) {
  132. throw new std::invalid_argument("Unable to parse " + arguments[i] + "'s value " + values[i] + " as an integer.");
  133. }
  134. found = retvar;
  135. return true;
  136. }
  137. }
  138. return false;
  139. }
  140. bool Options::getString( std::string name, char namec, std::string& found ) {
  141. for( unsigned int i=0;i<arguments.size();i++ ) {
  142. if ( arguments[i] == name || arguments[i] == std::string("")+namec ) {
  143. found = values[i];
  144. return true;
  145. }
  146. }
  147. return false;
  148. }
  149. bool Options::getColor( std::string name, char namec, glm::vec4& found ) {
  150. for( unsigned int i=0;i<arguments.size();i++ ) {
  151. if ( arguments[i] == name || arguments[i] == std::string("")+namec ) {
  152. std::string::size_type sz;
  153. std::string value = values[i];
  154. try {
  155. found[0] = std::stof(value,&sz);
  156. value = value.substr(sz+1);
  157. found[1] = std::stof(value,&sz);
  158. value = value.substr(sz+1);
  159. found[2] = std::stof(value,&sz);
  160. if ( value.size() != sz ) {
  161. value = value.substr(sz+1);
  162. found[3] = std::stof(value,&sz);
  163. if ( value.size() != sz ) {
  164. throw "dur";
  165. }
  166. } else {
  167. found[3] = 1;
  168. }
  169. } catch ( ... ) {
  170. throw new std::invalid_argument("Unable to parse `" + arguments[i] + "`'s value `" + values[i] + "` as a color. Should be in the format r,g,b or r,g,b,a. Like 1,1,1,1.");
  171. }
  172. return true;
  173. }
  174. }
  175. return false;
  176. }
  177. bool Options::getBool( std::string name, char namec, bool& found ) {
  178. for( unsigned int i=0;i<arguments.size();i++ ) {
  179. if ( arguments[i] == name || arguments[i] == std::string("")+namec ) {
  180. if ( values[i] != "" ) {
  181. throw new std::invalid_argument("Unexpected value `" + values[i] + "` for flag argument `" + arguments[i] + "`.");
  182. }
  183. found = true;
  184. return true;
  185. }
  186. }
  187. return false;
  188. }