HierarchicalStorage.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566
  1. //---------------------------------------------------------------------------
  2. #include <vcl.h>
  3. #pragma hdrstop
  4. #include "Common.h"
  5. #include "PuttyIntf.h"
  6. #include "HierarchicalStorage.h"
  7. //---------------------------------------------------------------------------
  8. #pragma package(smart_init)
  9. //---------------------------------------------------------------------------
  10. #define READ_REGISTRY(Method) \
  11. if (FRegistry->ValueExists(Name)) \
  12. try { return FRegistry->Method(Name); } catch(...) { FFailed++; return Default; } \
  13. else return Default;
  14. #define WRITE_REGISTRY(Method) \
  15. try { FRegistry->Method(Name, Value); } catch(...) { FFailed++; }
  16. //---------------------------------------------------------------------------
  17. AnsiString __fastcall MungeStr(const AnsiString Str)
  18. {
  19. AnsiString Result;
  20. Result.SetLength(Str.Length() * 3 + 1);
  21. putty_mungestr(Str.c_str(), Result.c_str());
  22. PackStr(Result);
  23. return Result;
  24. }
  25. //---------------------------------------------------------------------------
  26. AnsiString __fastcall UnMungeStr(const AnsiString Str)
  27. {
  28. AnsiString Result;
  29. Result.SetLength(Str.Length() * 3 + 1);
  30. putty_unmungestr(Str.c_str(), Result.c_str(), Result.Length());
  31. PackStr(Result);
  32. return Result;
  33. }
  34. //===========================================================================
  35. __fastcall THierarchicalStorage::THierarchicalStorage(const AnsiString AStorage)
  36. {
  37. FStorage = AStorage;
  38. FKeyHistory = new TStringList();
  39. AccessMode = smRead;
  40. }
  41. //---------------------------------------------------------------------------
  42. __fastcall THierarchicalStorage::~THierarchicalStorage()
  43. {
  44. delete FKeyHistory;
  45. }
  46. //---------------------------------------------------------------------------
  47. void __fastcall THierarchicalStorage::SetAccessMode(TStorageAccessMode value)
  48. {
  49. FAccessMode = value;
  50. }
  51. //---------------------------------------------------------------------------
  52. AnsiString __fastcall THierarchicalStorage::GetCurrentSubKey()
  53. {
  54. if (FKeyHistory->Count) return FKeyHistory->Strings[FKeyHistory->Count-1];
  55. else return "";
  56. }
  57. //---------------------------------------------------------------------------
  58. bool __fastcall THierarchicalStorage::OpenRootKey(bool CanCreate)
  59. {
  60. return OpenSubKey("", CanCreate);
  61. }
  62. //---------------------------------------------------------------------------
  63. bool __fastcall THierarchicalStorage::OpenSubKey(const AnsiString SubKey, bool )
  64. {
  65. FKeyHistory->Add(IncludeTrailingBackslash(CurrentSubKey+SubKey));
  66. return true;
  67. }
  68. //---------------------------------------------------------------------------
  69. bool __fastcall THierarchicalStorage::CreateSubKey(const AnsiString SubKey)
  70. {
  71. FKeyHistory->Add(IncludeTrailingBackslash(CurrentSubKey+SubKey));
  72. return true;
  73. }
  74. //---------------------------------------------------------------------------
  75. void __fastcall THierarchicalStorage::CloseSubKey()
  76. {
  77. if (FKeyHistory->Count == 0) throw Exception("");
  78. else FKeyHistory->Delete(FKeyHistory->Count-1);
  79. }
  80. //---------------------------------------------------------------------------
  81. void __fastcall THierarchicalStorage::RecursiveDeleteSubKey(const AnsiString Key)
  82. {
  83. if (OpenSubKey(Key, false))
  84. {
  85. TStringList *SubKeys = new TStringList();
  86. try
  87. {
  88. GetSubKeyNames(SubKeys);
  89. for (int Index = 0; Index < SubKeys->Count; Index++)
  90. {
  91. RecursiveDeleteSubKey(SubKeys->Strings[Index]);
  92. }
  93. }
  94. __finally
  95. {
  96. delete SubKeys;
  97. }
  98. CloseSubKey();
  99. }
  100. DeleteSubKey(Key);
  101. }
  102. //---------------------------------------------------------------------------
  103. bool __fastcall THierarchicalStorage::HasSubKeys()
  104. {
  105. bool Result;
  106. TStrings * SubKeys = new TStringList();
  107. try
  108. {
  109. GetSubKeyNames(SubKeys);
  110. Result = (SubKeys->Count > 0);
  111. }
  112. __finally
  113. {
  114. delete SubKeys;
  115. }
  116. return Result;
  117. }
  118. //---------------------------------------------------------------------------
  119. void __fastcall THierarchicalStorage::ReadValues(Classes::TStrings* Strings,
  120. bool MaintainKeys)
  121. {
  122. TStrings * Names = new TStringList();
  123. try
  124. {
  125. GetValueNames(Names);
  126. for (int Index = 0; Index < Names->Count; Index++)
  127. {
  128. if (MaintainKeys)
  129. {
  130. Strings->Add(FORMAT("%s=%s", (Names->Strings[Index],
  131. ReadString(Names->Strings[Index], ""))));
  132. }
  133. else
  134. {
  135. Strings->Add(ReadString(Names->Strings[Index], ""));
  136. }
  137. }
  138. }
  139. __finally
  140. {
  141. delete Names;
  142. }
  143. }
  144. //---------------------------------------------------------------------------
  145. void __fastcall THierarchicalStorage::WriteValues(Classes::TStrings * Strings,
  146. bool MaintainKeys)
  147. {
  148. TStrings * Names = new TStringList();
  149. try
  150. {
  151. GetValueNames(Names);
  152. for (int Index = 0; Index < Names->Count; Index++)
  153. {
  154. DeleteValue(Names->Strings[Index]);
  155. }
  156. }
  157. __finally
  158. {
  159. delete Names;
  160. }
  161. if (Strings)
  162. {
  163. for (int Index = 0; Index < Strings->Count; Index++)
  164. {
  165. if (MaintainKeys)
  166. {
  167. assert(Strings->Strings[Index].Pos("=") > 1);
  168. WriteString(Strings->Names[Index], Strings->Values[Strings->Names[Index]]);
  169. }
  170. else
  171. {
  172. WriteString(IntToStr(Index), Strings->Strings[Index]);
  173. }
  174. }
  175. }
  176. }
  177. //---------------------------------------------------------------------------
  178. AnsiString __fastcall THierarchicalStorage::ReadString(const AnsiString Name, const AnsiString Default)
  179. {
  180. return UnMungeStr(ReadStringRaw(Name, Default));
  181. }
  182. //---------------------------------------------------------------------------
  183. void __fastcall THierarchicalStorage::WriteString(const AnsiString Name, const AnsiString Value)
  184. {
  185. WriteStringRaw(Name, MungeStr(Value));
  186. }
  187. //---------------------------------------------------------------------------
  188. AnsiString __fastcall THierarchicalStorage::IncludeTrailingBackslash(const AnsiString S) const
  189. {
  190. return S.IsEmpty() ? S : ::IncludeTrailingBackslash(S);
  191. }
  192. //---------------------------------------------------------------------------
  193. AnsiString __fastcall THierarchicalStorage::ExcludeTrailingBackslash(const AnsiString S) const
  194. {
  195. return S.IsEmpty() ? S : ::ExcludeTrailingBackslash(S);
  196. }
  197. //===========================================================================
  198. __fastcall TRegistryStorage::TRegistryStorage(const AnsiString AStorage):
  199. THierarchicalStorage(IncludeTrailingBackslash(AStorage))
  200. {
  201. Init();
  202. };
  203. //---------------------------------------------------------------------------
  204. __fastcall TRegistryStorage::TRegistryStorage(const AnsiString AStorage, HKEY ARootKey):
  205. THierarchicalStorage(IncludeTrailingBackslash(AStorage))
  206. {
  207. Init();
  208. FRegistry->RootKey = ARootKey;
  209. }
  210. //---------------------------------------------------------------------------
  211. void __fastcall TRegistryStorage::Init()
  212. {
  213. FFailed = 0;
  214. FRegistry = new TRegistry();
  215. FRegistry->Access = KEY_READ;
  216. }
  217. //---------------------------------------------------------------------------
  218. __fastcall TRegistryStorage::~TRegistryStorage()
  219. {
  220. delete FRegistry;
  221. };
  222. //---------------------------------------------------------------------------
  223. void __fastcall TRegistryStorage::SetAccessMode(TStorageAccessMode value)
  224. {
  225. THierarchicalStorage::SetAccessMode(value);
  226. if (FRegistry)
  227. {
  228. switch (AccessMode) {
  229. case smRead:
  230. FRegistry->Access = KEY_READ;
  231. break;
  232. case smReadWrite:
  233. default:
  234. FRegistry->Access = KEY_READ | KEY_WRITE;
  235. break;
  236. }
  237. }
  238. }
  239. //---------------------------------------------------------------------------
  240. bool __fastcall TRegistryStorage::OpenSubKey(const AnsiString SubKey, bool CanCreate)
  241. {
  242. bool Result;
  243. if (FKeyHistory->Count > 0) FRegistry->CloseKey();
  244. Result = FRegistry->OpenKey(
  245. ExcludeTrailingBackslash(Storage + CurrentSubKey + SubKey), CanCreate);
  246. if (Result) Result = THierarchicalStorage::OpenSubKey(SubKey, CanCreate);
  247. return Result;
  248. }
  249. //---------------------------------------------------------------------------
  250. bool __fastcall TRegistryStorage::CreateSubKey(const AnsiString SubKey)
  251. {
  252. bool Result;
  253. if (FKeyHistory->Count) FRegistry->CloseKey();
  254. Result = FRegistry->CreateKey(ExcludeTrailingBackslash(Storage + CurrentSubKey + SubKey));
  255. if (Result) Result = THierarchicalStorage::CreateSubKey(CurrentSubKey + SubKey);
  256. return Result;
  257. }
  258. //---------------------------------------------------------------------------
  259. void __fastcall TRegistryStorage::CloseSubKey()
  260. {
  261. FRegistry->CloseKey();
  262. THierarchicalStorage::CloseSubKey();
  263. if (FKeyHistory->Count)
  264. {
  265. FRegistry->OpenKey(Storage + CurrentSubKey, True);
  266. }
  267. }
  268. //---------------------------------------------------------------------------
  269. bool __fastcall TRegistryStorage::DeleteSubKey(const AnsiString SubKey)
  270. {
  271. AnsiString K;
  272. if (FKeyHistory->Count == 0) K = Storage + CurrentSubKey;
  273. K += SubKey;
  274. return FRegistry->DeleteKey(K);
  275. }
  276. //---------------------------------------------------------------------------
  277. void __fastcall TRegistryStorage::GetSubKeyNames(Classes::TStrings* Strings)
  278. {
  279. FRegistry->GetKeyNames(Strings);
  280. }
  281. //---------------------------------------------------------------------------
  282. void __fastcall TRegistryStorage::GetValueNames(Classes::TStrings* Strings)
  283. {
  284. FRegistry->GetValueNames(Strings);
  285. }
  286. //---------------------------------------------------------------------------
  287. bool __fastcall TRegistryStorage::DeleteValue(const AnsiString Name)
  288. {
  289. return FRegistry->DeleteValue(Name);
  290. }
  291. //---------------------------------------------------------------------------
  292. bool __fastcall TRegistryStorage::ReadBool(const AnsiString Name, bool Default)
  293. {
  294. READ_REGISTRY(ReadBool);
  295. }
  296. //---------------------------------------------------------------------------
  297. TDateTime __fastcall TRegistryStorage::ReadDateTime(const AnsiString Name, TDateTime Default)
  298. {
  299. READ_REGISTRY(ReadDateTime);
  300. }
  301. //---------------------------------------------------------------------------
  302. double __fastcall TRegistryStorage::ReadFloat(const AnsiString Name, double Default)
  303. {
  304. READ_REGISTRY(ReadFloat);
  305. }
  306. //---------------------------------------------------------------------------
  307. int __fastcall TRegistryStorage::ReadInteger(const AnsiString Name, int Default)
  308. {
  309. READ_REGISTRY(ReadInteger);
  310. }
  311. //---------------------------------------------------------------------------
  312. __int64 __fastcall TRegistryStorage::ReadInt64(const AnsiString Name, __int64 Default)
  313. {
  314. __int64 Result = Default;
  315. if (FRegistry->ValueExists(Name))
  316. {
  317. try
  318. {
  319. FRegistry->ReadBinaryData(Name, &Result, sizeof(Result));
  320. }
  321. catch(...)
  322. {
  323. FFailed++;
  324. }
  325. }
  326. return Result;
  327. }
  328. //---------------------------------------------------------------------------
  329. AnsiString __fastcall TRegistryStorage::ReadStringRaw(const AnsiString Name, const AnsiString Default)
  330. {
  331. READ_REGISTRY(ReadString);
  332. }
  333. //---------------------------------------------------------------------------
  334. void __fastcall TRegistryStorage::WriteBool(const AnsiString Name, bool Value)
  335. {
  336. WRITE_REGISTRY(WriteBool);
  337. }
  338. //---------------------------------------------------------------------------
  339. void __fastcall TRegistryStorage::WriteDateTime(const AnsiString Name, TDateTime Value)
  340. {
  341. WRITE_REGISTRY(WriteDateTime);
  342. }
  343. //---------------------------------------------------------------------------
  344. void __fastcall TRegistryStorage::WriteFloat(const AnsiString Name, double Value)
  345. {
  346. WRITE_REGISTRY(WriteFloat);
  347. }
  348. //---------------------------------------------------------------------------
  349. void __fastcall TRegistryStorage::WriteStringRaw(const AnsiString Name, const AnsiString Value)
  350. {
  351. WRITE_REGISTRY(WriteString);
  352. }
  353. //---------------------------------------------------------------------------
  354. void __fastcall TRegistryStorage::WriteInteger(const AnsiString Name, int Value)
  355. {
  356. WRITE_REGISTRY(WriteInteger);
  357. }
  358. //---------------------------------------------------------------------------
  359. void __fastcall TRegistryStorage::WriteInt64(const AnsiString Name, __int64 Value)
  360. {
  361. try
  362. {
  363. FRegistry->WriteBinaryData(Name, &Value, sizeof(Value));
  364. }
  365. catch(...)
  366. {
  367. FFailed++;
  368. }
  369. }
  370. //---------------------------------------------------------------------------
  371. int __fastcall TRegistryStorage::GetFailed()
  372. {
  373. int Result = FFailed;
  374. FFailed = 0;
  375. return Result;
  376. }
  377. //===========================================================================
  378. __fastcall TIniFileStorage::TIniFileStorage(const AnsiString AStorage):
  379. THierarchicalStorage(AStorage)
  380. {
  381. FIniFile = new TIniFile(Storage);
  382. }
  383. //---------------------------------------------------------------------------
  384. __fastcall TIniFileStorage::~TIniFileStorage()
  385. {
  386. delete FIniFile;
  387. }
  388. //---------------------------------------------------------------------------
  389. AnsiString __fastcall TIniFileStorage::GetCurrentSection()
  390. {
  391. return ExcludeTrailingBackslash(CurrentSubKey);
  392. }
  393. //---------------------------------------------------------------------------
  394. bool __fastcall TIniFileStorage::OpenSubKey(const AnsiString SubKey, bool CanCreate)
  395. {
  396. bool Result = CanCreate;
  397. if (!Result)
  398. {
  399. TStringList * Sections = new TStringList();
  400. try
  401. {
  402. Sections->Sorted = true;
  403. FIniFile->ReadSections(Sections);
  404. AnsiString NewKey = ExcludeTrailingBackslash(CurrentSubKey+SubKey);
  405. int Index = -1;
  406. if (Sections->Count)
  407. {
  408. Result = Sections->Find(NewKey, Index);
  409. if (!Result && Index < Sections->Count &&
  410. Sections->Strings[Index].SubString(1, NewKey.Length()+1) == NewKey + "\\")
  411. {
  412. Result = true;
  413. }
  414. }
  415. }
  416. __finally
  417. {
  418. delete Sections;
  419. }
  420. }
  421. if (Result)
  422. {
  423. Result = THierarchicalStorage::OpenSubKey(SubKey, CanCreate);
  424. }
  425. return Result;
  426. }
  427. //---------------------------------------------------------------------------
  428. bool __fastcall TIniFileStorage::DeleteSubKey(const AnsiString SubKey)
  429. {
  430. bool Result;
  431. try
  432. {
  433. FIniFile->EraseSection(CurrentSubKey + SubKey);
  434. Result = true;
  435. }
  436. catch (...)
  437. {
  438. Result = false;
  439. }
  440. return Result;
  441. }
  442. //---------------------------------------------------------------------------
  443. void __fastcall TIniFileStorage::GetSubKeyNames(Classes::TStrings* Strings)
  444. {
  445. TStrings * Sections = new TStringList();
  446. try
  447. {
  448. Strings->Clear();
  449. FIniFile->ReadSections(Sections);
  450. for (int i = 0; i < Sections->Count; i++)
  451. {
  452. AnsiString Section = Sections->Strings[i];
  453. if (AnsiCompareText(CurrentSubKey,
  454. Section.SubString(1, CurrentSubKey.Length())) == 0)
  455. {
  456. AnsiString SubSection = Section.SubString(CurrentSubKey.Length() + 1,
  457. Section.Length() - CurrentSubKey.Length());
  458. int P = SubSection.Pos("\\");
  459. if (P)
  460. {
  461. SubSection.SetLength(P - 1);
  462. }
  463. if (Strings->IndexOf(SubSection) < 0)
  464. {
  465. Strings->Add(SubSection);
  466. }
  467. }
  468. }
  469. }
  470. __finally
  471. {
  472. delete Sections;
  473. }
  474. }
  475. //---------------------------------------------------------------------------
  476. void __fastcall TIniFileStorage::GetValueNames(Classes::TStrings* Strings)
  477. {
  478. return FIniFile->ReadSection(CurrentSection, Strings);
  479. }
  480. //---------------------------------------------------------------------------
  481. bool __fastcall TIniFileStorage::DeleteValue(const AnsiString Name)
  482. {
  483. FIniFile->DeleteKey(CurrentSection, Name);
  484. return true;
  485. }
  486. //---------------------------------------------------------------------------
  487. bool __fastcall TIniFileStorage::ReadBool(const AnsiString Name, bool Default)
  488. {
  489. return FIniFile->ReadBool(CurrentSection, Name, Default);
  490. }
  491. //---------------------------------------------------------------------------
  492. int __fastcall TIniFileStorage::ReadInteger(const AnsiString Name, int Default)
  493. {
  494. return FIniFile->ReadInteger(CurrentSection, Name, Default);
  495. }
  496. //---------------------------------------------------------------------------
  497. __int64 __fastcall TIniFileStorage::ReadInt64(const AnsiString Name, __int64 Default)
  498. {
  499. __int64 Result = Default;
  500. AnsiString Str;
  501. Str = ReadStringRaw(Name, "");
  502. if (!Str.IsEmpty())
  503. {
  504. Result = StrToInt64Def(Str, Default);
  505. }
  506. return Result;
  507. }
  508. //---------------------------------------------------------------------------
  509. TDateTime __fastcall TIniFileStorage::ReadDateTime(const AnsiString Name, TDateTime Default)
  510. {
  511. return FIniFile->ReadDateTime(CurrentSection, Name, Default);
  512. }
  513. //---------------------------------------------------------------------------
  514. double __fastcall TIniFileStorage::ReadFloat(const AnsiString Name, double Default)
  515. {
  516. return FIniFile->ReadFloat(CurrentSection, Name, Default);
  517. }
  518. //---------------------------------------------------------------------------
  519. AnsiString __fastcall TIniFileStorage::ReadStringRaw(const AnsiString Name, AnsiString Default)
  520. {
  521. return FIniFile->ReadString(CurrentSection, Name, Default);
  522. }
  523. //---------------------------------------------------------------------------
  524. void __fastcall TIniFileStorage::WriteBool(const AnsiString Name, bool Value)
  525. {
  526. FIniFile->WriteBool(CurrentSection, Name, Value);
  527. }
  528. //---------------------------------------------------------------------------
  529. void __fastcall TIniFileStorage::WriteInteger(const AnsiString Name, int Value)
  530. {
  531. FIniFile->WriteInteger(CurrentSection, Name, Value);
  532. }
  533. //---------------------------------------------------------------------------
  534. void __fastcall TIniFileStorage::WriteInt64(const AnsiString Name, __int64 Value)
  535. {
  536. WriteStringRaw(Name, IntToStr(Value));
  537. }
  538. //---------------------------------------------------------------------------
  539. void __fastcall TIniFileStorage::WriteDateTime(const AnsiString Name, TDateTime Value)
  540. {
  541. FIniFile->WriteDateTime(CurrentSection, Name, Value);
  542. }
  543. //---------------------------------------------------------------------------
  544. void __fastcall TIniFileStorage::WriteFloat(const AnsiString Name, double Value)
  545. {
  546. FIniFile->WriteFloat(CurrentSection, Name, Value);
  547. }
  548. //---------------------------------------------------------------------------
  549. void __fastcall TIniFileStorage::WriteStringRaw(const AnsiString Name, const AnsiString Value)
  550. {
  551. FIniFile->WriteString(CurrentSection, Name, Value);
  552. }