/src/OS/Args.hpp

https://github.com/Tjeerdm/XCSoar · C++ Header · 211 lines · 173 code · 16 blank · 22 comment · 4 complexity · d0c7365bbfcbbd28d02a20510ba78d40 MD5 · raw file

  1. /*
  2. Copyright_License {
  3. XCSoar Glide Computer - http://www.xcsoar.org/
  4. Copyright (C) 2000-2013 The XCSoar Project
  5. A detailed list of copyright holders can be found in the file "AUTHORS".
  6. This program is free software; you can redistribute it and/or
  7. modify it under the terms of the GNU General Public License
  8. as published by the Free Software Foundation; either version 2
  9. of the License, or (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program; if not, write to the Free Software
  16. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17. }
  18. */
  19. #ifndef ARGS_HPP
  20. #define ARGS_HPP
  21. #include "Compiler.h"
  22. #include "Util/tstring.hpp"
  23. #include "Util/NumberParser.hpp"
  24. #ifdef _UNICODE
  25. #include "OS/PathName.hpp"
  26. #endif
  27. #include <list>
  28. #include <algorithm>
  29. #include <stdlib.h>
  30. #include <stdio.h>
  31. #include <assert.h>
  32. #ifdef MORE_USAGE
  33. extern void PrintMoreUsage();
  34. #endif
  35. class Args {
  36. std::list<char *> args;
  37. const char *name, *usage;
  38. #ifdef WIN32
  39. char *cmdline;
  40. #endif
  41. public:
  42. Args(int argc, char **argv, const char *_usage)
  43. :name(argv[0]), usage(_usage) {
  44. assert(name != nullptr);
  45. assert(usage != nullptr);
  46. std::copy(argv + 1, argv + argc, std::back_inserter(args));
  47. #ifdef WIN32
  48. cmdline = nullptr;
  49. #endif
  50. }
  51. Args(const Args &other) = delete;
  52. Args(Args &&other):name(other.name), usage(other.usage) {
  53. std::swap(args, other.args);
  54. #ifdef WIN32
  55. std::swap(cmdline, other.cmdline);
  56. #endif
  57. }
  58. #ifdef WIN32
  59. Args(const TCHAR *_cmdline, const char *_usage)
  60. :usage(_usage) {
  61. ParseCommandLine(_cmdline);
  62. }
  63. ~Args() {
  64. delete[] cmdline;
  65. }
  66. void ParseCommandLine(const char *_cmdline) {
  67. const char *s = _cmdline;
  68. cmdline = new char[strlen(s) + 1];
  69. char *d = cmdline; // current position in destination buffer
  70. char *option = cmdline;
  71. name = nullptr;
  72. bool in_qoute = false;
  73. do {
  74. if (*s == '"')
  75. in_qoute = !in_qoute;
  76. else if (*s == '\0' || (!in_qoute && *s == ' ')) {
  77. // collapse runs of unqouted ' 's to a single '\0'
  78. if (d > cmdline && *(d-1) != '\0') {
  79. *d++ = '\0';
  80. // remember potential start position of next option
  81. option = d;
  82. }
  83. } else {
  84. *d = *s;
  85. if (option == d) {
  86. // first quoted blank or non blank character of new option
  87. #ifndef _WIN32_WCE
  88. // program name is not included in command line on CE
  89. if (name == nullptr)
  90. name = option;
  91. else
  92. #endif
  93. args.push_back(option);
  94. }
  95. d++;
  96. }
  97. } while (*s++);
  98. if (name == nullptr)
  99. name = "";
  100. }
  101. #ifdef _UNICODE
  102. void ParseCommandLine(const TCHAR *_cmdline) {
  103. NarrowPathName convert(_cmdline);
  104. ParseCommandLine(convert);
  105. }
  106. #endif
  107. #endif
  108. Args &operator=(const Args &other) = delete;
  109. gcc_noreturn
  110. void UsageError() {
  111. fprintf(stderr, "Usage: %s %s\n", name, usage);
  112. #ifdef MORE_USAGE
  113. PrintMoreUsage();
  114. #endif
  115. exit(EXIT_FAILURE);
  116. }
  117. bool IsEmpty() const {
  118. return args.empty();
  119. }
  120. const char *GetNext() {
  121. assert(!IsEmpty());
  122. const char *p = args.front();
  123. Skip();
  124. return p;
  125. }
  126. void Skip() {
  127. args.pop_front();
  128. }
  129. const char *PeekNext() const {
  130. return IsEmpty() ? nullptr : args.front();
  131. }
  132. const char *ExpectNext() {
  133. if (IsEmpty())
  134. UsageError();
  135. return GetNext();
  136. }
  137. int ExpectNextInt() {
  138. const char *p = ExpectNext();
  139. assert(p != nullptr);
  140. char *endptr;
  141. int result = ParseInt(p, &endptr);
  142. if (p == endptr)
  143. UsageError();
  144. return result;
  145. }
  146. double ExpectNextDouble() {
  147. const char *p = ExpectNext();
  148. assert(p != nullptr);
  149. char *endptr;
  150. double result = ParseDouble(p, &endptr);
  151. if (p == endptr)
  152. UsageError();
  153. return result;
  154. }
  155. tstring ExpectNextT() {
  156. const char *p = ExpectNext();
  157. assert(p != nullptr);
  158. #ifdef _UNICODE
  159. PathName convert(p);
  160. return tstring(convert);
  161. #else
  162. return tstring(p);
  163. #endif
  164. }
  165. void ExpectEnd() {
  166. if (!IsEmpty())
  167. UsageError();
  168. }
  169. };
  170. #endif