options.cpp 8.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  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 ( isFlagArgument[index] && i+3 != argument.length() ) {
  16. throw new std::invalid_argument("Trailing characters on flag " + argument );
  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. for( int o=1;o<argument.length();o++ ) {
  32. bool isValid = false;
  33. for( int i=0;i<validArgumentCount&&!isValid;i++ ) {
  34. if ( argument[o] == validCharArguments[i] ) {
  35. if ( isFlagArgument[i] ) {
  36. isValid = true;
  37. arguments.push_back( std::string()+validCharArguments[i] );
  38. values.push_back("");
  39. break;
  40. } else {
  41. throw new std::invalid_argument( std::string()+"Truncating non-flag arguments is not allowed. Split this up: `" + argument + "`." );
  42. }
  43. }
  44. }
  45. if (!isValid) {
  46. throw new std::invalid_argument( std::string()+"Unexpected characters around flag `" + argument + "`." );
  47. }
  48. }
  49. return 1;
  50. } else {
  51. arguments.push_back( std::string()+argument[1] );
  52. values.push_back("");
  53. return 1;
  54. }
  55. }
  56. arguments.push_back( std::string()+argument[1] );
  57. // If they supplied the parameters with spaces
  58. if ( argument == std::string()+"-"+validCharArguments[validIndex] ) {
  59. values.push_back(argv[argumentIndex+1]);
  60. return 2;
  61. }
  62. // If they didn't supply the parameters with spaces
  63. if ( argument[2] == '=' ) {
  64. values.push_back(argument.substr(3));
  65. return 1;
  66. }
  67. values.push_back(argument.substr(2));
  68. return 1;
  69. }
  70. int Options::parseStringOption( int argc, char** argv, int argumentIndex, int validIndex ) {
  71. std::string argument = argv[argumentIndex];
  72. if ( isFlagArgument[validIndex] ) {
  73. arguments.push_back( argument.substr(2) );
  74. values.push_back("");
  75. return 1;
  76. }
  77. arguments.push_back( argument.substr(2,argument.find_first_of('=')) );
  78. values.push_back(argument.substr(argument.find_first_of('=')));
  79. return 1;
  80. }
  81. int Options::validateCharOption( int argc, char** argv, int argumentIndex ) {
  82. std::string argument = argv[argumentIndex];
  83. unsigned int index = 0;
  84. while( index < validArgumentCount ) {
  85. char check = validCharArguments[index];
  86. if ( argument.length() < 2 ) {
  87. continue;
  88. }
  89. if ( check == argument[1] && ( argument.find("=") == 2 || argument.find('=') == std::string::npos ) && argument[0] == '-' ) {
  90. return parseCharOption( argc, argv, argumentIndex, index );
  91. }
  92. index++;
  93. }
  94. throw new std::invalid_argument("Invalid argument `" + argument + "`.");
  95. return 0;
  96. }
  97. void Options::validate( int argc, char** argv ) {
  98. for ( int i=1;i<argc;) {
  99. std::string argument = argv[i];
  100. if ( argument[0] != '-' ) {
  101. floatingValues.push_back( argument );
  102. if ( floatingValues.size() > maxFloatingValues ) {
  103. throw new std::invalid_argument("Unexpected floating value `" + argument + "`. Forget to specify an option?" );
  104. }
  105. }
  106. if ( argument[0] == '-' && argument[1] == '-' ) {
  107. i += validateStringOption( argc, argv, i );
  108. continue;
  109. }
  110. i += validateCharOption( argc, argv, i );
  111. }
  112. }
  113. Options::Options( int argc, char** argv ) {
  114. validate( argc, argv );
  115. }
  116. bool Options::getFloat( std::string name, char namec, float& found ) {
  117. for( unsigned int i=0;i<arguments.size();i++ ) {
  118. if ( arguments[i] == name || arguments[i] == std::string("")+namec ) {
  119. std::string::size_type sz;
  120. float retvar;
  121. try {
  122. retvar = std::stof(values[i],&sz);
  123. } catch ( ... ) {
  124. throw new std::invalid_argument("Unable to parse `" + arguments[i] + "`'s value `" + values[i] + "` as a float.");
  125. }
  126. if ( sz != values[i].length() ) {
  127. throw new std::invalid_argument("Unable to parse `" + arguments[i] + "`'s value `" + values[i] + "` as a float.");
  128. }
  129. found = retvar;
  130. return true;
  131. }
  132. }
  133. return false;
  134. }
  135. bool Options::getInt( std::string name, char namec, int& found ) {
  136. for( unsigned int i=0;i<arguments.size();i++ ) {
  137. if ( arguments[i] == name || arguments[i] == std::string("")+namec ) {
  138. if ( arguments[i].size() > 1 && arguments[i].find("=") == std::string::npos ) {
  139. throw new std::invalid_argument("Expected `=` after " + arguments[i]);
  140. }
  141. std::string::size_type sz;
  142. float retvar;
  143. try {
  144. retvar = std::stoi(values[i],&sz);
  145. } catch ( ... ) {
  146. throw new std::invalid_argument("Unable to parse " + arguments[i] + "'s value " + values[i] + " as an integer.");
  147. }
  148. if ( sz != values[i].length() ) {
  149. throw new std::invalid_argument("Unable to parse " + arguments[i] + "'s value " + values[i] + " as an integer.");
  150. }
  151. found = retvar;
  152. return true;
  153. }
  154. }
  155. return false;
  156. }
  157. bool Options::getString( std::string name, char namec, std::string& found ) {
  158. for( unsigned int i=0;i<arguments.size();i++ ) {
  159. if ( arguments[i] == name || arguments[i] == std::string("")+namec ) {
  160. found = values[i];
  161. return true;
  162. }
  163. }
  164. return false;
  165. }
  166. bool Options::getColor( std::string name, char namec, glm::vec4& found ) {
  167. for( unsigned int i=0;i<arguments.size();i++ ) {
  168. if ( arguments[i] == name || arguments[i] == std::string("")+namec ) {
  169. std::string::size_type sz;
  170. std::string value = values[i];
  171. try {
  172. found[0] = std::stof(value,&sz);
  173. value = value.substr(sz+1);
  174. found[1] = std::stof(value,&sz);
  175. value = value.substr(sz+1);
  176. found[2] = std::stof(value,&sz);
  177. if ( value.size() != sz ) {
  178. value = value.substr(sz+1);
  179. found[3] = std::stof(value,&sz);
  180. if ( value.size() != sz ) {
  181. throw "dur";
  182. }
  183. } else {
  184. found[3] = 1;
  185. }
  186. } catch ( ... ) {
  187. 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.");
  188. }
  189. return true;
  190. }
  191. }
  192. return false;
  193. }
  194. bool Options::getBool( std::string name, char namec, bool& found ) {
  195. for( unsigned int i=0;i<arguments.size();i++ ) {
  196. if ( arguments[i] == name || arguments[i] == std::string("")+namec ) {
  197. if ( values[i] != "" ) {
  198. throw new std::invalid_argument("Unexpected value `" + values[i] + "` for flag argument `" + arguments[i] + "`.");
  199. }
  200. found = true;
  201. return true;
  202. }
  203. }
  204. return false;
  205. }