Option.cpp 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. //---------------------------------------------------------------------------
  2. #include <vcl.h>
  3. #pragma hdrstop
  4. #include <Common.h>
  5. #include "Option.h"
  6. #include "TextsCore.h"
  7. //---------------------------------------------------------------------------
  8. #pragma package(smart_init)
  9. //---------------------------------------------------------------------------
  10. __fastcall TOptions::TOptions()
  11. {
  12. FSwitchMarks = L"/-";
  13. FSwitchValueDelimiters = L"=:";
  14. FNoMoreSwitches = false;
  15. FParamCount = 0;
  16. }
  17. //---------------------------------------------------------------------------
  18. void __fastcall TOptions::Add(UnicodeString Value)
  19. {
  20. if (!FNoMoreSwitches &&
  21. (Value.Length() == 2) &&
  22. (Value[1] == Value[2]) &&
  23. (FSwitchMarks.Pos(Value[1]) > 0))
  24. {
  25. FNoMoreSwitches = true;
  26. }
  27. else
  28. {
  29. bool Switch = false;
  30. int Index = 0; // shut up
  31. if (!FNoMoreSwitches &&
  32. (Value.Length() >= 2) &&
  33. (FSwitchMarks.Pos(Value[1]) > 0))
  34. {
  35. Index = 2;
  36. Switch = true;
  37. while (Switch && (Index <= Value.Length()))
  38. {
  39. if (Value.IsDelimiter(FSwitchValueDelimiters, Index))
  40. {
  41. break;
  42. }
  43. // this is to treat /home/martin as parameter, not as switch
  44. else if ((Value[Index] != L'?') && !IsLetter(Value[Index]))
  45. {
  46. Switch = false;
  47. break;
  48. }
  49. ++Index;
  50. }
  51. }
  52. if (Switch)
  53. {
  54. TOption Option;
  55. Option.Type = otSwitch;
  56. Option.Name = Value.SubString(2, Index - 2);
  57. Option.Value = Value.SubString(Index + 1, Value.Length());
  58. Option.Used = false;
  59. FOptions.push_back(Option);
  60. }
  61. else
  62. {
  63. TOption Option;
  64. Option.Type = otParam;
  65. Option.Value = Value;
  66. Option.Used = false;
  67. FOptions.push_back(Option);
  68. ++FParamCount;
  69. }
  70. }
  71. FOriginalOptions = FOptions;
  72. }
  73. //---------------------------------------------------------------------------
  74. UnicodeString __fastcall TOptions::GetParam(int Index)
  75. {
  76. assert((Index >= 1) && (Index <= FParamCount));
  77. UnicodeString Result;
  78. size_t I = 0;
  79. while ((I < FOptions.size()) && (Index > 0))
  80. {
  81. if (FOptions[I].Type == otParam)
  82. {
  83. --Index;
  84. if (Index == 0)
  85. {
  86. Result = FOptions[I].Value;
  87. FOptions[I].Used = true;
  88. }
  89. }
  90. ++I;
  91. }
  92. return Result;
  93. }
  94. //---------------------------------------------------------------------------
  95. bool __fastcall TOptions::GetEmpty()
  96. {
  97. return FOptions.empty();
  98. }
  99. //---------------------------------------------------------------------------
  100. bool __fastcall TOptions::FindSwitch(const UnicodeString Switch,
  101. UnicodeString & Value, int & ParamsStart, int & ParamsCount)
  102. {
  103. ParamsStart = 0;
  104. int Index = 0;
  105. bool Found = false;
  106. while ((Index < int(FOptions.size())) && !Found)
  107. {
  108. if (FOptions[Index].Type == otParam)
  109. {
  110. ParamsStart++;
  111. }
  112. else if (FOptions[Index].Type == otSwitch)
  113. {
  114. if (AnsiSameText(FOptions[Index].Name, Switch))
  115. {
  116. Found = true;
  117. Value = FOptions[Index].Value;
  118. FOptions[Index].Used = true;
  119. }
  120. }
  121. Index++;
  122. }
  123. ParamsCount = 0;
  124. if (Found)
  125. {
  126. ParamsStart++;
  127. while ((Index + ParamsCount < int(FOptions.size())) &&
  128. (FOptions[Index + ParamsCount].Type == otParam))
  129. {
  130. ParamsCount++;
  131. }
  132. }
  133. else
  134. {
  135. ParamsStart = 0;
  136. }
  137. return Found;
  138. }
  139. //---------------------------------------------------------------------------
  140. bool __fastcall TOptions::FindSwitch(const UnicodeString Switch, UnicodeString & Value)
  141. {
  142. int ParamsStart;
  143. int ParamsCount;
  144. return FindSwitch(Switch, Value, ParamsStart, ParamsCount);
  145. }
  146. //---------------------------------------------------------------------------
  147. bool __fastcall TOptions::FindSwitch(const UnicodeString Switch)
  148. {
  149. UnicodeString Value;
  150. int ParamsStart;
  151. int ParamsCount;
  152. return FindSwitch(Switch, Value, ParamsStart, ParamsCount);
  153. }
  154. //---------------------------------------------------------------------------
  155. bool __fastcall TOptions::FindSwitch(const UnicodeString Switch,
  156. TStrings * Params, int ParamsMax)
  157. {
  158. UnicodeString Value;
  159. int ParamsStart;
  160. int ParamsCount;
  161. bool Result = FindSwitch(Switch, Value, ParamsStart, ParamsCount);
  162. if (Result)
  163. {
  164. if ((ParamsMax >= 0) && (ParamsCount > ParamsMax))
  165. {
  166. ParamsCount = ParamsMax;
  167. }
  168. int Index = 0;
  169. while (Index < ParamsCount)
  170. {
  171. Params->Add(Param[ParamsStart + Index]);
  172. Index++;
  173. }
  174. ParamsProcessed(ParamsStart, ParamsCount);
  175. }
  176. return Result;
  177. }
  178. //---------------------------------------------------------------------------
  179. UnicodeString __fastcall TOptions::SwitchValue(const UnicodeString Switch,
  180. const UnicodeString Default)
  181. {
  182. UnicodeString Value;
  183. FindSwitch(Switch, Value);
  184. if (Value.IsEmpty())
  185. {
  186. Value = Default;
  187. }
  188. return Value;
  189. }
  190. //---------------------------------------------------------------------------
  191. bool __fastcall TOptions::SwitchValue(const UnicodeString Switch, bool Default, bool DefaultOnNonExistence)
  192. {
  193. bool Result;
  194. int IntValue;
  195. UnicodeString Value;
  196. if (!FindSwitch(Switch, Value))
  197. {
  198. Result = DefaultOnNonExistence;
  199. }
  200. else if (Value.IsEmpty())
  201. {
  202. Result = Default;
  203. }
  204. else if (SameText(Value, "on"))
  205. {
  206. Result = true;
  207. }
  208. else if (SameText(Value, "off"))
  209. {
  210. Result = false;
  211. }
  212. else if (TryStrToInt(Value, IntValue))
  213. {
  214. Result = (IntValue != 0);
  215. }
  216. else
  217. {
  218. throw Exception(FMTLOAD(URL_OPTION_BOOL_VALUE_ERROR, (Value)));
  219. }
  220. return Result;
  221. }
  222. //---------------------------------------------------------------------------
  223. bool __fastcall TOptions::SwitchValue(const UnicodeString Switch, bool Default)
  224. {
  225. return SwitchValue(Switch, Default, Default);
  226. }
  227. //---------------------------------------------------------------------------
  228. bool __fastcall TOptions::UnusedSwitch(UnicodeString & Switch)
  229. {
  230. bool Result = false;
  231. size_t Index = 0;
  232. while (!Result && (Index < FOptions.size()))
  233. {
  234. if ((FOptions[Index].Type == otSwitch) &&
  235. !FOptions[Index].Used)
  236. {
  237. Switch = FOptions[Index].Name;
  238. Result = true;
  239. }
  240. ++Index;
  241. }
  242. return Result;
  243. }
  244. //---------------------------------------------------------------------------
  245. bool __fastcall TOptions::WasSwitchAdded(UnicodeString & Switch)
  246. {
  247. bool Result =
  248. ALWAYS_TRUE(FOptions.size() > 0) &&
  249. (FOptions.back().Type == otSwitch);
  250. if (Result)
  251. {
  252. Switch = FOptions.back().Name;
  253. }
  254. return Result;
  255. }
  256. //---------------------------------------------------------------------------
  257. void __fastcall TOptions::ParamsProcessed(int ParamsStart, int ParamsCount)
  258. {
  259. if (ParamsCount > 0)
  260. {
  261. assert((ParamsStart >= 0) && ((ParamsStart - ParamsCount + 1) <= FParamCount));
  262. size_t Index = 0;
  263. while ((Index < FOptions.size()) && (ParamsStart > 0))
  264. {
  265. if (FOptions[Index].Type == otParam)
  266. {
  267. --ParamsStart;
  268. if (ParamsStart == 0)
  269. {
  270. while (ParamsCount > 0)
  271. {
  272. assert(Index < FOptions.size());
  273. assert(FOptions[Index].Type == otParam);
  274. FOptions.erase(FOptions.begin() + Index);
  275. --FParamCount;
  276. --ParamsCount;
  277. }
  278. }
  279. }
  280. Index++;
  281. }
  282. }
  283. }
  284. //---------------------------------------------------------------------------
  285. void __fastcall TOptions::LogOptions(TLogOptionEvent OnLogOption)
  286. {
  287. for (size_t Index = 0; Index < FOriginalOptions.size(); Index++)
  288. {
  289. const TOption & Option = FOriginalOptions[Index];
  290. UnicodeString LogStr;
  291. switch (Option.Type)
  292. {
  293. case otParam:
  294. LogStr = FORMAT(L"Parameter: %s", (Option.Value));
  295. assert(Option.Name.IsEmpty());
  296. break;
  297. case otSwitch:
  298. LogStr =
  299. FORMAT(L"Switch: %s%s%s%s",
  300. (FSwitchMarks[1], Option.Name, (Option.Value.IsEmpty() ? UnicodeString() : FSwitchValueDelimiters.SubString(1, 1)), Option.Value));
  301. break;
  302. default:
  303. FAIL;
  304. break;
  305. }
  306. OnLogOption(LogStr);
  307. }
  308. }