PageRenderTime 42ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/SRC/Ahk/sub/ini.ahk

http://candy-software.googlecode.com/
AutoHotKey | 592 lines | 343 code | 23 blank | 226 comment | 9 complexity | 870877063e37ab6cb6dee81ff94df5ee MD5 | raw file
  1. ;http://www.autohotkey.net/~Titan
  2. ;子函数=================================================================================
  3. /*
  4. Title: INI Library
  5. A set of functions for modifying INI files in memory and writing them later to file.
  6. Useful for parsing a large data sets with minimal disk reads.
  7. License:
  8. - Version 1.08 by Titan <http://www.autohotkey.net/~Titan/#ini>
  9. - zlib License <http://www.autohotkey.net/~Titan/zlib.txt>
  10. */
  11. /*
  12. Function: ini_Read
  13. Get the value of a key within a specifed section.
  14. Parameters:
  15. var - ini object
  16. sec - name of section to look under
  17. key - key name
  18. default - (optional) value to return if key was not found
  19. Returns:
  20. Key value.
  21. Example:
  22. > ini_Load(phpconfig, ProgramFiles . "\PHP\php.ini") ; load INI file
  23. > ; read variable under section named "MySQL":
  24. > MyAppName := ini_Read(phpconfig, "MySQL", "mysql.max_MyAppName")
  25. > MsgBox, %MyAppName%
  26. */
  27. ini_Read(ByRef var, sec, key, default = "") {
  28. NumPut(160, var, 0, "UChar")
  29. f = `n%sec%/%key%=
  30. StringGetPos, p, var, %f%
  31. If ErrorLevel = 0
  32. {
  33. StringGetPos, p, var, =, , %p%
  34. StringMid, v, var, p += 2, InStr(var, "`n", "", p) - p
  35. }
  36. NumPut(0, var, 0, "UChar")
  37. Return, v == "" ? default : _ini_unescape(v)
  38. }
  39. /*
  40. Function: ini_Delete
  41. Removes a key within a specifed section.
  42. Parameters:
  43. var - ini object
  44. sec - name of section to
  45. look under
  46. key - key name
  47. */
  48. ini_Delete(ByRef var, sec, key) {
  49. NumPut(160, var, 0, "UChar")
  50. f = `n%sec%/%key%=
  51. StringGetPos, p, var, %f%
  52. If ErrorLevel = 0
  53. var := SubStr(var, 1, p) . SubStr(var, 1 + InStr(var, "`n", "", p + 2))
  54. NumPut(0, var, 0, "UChar")
  55. Return, true
  56. }
  57. /*
  58. Function: ini_Write
  59. Change the value of a key within a section or create one if it does not exist.
  60. Parameters:
  61. var - ini object
  62. sec - name of section to look under
  63. key - key name
  64. value - a string to store as the keys content
  65. Returns:
  66. Key value.
  67. */
  68. ini_Write(ByRef var, sec, key, value = "") {
  69. NumPut(160, var, 0, "UChar")
  70. f = `n%sec%/%key%=
  71. l := _ini_escape(value)
  72. StringGetPos, p, var, %f%
  73. If ErrorLevel = 1
  74. {
  75. var = %var%%f%%l%`n
  76. NumPut(0, var, 0, "UChar")
  77. Return, false
  78. }
  79. p += StrLen(f) + 1
  80. StringGetPos, p1, var, `n, , p
  81. StringLeft, d1, var, p - 1
  82. StringTrimLeft, d2, var, p1
  83. var = %d1%%l%%d2%
  84. NumPut(0, var, 0, "UChar")
  85. Return, true
  86. }
  87. /*
  88. Function: ini_MoveKey
  89. Copies or moves a key and its value from one section to another.
  90. Parameters:
  91. var - ini object
  92. from - name of parent section to the specified key
  93. to - section to inherit the new key
  94. copy - true to remove the old key, false otherwise
  95. Returns:
  96. True if the key was found and moved.
  97. */
  98. ini_MoveKey(ByRef var, from, to, key, copy = false) {
  99. NumPut(160, var, 0, "UChar")
  100. to := SubStr(var, InStr(var, "`n" . to . "/") + 1, StrLen(to))
  101. f = `n%from%/%key%
  102. StringGetPos, p, var, %f%
  103. If ErrorLevel = 1
  104. {
  105. NumPut(0, var, 0, "UChar")
  106. Return, false
  107. }
  108. p++
  109. StringGetPos, p1, var, `n, , p
  110. StringMid, e, var, p, p1 - p + 2
  111. v := SubStr(e, InStr(e, "=") + 1, -1)
  112. StringGetPos, p, var, `n%to%/%key%=
  113. If ErrorLevel = 0
  114. {
  115. p++
  116. StringGetPos, p1, var, `n, , p
  117. StringMid, r, var, p, p1 - p + 2
  118. StringReplace, var, var, %r%, `n%to%/%key%=%v%`n
  119. }
  120. Else var = %var%`n%to%/%key%=%v%
  121. If (!copy)
  122. StringReplace, var, var, %e%
  123. NumPut(0, var, 0, "UChar")
  124. Return, true
  125. }
  126. /*
  127. Function: ini_FindKeysRE
  128. Get a list of key names for a section from a regular expression.
  129. Parameters:
  130. var - ini object
  131. sec - name of section to look under
  132. exp - regular expression for key name
  133. Returns:
  134. List of `n (LF) delimited key names.
  135. */
  136. ini_FindKeysRE(ByRef var, sec, exp) {
  137. NumPut(160, var, 0, "UChar")
  138. s = %sec%/
  139. StringLen, b, s
  140. b++
  141. Loop, Parse, var, `n
  142. {
  143. If A_LoopField =
  144. Continue
  145. StringMid, k, A_LoopField, b, InStr(A_LoopField, "=") - b
  146. If (InStr(A_LoopField, s) == 1 and RegExMatch(k, exp))
  147. {
  148. l = %l%%k%
  149. Break
  150. }
  151. }
  152. NumPut(0, var, 0, "UChar")
  153. Return, l
  154. }
  155. /*
  156. Function: ini_GetKeys
  157. Get a list of key names for a section.
  158. Parameters:
  159. var - ini object
  160. sec - name of section to look under
  161. Returns:
  162. List of `n (LF) delimited key names.
  163. */
  164. ini_GetKeys(ByRef var, sec = "") {
  165. NumPut(160, var, 0, "UChar")
  166. p = 0
  167. Loop {
  168. StringGetPos, p, var, `n%sec%/, , p
  169. If ErrorLevel = 1
  170. Break
  171. StringGetPos, p1, var, /, , p
  172. StringGetPos, p2, var, =, , p
  173. p1 += 2
  174. StringMid, n, var, p1, p2 - p1 + 1
  175. l = %l%%n%`n
  176. p++
  177. }
  178. NumPut(0, var, 0, "UChar")
  179. l:=RegExReplace(l,"(^\s*|\s*$)")
  180. Return, l
  181. }
  182. /*
  183. Function: ini_FindSectionsRE
  184. Get a list of section names that match a regular expression.
  185. Parameters:
  186. var - ini object
  187. exp - regular expression for section names
  188. Returns:
  189. List of `n (LF) delimited section names.
  190. */
  191. ini_FindSectionsRE(ByRef var, exp) {
  192. NumPut(160, var, 0, "UChar")
  193. Loop, Parse, var, `n
  194. {
  195. If A_LoopField =
  196. Continue
  197. StringLeft, s, A_LoopField, InStr(A_LoopField, "/") - 1
  198. If (RegExMatch(s, exp) and !InStr(l, s . "`n"))
  199. l = %l%%s%`n
  200. }
  201. NumPut(0, var, 0, "UChar")
  202. Return, l
  203. }
  204. /*
  205. Function: ini_GetSections
  206. Get the complete list of sections.
  207. Parameters:
  208. var - ini object
  209. Returns:
  210. List of `n (LF) delimited section names.
  211. */
  212. ini_GetSections(ByRef var) {
  213. NumPut(160, var, 0, "UChar")
  214. Loop, Parse, var, `n
  215. {
  216. StringGetPos, p, A_LoopField, /
  217. StringLeft, n, A_LoopField, p
  218. n = %n%`n
  219. If (!InStr(s, n))
  220. s = %s%%n%
  221. }
  222. NumPut(0, var, 0, "UChar")
  223. s:=RegExReplace(s,"(^\s*|\s*$)")
  224. Return, s
  225. }
  226. /*
  227. Function: ini_MergeSections
  228. Merges two sections.
  229. Parameters:
  230. var - ini object
  231. from - section to move
  232. to - section to inherit new keys
  233. replace - true to replace existing keys from the destination section
  234. Returns:
  235. Number of keys moved.
  236. */
  237. ini_MergeSections(ByRef var, from, to, replace = true) {
  238. NumPut(160, var, 0, "UChar")
  239. f = %from%/
  240. t = %to%/
  241. StringGetPos, p, var, %t%
  242. StringMid, t, var, p + 1, StrLen(t)
  243. StringLen, l, f
  244. Loop, Parse, var, `n
  245. {
  246. If A_LoopField =
  247. Continue
  248. If (InStr(A_LoopField, f) == 1) {
  249. StringGetPos, p, A_LoopField, =
  250. StringMid, k, A_LoopField, l + 1, p - l
  251. StringMid, v, A_LoopField, p + 2
  252. e = `n%t%%k%=%v%`n
  253. StringGetPos, p, var, `n%t%%k%=
  254. If ErrorLevel = 0
  255. {
  256. If replace
  257. {
  258. p++
  259. StringGetPos, p1, var, `n, , p
  260. StringMid, x, var, p, p1 - p + 2
  261. StringReplace, var, var, %x%, %e%
  262. }
  263. }
  264. Else var = %var%%e%
  265. StringReplace, var, var, `n%f%%k%=%v%`n
  266. c++
  267. }
  268. }
  269. NumPut(0, var, 0, "UChar")
  270. Return, c
  271. }
  272. /*
  273. Function: ini_DeleteSection
  274. Get the complete list of sections.
  275. Parameters:
  276. var - ini object
  277. sec - name of section
  278. Returns:
  279. Number of child keys removed.
  280. */
  281. ini_DeleteSection(ByRef var, sec) {
  282. NumPut(160, var, 0, "UChar")
  283. n = %sec%/
  284. Loop, Parse, var, `n
  285. {
  286. If A_LoopField =
  287. Continue
  288. If (InStr(A_LoopField, n) == 1) {
  289. StringReplace, var, var, `n%A_LoopField%`n
  290. c++
  291. }
  292. }
  293. NumPut(0, var, 0, "UChar")
  294. Return, c
  295. }
  296. /*
  297. Function: ini_Duplicate
  298. Copies the INI variable to another.
  299. Parameters:
  300. var - ini object
  301. newVar - new ini object
  302. Returns:
  303. True if data was copied successfully, flase otherwise.
  304. */
  305. ini_Duplicate(ByRef var, ByRef newVar) {
  306. NumPut(160, var, 0, "UChar")
  307. newVar := var
  308. NumPut(0, newVar, 0, "UChar")
  309. NumPut(0, var, 0, "UChar")
  310. Return, VarSetCapacity(var) == VarSetCapacity(newVar)
  311. }
  312. /*
  313. Function: ini_ToXML
  314. Converts the INI structure to XML.
  315. Parameters:
  316. var - ini object
  317. ind - (optional) tag indentation character(s) (default: two spaces (" "))
  318. root - (optional) root element (default: ini)
  319. Remarks:
  320. Empty key nodes are automatically fused.
  321. Returns:
  322. An XML document.
  323. Example:
  324. > ini_Load(phpconfig, ProgramFiles . "\PHP\php.ini")
  325. > xmlsource := ini_ToXML(phpconfig)
  326. >
  327. > ; the following requires the xpath library:
  328. > xpath_load(xmldata, xmlsource)
  329. > MsgBox, % xpath(xmldata, "/ini/PHP/*[3]")
  330. */
  331. ini_ToXML(ByRef var, ind = " ", root = "ini") {
  332. NumPut(160, var, 0, "UChar")
  333. VarSetCapacity(x, StrLen(var) * 1.5)
  334. x = <?xml version="1.0" encoding="iso-8859-1"?>`n<%root%>
  335. Loop, Parse, var, `n, ?
  336. {
  337. If A_LoopField =
  338. Continue
  339. StringLeft, s, A_LoopField, b := InStr(A_LoopField, "/") - 1
  340. StringMid, k, A_LoopField, b += 2, InStr(A_LoopField, "=") - b
  341. StringTrimLeft, v, A_LoopField, InStr(A_LoopField, "=")
  342. If s != %ls%
  343. {
  344. If ls !=
  345. x = %x%`n%ind%</%ls%>
  346. x = %x%`n%ind%<%s%>
  347. ls = %s%
  348. }
  349. x = %x%`n%ind%%ind%<%k%>%v%</%k%>
  350. }
  351. NumPut(0, var, 0, "UChar")
  352. Return, RegExReplace(x . "`n" . ind . "</" . ls . ">`n</" . root . ">"
  353. , "<([\w:]+)([^>]*)>\s*<\/\1>", "<$1$2 />")
  354. }
  355. /*
  356. Function: ini_Save
  357. Save the INI content to a file,
  358. preserving the positions of previously existing sections and their keys.
  359. Parameters:
  360. var - ini object
  361. src - (optional) path to a file or source as text
  362. Returns:
  363. The output source if src is not a file path,
  364. otherwise a boolean indicating file write success or failure.
  365. */
  366. ini_Save(ByRef var, src = "") {
  367. NumPut(160, var, 0, "UChar")
  368. IfExist, %src%
  369. {
  370. src_file = 1
  371. FileRead, src, %src%
  372. }
  373. StringReplace, src, src, `r`n, `n, All
  374. StringReplace, src, src, `r, `n, All
  375. ls := ini_GetSections(var)
  376. _at = %A_LoopField%
  377. AutoTrim, On
  378. s =
  379. z =
  380. x = 1
  381. Loop, Parse, src, `n
  382. {
  383. l = %A_LoopField%
  384. If (InStr(l, "[") == 1) {
  385. StringReplace, ls, ls, %s%`n
  386. Loop, Parse, z, `n
  387. If A_LoopField
  388. d .= A_LoopField . " = " . ini_Read(var, s, A_LoopField) . "`n"
  389. s := SubStr(l, 2, -2), x := InStr(ls, s . "`n"), z := ini_GetKeys(var, s)
  390. If x
  391. d = %d%%l%`n
  392. Continue
  393. }
  394. If x
  395. {
  396. StringGetPos, p, l, =
  397. StringLeft, k, l, p
  398. k = %k%
  399. If k !=
  400. If k not contains /,`t, ,?#
  401. If (InStr(z, k . "`n")) {
  402. d .= k . " = " . ini_Read(var, s, k) . "`n"
  403. StringReplace, z, z, %k%`n
  404. Continue
  405. }
  406. d = %d%%l%`n
  407. }
  408. }
  409. Loop, Parse, ls, `n
  410. {
  411. s = %A_LoopField%
  412. If s !=
  413. d = %d%`n[%s%]`n
  414. z := ini_GetKeys(var, s)
  415. Loop, Parse, z, `n
  416. If A_LoopField !=
  417. d .= A_LoopField . " = " . ini_Read(var, s, A_LoopField) . "`n"
  418. }
  419. AutoTrim, %_at%
  420. NumPut(0, var, 0, "UChar")
  421. If (InStr(d, "`n") == 1)
  422. StringTrimLeft, d, d, 1
  423. StringTrimRight, d, d, 1
  424. If src_file = 1
  425. {
  426. FileDelete, %file%
  427. FileAppend, %d%, %file%
  428. Return, !ErrorLevel
  429. }
  430. Return, d
  431. }
  432. /*
  433. Function: ini_Load
  434. Load an INI file into memory so that it may be used with all the other functions in this library.
  435. Parameters:
  436. var - a reference to the loaded INI file as a variable (use for all other functions requiring this parameter)
  437. file - path to a file or source as text
  438. Returns:
  439. True if the file loaded successfully, false otherwise.
  440. */
  441. ini_Load(ByRef var, src) {
  442. IfExist, %src%
  443. FileRead, src, %src%
  444. If src =
  445. Return
  446. StringReplace, src, src, `r`n, `n, All
  447. StringReplace, src, src, `r, `n, All
  448. _at = %A_AutoTrim%
  449. AutoTrim, On
  450. Loop, Parse, src, `n
  451. {
  452. l = %A_LoopField%
  453. If (InStr(l, ";") == 1)
  454. Continue
  455. StringGetPos, p, l, `;
  456. If ErrorLevel = 0
  457. StringLeft, l, l, p
  458. If (InStr(l, "[") == 1) {
  459. s := SubStr(l, 2, -1)
  460. Continue
  461. }
  462. StringGetPos, p, l, =
  463. If pe = 0
  464. Continue
  465. StringLeft, k, l, p
  466. k = %k%
  467. If k =
  468. Continue
  469. ;~ MsgBox % A_LoopField
  470. ;~ If k contains /,`t, ,?#
  471. ;~ Continue
  472. StringTrimLeft, v, l, p + 1
  473. v = %v%
  474. StringLeft, a0, v, 1
  475. If a0 in ",'
  476. {
  477. StringRight, a1, v, 1
  478. If a0 = %a1%
  479. {
  480. StringTrimLeft, v, v, 1
  481. StringTrimRight, v, v, 1
  482. }
  483. }
  484. e = `n%s%/%k%=
  485. StringGetPos, p, d, %e%
  486. If ErrorLevel = 1
  487. d = %d%%e%%v%`n
  488. Else {
  489. StringGetPos, p1, d, =, , p
  490. StringGetPos, p2, d, `n, , p + 1
  491. d := SubStr(d, 1, p1 + 1) . v . SubStr(d, p2 + 1)
  492. }
  493. }
  494. AutoTrim, %_at%
  495. NumPut(0, var := " " . d, 0, "UChar")
  496. Return, true
  497. }
  498. _ini_escape(val) {
  499. StringReplace, val, val, \, \\, All
  500. StringReplace, val, val, `r, \r, All
  501. StringReplace, val, val, `n, \n, All
  502. Return, val
  503. }
  504. _ini_unescape(val) {
  505. StringReplace, val, val, \\, \, All
  506. Return, val
  507. }