AmourSpirit

MfMemoryString 20170430

Apr 30th, 2017
43
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 222.91 KB | None | 0 0
  1. ;{ License
  2. /* This file is part of Mini-Framework For AutoHotkey.
  3. *
  4. * Mini-Framework is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, version 2 of the License.
  7. *
  8. * Mini-Framework is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with Mini-Framework. If not, see <http://www.gnu.org/licenses/>.
  15. */
  16. ; End:License ;}
  17.  
  18. /*
  19. * Class MfMemoryString
  20. *
  21. * Methods
  22. * _NewEnum() Gets an enumerator that loops through the current instance char numbers
  23. * Append() Appends a new value to the current instance
  24. * AppendCharCode() Appends a Charcode number to current instance
  25. * AppendLine() Appends a new line value into the current instance
  26. * Clear() Clears the contents of the buffer removing all text
  27. * Clone() Clones the current instanece into a new stream
  28. * CompareOrdinal() Compares obj objects by evaluating the numeric values of the corresponding Char objects in obj.
  29. * CompareOrdinalSubString() Compares obj objects by evaluating the numeric values of the corresponding Char objects in obj.
  30. * Copy() Copies the Source MfMemoryString Chars instance to destination MfMemoryString
  31. * CopyFromIndex() Copies the Source MfMemoryString Chars to destination MfMemoryString
  32. * CopyToCharList() Copies the Source MfMemoryString Chars to destination MfCharList instance
  33. * CopyFromAddressToCharList() Copies the Source address Chars to destination MfCharList instance
  34. * CopyFromAddress() Copies the Source adress Chars instance to destination MfMemoryString
  35. * CopyAddressToCharList() Copies the Source address bytes to destination MfCharList
  36. * Difference() Gets the Difference between argument obj and argument this instance with an included Max Distance.
  37. * EndsWith() Gets a boolean value true or false if this instance ends with obj
  38. * Equals() Checks to see if obj is equals this instance
  39. * EqualsSubString() Compares a substring of current instance with a substrign of obj instance
  40. * Expand() Expands the current instance of MfMemoryString by AddChars ammount
  41. * FromAny() Creates a new instance of MfMemStrView from any source
  42. * FromBase64() Encodes Obj to base64 instance of MfMemoryString
  43. * FromByteList() Converts MfByteList into MfMemoryString instance
  44. * GetStringIgnoreNull() Gets an instance of MfMemoryString from current instance that has excluded all null values
  45. * IndexOf() Gets the zero based position of obj within the currrent instance from start
  46. * Insert() Inserts obj into current instance
  47. * LastIndexOf() Gets the zero based position of obj within the currrent instance from end
  48. * MoveCharsLeft() Move the characters in memory to the left overwriting any characters in position before move
  49. * MoveCharsRight() Move the characters in memory to the Right inserting null (unicode 0) from StartIndex to ShiftAmt
  50. * OverWrite() Overwrites the chars in this instance with the chars in obj instance
  51. * Replace() Replaces instances of oldValue with Instances of newValue
  52. * ReplaceAtIndex() Replaces as section of the string with newValue
  53. * Remove() Removes a number of chars from currrent instance
  54. * Reverse() Reverses the contentes of the currrent instance and returne it as a new instance
  55. * SetPosFromCharIndex() Moves the Location of Pos from index based upon char index
  56. * StartsWith() Gets if current instance starts with obj
  57. * SubString() Gets a new instance of MfMemoryString that represents a subset of the current instance chars
  58. * ToArray() Gets Byte array of current chars
  59. * ToBase64() Reads current instance and returns a new MfMemoryString instance endoced as UTF-8 base64
  60. * ToByteList() Creates an MfByteList of bytes from current instance of MfMemoryString
  61. * ToCharList() Gets a copy of the current instance as MfCharList
  62. * ToString() Retunrs the contents of the current instance as a string var
  63. * Trim() Trims TrimChars or whitespace from this instance start and end
  64. * TrimBuffer() Trims the internal buffer to the size of the current chars
  65. * TrimStart() Trims TrimChars or whitespace from this instance start
  66. * TrimStart() Trims TrimChars or whitespace from this instance end
  67. *
  68. * Properties
  69. * Byte - Gets the Byte value at the value of index
  70. * BufferPtr - Gets the Buffer memory addres pointer for this instance
  71. * Length - Gets the length of the current instance chars
  72. * Capacity - Gets the Size of the current instance in bytes
  73. * CharCapacity - Gets the Capacity value in Chars for the current instance
  74. * FreeCapacity - Gets the FreeCapacity of the current instance in bytes
  75. * FreeCharCapacity - Gets the number of characters that can be added to the current instance wihtout overflow
  76. * UsedCapacity - Gets the UsedCapacity in bytes associated with the this instance
  77. * Size - Gets the Size in bytes of the current buffer
  78. *
  79. * Internal class for working dircetly with memory strings
  80. */
  81. class MfMemoryString extends MfObject
  82. {
  83. m_Encoding := ""
  84. m_EncodingName := ""
  85. m_MemView := ""
  86. m_CharCount := 0
  87. m_BytesPerChar := ""
  88. m_FillBytes := ""
  89. m_nl := ""
  90. m_sType := ""
  91. ;{ Constructor
  92. /*
  93. Constructor(Size, FillByte:=0, Encoding="")
  94. Construct a new instance of the memory buffer Optionally setting Fillbytes and Encoding
  95. Example:
  96. mStr := new MfMemoryString(100,0,"UTF-16")
  97. mstr..Append("The Quick Brown fox jumped over the lazy Dog.")
  98. MsgBox % mStr.Char[7]
  99.  
  100. Constructor(Size, CharPos:="", Encoding="", Ptr)
  101. Construct a new instance of the memory buffer Optionally setting CharPos and Encoding and set the buffer
  102. the the address of external var or string represented by Ptr
  103. This method is mostly to work with existing string quicly by read then in memory but has other uses as well.
  104. Example:
  105. MyStr := "Hello World"
  106. mStr := new MfMemoryString(strlen(MyStr),,,&MyStr)
  107. MsgBox % mStr.Char[7]
  108.  
  109. Parameters:
  110. Size
  111. The buffer size in chars of the instance or Address
  112. Size has no real limits unless Address is included.
  113. If Address is included then the size must match the addres in chars
  114. FillByte
  115. The byte value to write into memory. Default is 0
  116. Fillbyte is ignored when Ptr is included
  117. CharPos
  118. Optional: The Positions to see the Char locatoin of the pointer
  119. applies only when Ptr is included
  120. If Omitted then Char Pos will default to the size of the buffer
  121. If included then Encoding become a factor nad the encoding parameter should be set
  122. Encoding
  123. Optional - The encoding for the instane.
  124. If Omitted then encoding will be UTF-16 with two bytes per char 0xFFFF for unicode versions of AutoHotkey;
  125. Otherwise will be cp1252 aand One Byte per char 0xFF
  126. Ptr
  127. Optional Memory Address to existing var.
  128. If Omitted then intrenal var is created that can hold the value of Size in chars.
  129. If Included then it is Important that the size match the address properly.
  130. If Address is to an existing string then size must match the len of the string
  131. When included Fillbyte is ignored
  132. Example:
  133. mStr := new MfMemoryString(strlen(MyStr),,,&MyStr)
  134.  
  135.  
  136. */
  137. __New(args*) {
  138. base.__New()
  139. ;Size, FillByte:=0, Encoding=""
  140. ;Size, Pos:=-1, Encoding="", Ptr=0
  141. cnt := MfParams.GetArgCount(args*)
  142. if (cnt = 0 || cnt > 4)
  143. {
  144. e := new MfNotSupportedException(MfEnvironment.Instance.GetResourceString("NotSupportedException_MethodOverload", A_ThisFunc))
  145. e.SetProp(A_LineFile, A_LineNumber, MethodName)
  146. throw e
  147. }
  148. Size := args[1]
  149. if (MfNull.IsNull(Size))
  150. {
  151. ex := new MfArgumentNullException("Size")
  152. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  153. throw ex
  154. }
  155. try
  156. {
  157. Size := MfInteger.GetValue(Size)
  158. }
  159. catch e
  160. {
  161. ex := new MfArgumentException(MfEnvironment.Instance.GetResourceString("InvalidCastException_ValueToInteger"), "Size")
  162. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  163. throw ex
  164. }
  165. if (Size < 0)
  166. {
  167. ex := new MfArgumentOutOfRangeException("Size", MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_IndexString"))
  168. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  169. throw ex
  170. }
  171.  
  172. Encoding := ""
  173. if (cnt > 2)
  174. {
  175. Encoding := args[3]
  176. }
  177.  
  178. if (MfString.IsNullOrEmpty(Encoding))
  179. {
  180. If (A_IsUnicode)
  181. {
  182. Encoding := "UTF-16"
  183. }
  184. else
  185. {
  186. Encoding := "cp1252"
  187. }
  188. }
  189. ; UTF-32 not really supported but here and partially working
  190. if (Encoding = "UTF-32")
  191. {
  192. this.m_BytesPerChar := 4
  193. this.m_sType := "UInt"
  194. }
  195. else if (Encoding = "UTF-16" || Encoding = "CP1200")
  196. {
  197. this.m_BytesPerChar := 2
  198. this.m_sType := "UShort"
  199. }
  200. else
  201. {
  202. this.m_BytesPerChar := 1
  203. this.m_sType := "UChar"
  204. }
  205.  
  206. this.m_nl := MfEnvironment.Instance.NewLine
  207. StringReplace, _Encoding, Encoding, -, , ALL
  208. this.m_Encoding := Encoding
  209. this.m_EncodingName := _Encoding
  210.  
  211. if (cnt > 3)
  212. {
  213. this.m_FillBytes := 0
  214.  
  215. try
  216. {
  217. Ptr := MfInt64.GetValue(args[4])
  218. }
  219. catch e
  220. {
  221. ex := new MfArgumentException(MfEnvironment.Instance.GetResourceString("InvalidCastException_ValueToInt64"), "Ptr")
  222. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  223. Throw ex
  224. }
  225.  
  226. size := (size + 1) * this.m_BytesPerChar
  227. CharPos := MfInteger.GetValue(args[2], -1)
  228.  
  229. this.m_MemView := new MfMemStrView(size, this.m_FillBytes, this.m_Encoding, Ptr)
  230.  
  231. if (CharPos < 0)
  232. {
  233. this.m_MemView.Pos := this.m_MemView.Size
  234. }
  235. Else
  236. {
  237. this.m_MemView.Pos := MfMath.Min(((CharPos + this.m_BytesPerChar) * this.m_BytesPerChar), this.m_MemView.Size)
  238. }
  239. this.m_CharCount := this.m_MemView.GetCharCount()
  240. }
  241. Else
  242. {
  243. if (cnt > 1)
  244. {
  245. this.m_FillBytes := MfInteger.GetValue(args[2], 0)
  246. }
  247. else
  248. {
  249. this.m_FillBytes := 0
  250. }
  251. size := (size + 1) * this.m_BytesPerChar
  252. this.m_MemView := new MfMemStrView(size, this.m_FillBytes, this.m_Encoding)
  253. }
  254. }
  255. ; End:Constructor ;}
  256. ;{ _NewEnum
  257. /*
  258. Method: _NewEnum()
  259. Overrides MfEnumerableBase._NewEnum()
  260. _NewEnum()
  261. Returns a new enumerator to enumerate this object's key-value pairs.
  262. This method is usually not called directly, but by the for-loop or by GetEnumerator()
  263. */
  264. _NewEnum() {
  265. return new MfMemStrView.Enumerator(this.m_MemView)
  266. }
  267. ; End:_NewEnum ;}
  268. ;{ Append
  269. /*
  270. Method: Append()
  271.  
  272. Append()
  273. Appends a new value to the current instance
  274. Parameters:
  275. obj
  276. The value to append to the instance
  277. Can be instance of MfMemoryString or any object derived from MfObject
  278. Returns:
  279. Returns this instance
  280. Throws:
  281. Throws MfArgumentException
  282. */
  283. Append(obj) {
  284. if (IsObject(obj))
  285. {
  286. if (MfObject.IsObjInstance(obj, MfMemoryString))
  287. {
  288. if (obj.m_CharCount = 0)
  289. {
  290. return this
  291. }
  292. chars := this.m_MemView.Append(obj.m_MemView)
  293. }
  294. else if (MfObject.IsObjInstance(obj, MfString))
  295. {
  296. if (obj.Length = 0)
  297. {
  298. return this
  299. }
  300. chars := this.m_MemView.AppendString(obj)
  301. }
  302. else if (MfObject.IsObjInstance(obj, MfObject))
  303. {
  304. chars := this.m_MemView.Append(obj)
  305. }
  306. Else
  307. {
  308. ex := new MfArgumentException(MfEnvironment.Instance.GetResourceString("NonMfObjectException_General"), "obj")
  309. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  310. throw ex
  311. }
  312. }
  313. else
  314. {
  315. chars := this.m_MemView.AppendString(obj)
  316. }
  317. this.m_CharCount += chars
  318. return this
  319. }
  320. ; End:Append ;}
  321. ;{ AppendCharCode
  322. /*
  323. Method: AppendCharCode()
  324.  
  325. AppendCharCode()
  326. Appends a Charcode number to current instance
  327. Parameters:
  328. cc
  329. Char code as integer number to add
  330. repeatCount
  331. The number of times to repeat the adding of the charcode
  332. Default value is 1
  333. Returns:
  334. Returns the number of chars in this instance
  335. Throws:
  336. Throws MfArgumentException if cc is outsite of current encoding range
  337. Remarks:
  338. cc must be a positive number
  339. */
  340. AppendCharCode(cc, repeatCount=1) {
  341. Count := MfInteger.GetValue(repeatCount, 1)
  342. If (repeatCount < 1)
  343. {
  344. return this
  345. }
  346. cc := MfInt64.GetValue(cc)
  347. i := 0
  348. while (i < repeatCount)
  349. {
  350. this.m_CharCount += this.m_MemView.AppendCharCode(cc)
  351. i++
  352. }
  353. return this
  354. }
  355. ; End:AppendCharCode ;}
  356. ;{ AppendLine
  357. /*
  358. Method: AppendLine()
  359.  
  360. AppendLine()
  361. Appends a new line value into the current instance
  362. Returns:
  363. Returns this instance after new line is appended
  364. */
  365. AppendLine() {
  366. chars := this.m_MemView.AppendString(this.m_nl)
  367. this.m_CharCount += chars
  368. return this
  369. }
  370. ; End:AppendLine ;}
  371. /*
  372. Method: Clear()
  373.  
  374. Clear()
  375. Clears the contents of the buffer removing all text
  376. Returns:
  377. Returns this instance after has taken place
  378. */
  379. ;{ Clear
  380. Clear() {
  381. this.m_CharCount := 0
  382. this.m_MemView := ""
  383. this.m_MemView := new MfMemStrView(this.Capacity, this.m_FillBytes, this.m_Encoding)
  384. return this
  385. }
  386. ; End:Clear ;}
  387. ;{ Clone
  388. /*
  389. Method: Clone()
  390.  
  391. Clone()
  392. Clones the current instanece into a new stream
  393. Returns:
  394. Returns an new instance with itentical contentents
  395. Remarks:
  396. Returns result contents are in a new new memory stream
  397. */
  398. Clone() {
  399. objMemRW := new MfMemoryString(0, this.m_FillBytes, this.m_Encoding)
  400. objMemRW.m_MemView := ""
  401. objMemRW.m_MemView := this.m_MemView.Clone()
  402. objMemRW.m_CharCount := this.m_CharCount
  403. return objMemRW
  404. }
  405. ; End:Clone ;}
  406. ;{ CompareOrdinal
  407. /*
  408. Method: CompareOrdinal()
  409.  
  410. CompareOrdinal()
  411. Compares obj objects by evaluating the numeric values of the corresponding Char objects in obj.
  412. Parameters:
  413. obj
  414. The value compare
  415. Can be instance of MfMemoryString or MfMemStrView or any object derived from MfObject
  416. IgnoreCase
  417. If true comparison must ignore case, then perform an ordinal comparison.
  418. This technique is equivalent to converting the string to uppercase using the invariant culture
  419. and then performing an ordinal comparison on the result.
  420. Default value is false
  421. Returns:
  422. An integer that indicates the lexical relationship between the two comparands.
  423. Less than zero this instance is less than strB.
  424. Zero this instance and strB are equal.
  425. Greater than zero this instance is greater than strB.
  426. Throws:
  427. Throws MfException if
  428. Remarks:
  429. When IgnoreCase is true this method performs a case-sensitive comparison using ordinal sort rules.
  430. Indicates that the string comparison must use successive Unicode UTF-8 or UTF-16 encoded values of the string
  431. (code unit by code unit comparison), leading to a fast comparison but one that is culture-insensitive.
  432. */
  433. CompareOrdinal(obj, ignoreCase=false) {
  434. if (MfNull.IsNull(obj))
  435. {
  436. return 1
  437. }
  438. mStr := this._FromAny(obj)
  439. ignoreCase := MfBool.GetValue(ignoreCase, false)
  440. If (ignoreCase)
  441. {
  442. result := MfMemStrView.CompareOrdinalIgnoreCase(this.m_MemView, mStr.m_MemView)
  443. }
  444. else
  445. {
  446. result := MfMemStrView.CompareOrdinal(this.m_MemView, mStr.m_MemView)
  447. }
  448. return result
  449.  
  450. }
  451. ; End:CompareOrdinal ;}
  452. ;{ CompareOrdinalSubString
  453. /*
  454. Method: CompareOrdinalSubString()
  455.  
  456. CompareOrdinalSubString()
  457. Compares obj objects by evaluating the numeric values of the corresponding Char objects in obj.
  458. Parameters:
  459. obj
  460. The value to compare
  461. Can be instance of MfMemoryString or MfMemStrView or any object derived from MfObject
  462. objIndex
  463. The index in obj to start comparing to this instance
  464. index
  465. The index of the current instance to start comparing
  466. length
  467. The length of the string to compare, this is the length of number of characters
  468. Default value is -1. If default then length is converted to the length of the shortest value after index of this and obj.
  469. IgnoreCase
  470. If true comparison must ignore case, then perform an ordinal comparison.
  471. This technique is equivalent to converting the string to uppercase using the invariant culture
  472. and then performing an ordinal comparison on the result.
  473. Default value is false
  474. Returns:
  475. Returns
  476. Throws:
  477. Throws MfException if
  478. Remarks:
  479. If CompareOrdinalSubString
  480. */
  481. CompareOrdinalSubString(obj, objIndex, index, length=-1, ignoreCase=false) {
  482. if (MfNull.IsNull(obj))
  483. {
  484. return 1
  485. }
  486. objIndex := MfInteger.GetValue(objIndex)
  487. index := MfInteger.GetValue(index)
  488. length := MfInteger.GetValue(length)
  489. ignoreCase := MfBool.GetValue(ignoreCase, false)
  490. mStr := this._FromAny(obj)
  491. result := MfMemStrView.CompareOrdinalSub(this.m_MemView, index, mStr.m_MemView, objIndex, length, ignoreCase)
  492. return result
  493. }
  494. ; End:CompareOrdinalSubString ;}
  495. ;{ Copy
  496. /*
  497. Method: Copy()
  498.  
  499. Copy()
  500. Copies the Source MfMemoryString Chars instance to destination MfMemoryString
  501. Parameters:
  502. sourceMfMemoryString
  503. Source instance of MfMemoryString
  504. destinationMfMemoryString
  505. Destination instance of MfMemoryString
  506. destinationIndex
  507. The Destination index to start copying into
  508. count
  509. The Number of chars to copy
  510. Throws:
  511. Throws MfArgumentException, MfArgumentOutOfRangeException, MfException
  512. Remarks:
  513. Method does Ajuust Pos and charcount of sourceMfMemoryString or destinationMfMemoryString alhougth the new Pos is not guaranteed to be correct.
  514. Caller of method should ajusct Pos and Char coumt manually
  515. Static Method
  516. */
  517. Copy(sourceMfMemoryString, destinationMfMemoryString, destinationIndex, count) {
  518. this.VerifyIsNotInstance(A_ThisFunc, A_LineFile, A_LineNumber, A_ThisFunc)
  519.  
  520. if(!MfObject.IsObjInstance(sourceMfMemoryString, MfMemoryString))
  521. {
  522. ex := new MfArgumentException(MfEnvironment.Instance.GetResourceString("NullReferenceException_Object_Param", "MfMemoryString"), "sourceMfMemoryString")
  523. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  524. throw ex
  525. }
  526. if(!MfObject.IsObjInstance(destinationMfMemoryString, MfMemoryString))
  527. {
  528. ex := new MfArgumentException(MfEnvironment.Instance.GetResourceString("NullReferenceException_Object_Param", "MfMemoryString"), "destinationMfMemoryString")
  529. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  530. throw ex
  531. }
  532. destinationIndex := MfInteger.GetValue(destinationIndex)
  533. count := MfInteger.GetValue(count)
  534. if (count <= 0)
  535. {
  536. return
  537. }
  538. if (destinationIndex < 0)
  539. {
  540. ex := new MfArgumentOutOfRangeException("destinationIndex", MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_MustBePositive", "destinationIndex"))
  541. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  542. throw ex
  543. }
  544.  
  545. BytesPerChar := sourceMfMemoryString.m_BytesPerChar
  546. destinationIndex := destinationIndex * BytesPerChar
  547. count := count * BytesPerChar
  548. try
  549. {
  550. MfMemStrView.Copy(sourceMfMemoryString.m_MemView, destinationMfMemoryString.m_MemView, destinationIndex, count)
  551. destinationMfMemoryString.m_CharCount := destinationMfMemoryString.m_MemView.GetCharCount()
  552. }
  553. catch e
  554. {
  555. ex := new MfException(MfEnvironment.Instance.GetResourceString("Exception_Error", A_ThisFunc), e)
  556. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  557. throw ex
  558. }
  559.  
  560. }
  561. ; End:Copy ;}
  562. ;{ CopyFromAddress
  563. /*
  564. Method: CopyFromAddress()
  565.  
  566. CopyFromAddress()
  567. Copies the Source adress Chars instance to destination MfMemoryString
  568. Parameters:
  569. SourceAddress
  570. Source address to copy chars from
  571. destinationMfMemoryString
  572. Destination instance of MfMemoryString
  573. destinationIndex
  574. The Destination index to start copying into
  575. count
  576. The Number of chars to copy
  577. Throws:
  578. Throws MfArgumentException, MfArgumentOutOfRangeException, MfException
  579. Remarks:
  580. Method does Ajuust Pos and charcount of sourceMfMemoryString or destinationMfMemoryString alhougth the new Pos is not guaranteed to be correct.
  581. Caller of method should ajusct Pos and Char coumt manually
  582. Static Method
  583. */
  584. CopyFromAddress(SourceAddress, ByRef destinationMfMemoryString, destinationIndex, count) {
  585. this.VerifyIsNotInstance(A_ThisFunc, A_LineFile, A_LineNumber, A_ThisFunc)
  586.  
  587. if(!MfObject.IsObjInstance(destinationMfMemoryString, MfMemoryString))
  588. {
  589. ex := new MfArgumentException(MfEnvironment.Instance.GetResourceString("NullReferenceException_Object_Param", "MfMemoryString"), "destinationMfMemoryString")
  590. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  591. throw ex
  592. }
  593. destinationIndex := MfInteger.GetValue(destinationIndex)
  594. count := MfInteger.GetValue(count)
  595.  
  596. if (count <= 0)
  597. {
  598. return
  599. }
  600. if (destinationIndex < 0)
  601. {
  602. ex := new MfArgumentOutOfRangeException("destinationIndex", MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_MustBePositive", "destinationIndex"))
  603. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  604. throw ex
  605. }
  606.  
  607. BytesPerChar := destinationMfMemoryString.m_BytesPerChar
  608. destinationIndex := destinationIndex * BytesPerChar
  609. count := count * BytesPerChar
  610. try
  611. {
  612. MfMemStrView.CopyFromAddress(SourceAddress, destinationMfMemoryString.m_MemView, destinationIndex, count)
  613. destinationMfMemoryString.m_CharCount := destinationMfMemoryString.m_MemView.GetCharCount()
  614.  
  615. }
  616. catch e
  617. {
  618. ex := new MfException(MfEnvironment.Instance.GetResourceString("Exception_Error", A_ThisFunc), e)
  619. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  620. throw ex
  621. }
  622.  
  623. }
  624. ; End:Copy ;}
  625. ;{ CopyFromAddressToCharList
  626. /*
  627. Method: CopyFromAddressToCharList()
  628.  
  629. CopyFromAddressToCharList()
  630. Copies the Source address Chars to destination MfCharList instance
  631. Parameters:
  632. SourceAddress
  633. Source address to copy chars from
  634. CharList
  635. Destination instance of MfCharList
  636. destinationIndex
  637. The Destination index to start copying into
  638. count
  639. The Number of Chars to copy
  640. Throws:
  641. Throws MfArgumentOutOfRangeException, MfException
  642. Remarks:
  643. Static method
  644. */
  645. CopyFromAddressToCharList(SourceAddress, CharList, destinationIndex, count) {
  646. this.VerifyIsNotInstance(A_ThisFunc, A_LineFile, A_LineNumber, A_ThisFunc)
  647. destinationIndex := MfInteger.GetValue(destinationIndex)
  648. count := MfInteger.GetValue(count)
  649.  
  650. if (count <= 0)
  651. {
  652. return
  653. }
  654. if (destinationIndex < 0)
  655. {
  656. ex := new MfArgumentOutOfRangeException("destinationIndex", MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_MustBePositive", "destinationIndex"))
  657. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  658. throw ex
  659. }
  660. try
  661. {
  662. MfMemStrView.CopyFromAddressToCharList(SourceAddress, CharList, destinationIndex, count)
  663.  
  664. }
  665. catch e
  666. {
  667. ex := new MfException(MfEnvironment.Instance.GetResourceString("Exception_Error", A_ThisFunc), e)
  668. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  669. throw ex
  670. }
  671. }
  672. ; End:CopyFromAddressToCharList ;}
  673. ;{ CopyToCharList
  674. /*
  675. Method: CopyToCharList()
  676.  
  677. CopyToCharList()
  678. Copies the Source MfMemoryString Chars to destination MfCharList instance
  679. Parameters:
  680. sourceMfMemoryString
  681. Source MfMemoryString instance of chars to copy
  682. sourceIndex
  683. The Start index withn the source to start the copy from
  684. CharList
  685. Destination instance of MfCharList
  686. destinationIndex
  687. The Destination index to start copying into
  688. count
  689. The Number of Chars to copy
  690. Throws:
  691. Throws MfArgumentOutOfRangeException, MfException, MfFormatException
  692. Remarks:
  693. Static method
  694. */
  695. CopyToCharList(sourceMfMemoryString, sourceIndex, CharList, destinationIndex, count) {
  696. this.VerifyIsNotInstance(A_ThisFunc, A_LineFile, A_LineNumber, A_ThisFunc)
  697. destinationIndex := MfInteger.GetValue(destinationIndex)
  698. count := MfInteger.GetValue(count)
  699.  
  700. if (count <= 0)
  701. {
  702. return
  703. }
  704. if(!MfObject.IsObjInstance(sourceMfMemoryString, MfMemoryString))
  705. {
  706. ex := new MfArgumentException(MfEnvironment.Instance.GetResourceString("NullReferenceException_Object_Param", "MfMemoryString"), "sourceMfMemoryString")
  707. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  708. throw ex
  709. }
  710. if (!(sourceMfMemoryString.m_Encoding = CharList.m_Encoding))
  711. {
  712. ex := new MfFormatException(MfEnvironment.Instance.GetResourceString("Format_Encoding_MisMatch"))
  713. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  714. throw ex
  715. }
  716. if (destinationIndex < 0)
  717. {
  718. ex := new MfArgumentOutOfRangeException("destinationIndex", MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_MustBePositive", "destinationIndex"))
  719. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  720. throw ex
  721. }
  722. BytesPerChar := sourceMfMemoryString.m_BytesPerChar
  723. try
  724. {
  725. if (sourceIndex <= sourceMfMemoryString.m_CharCount && (sourceIndex + count) <= sourceMfMemoryString.m_CharCount)
  726. {
  727. SourceAddress := sourceMfMemoryString.m_MemView[] + (sourceIndex * BytesPerChar)
  728. MfMemStrView.CopyFromAddressToCharList(SourceAddress, CharList, destinationIndex, count)
  729. }
  730. else
  731. {
  732. ex := new MfArgumentOutOfRangeException("sourceIndex", MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_Index"))
  733. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  734. throw ex
  735. }
  736. }
  737. catch e
  738. {
  739. if (e.Source = A_ThisFunc)
  740. {
  741. throw e
  742. }
  743. else
  744. {
  745. ex := new MfException(MfEnvironment.Instance.GetResourceString("Exception_Error", A_ThisFunc), e)
  746. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  747. throw ex
  748. }
  749. }
  750. }
  751. ; End:CopyToCharList ;}
  752. ;{ CopyFromIndex
  753. /*
  754. Method: CopyFromIndex()
  755.  
  756. CopyFromIndex()
  757. Copies the Source MfMemoryString Chars to destination MfMemoryString
  758. Parameters:
  759. sourceMfMemoryString
  760. Source MfMemoryString instance of chars to copy
  761. destinationMemView
  762. Destination instance of MfMemoryString
  763. destinationIndex
  764. The Destination index to start copying into
  765. count
  766. The Number of chars to copy
  767. Throws:
  768. Throws MfArgumentOutOfRangeException, MfException
  769. Remarks:
  770. If destinationMemView.Pos is less then destinationIndex + count it is adjusted to the position of destinationIndex + count
  771. Static Method
  772. */
  773. CopyFromIndex(sourceMfMemoryString, sourceIndex, destinationMfMemoryString, destinationIndex, count) {
  774. this.VerifyIsNotInstance(A_ThisFunc, A_LineFile, A_LineNumber, A_ThisFunc)
  775. count := MfInteger.GetValue(count)
  776. if (count <= 0)
  777. {
  778. return
  779. }
  780. if(!MfObject.IsObjInstance(sourceMfMemoryString, MfMemoryString))
  781. {
  782. ex := new MfArgumentException(MfEnvironment.Instance.GetResourceString("NullReferenceException_Object_Param", "MfMemoryString"), "sourceMfMemoryString")
  783. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  784. throw ex
  785. }
  786. if(!MfObject.IsObjInstance(destinationMfMemoryString, MfMemoryString))
  787. {
  788. ex := new MfArgumentException(MfEnvironment.Instance.GetResourceString("NullReferenceException_Object_Param", "MfMemoryString"), "destinationMfMemoryString")
  789. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  790. throw ex
  791. }
  792. destinationIndex := MfInteger.GetValue(destinationIndex)
  793. count := MfInteger.GetValue(count)
  794.  
  795. if (destinationIndex < 0)
  796. {
  797. ex := new MfArgumentOutOfRangeException("destinationIndex", MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_MustBePositive", "destinationIndex"))
  798. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  799. throw ex
  800. }
  801.  
  802. BytesPerChar := sourceMfMemoryString.m_BytesPerChar
  803.  
  804.  
  805. try
  806. {
  807. if (sourceIndex <= sourceMfMemoryString.m_CharCount && (sourceIndex + count) <= sourceMfMemoryString.m_CharCount)
  808. {
  809. SourceAddress := sourceMfMemoryString.m_MemView[] + (sourceIndex * BytesPerChar)
  810. count := count * BytesPerChar
  811. destinationIndex := destinationIndex * BytesPerChar
  812.  
  813. MfMemStrView.CopyFromAddress(SourceAddress, destinationMfMemoryString.m_MemView, destinationIndex, count)
  814. destinationMfMemoryString.Pos += -count
  815. destinationMfMemoryString.m_CharCount := destinationMfMemoryString.m_MemView.GetCharCount()
  816.  
  817. }
  818. else
  819. {
  820. ex := new MfArgumentOutOfRangeException("sourceIndex", MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_Index"))
  821. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  822. throw ex
  823. }
  824. }
  825. catch e
  826. {
  827. if (e.Source = A_ThisFunc)
  828. {
  829. throw e
  830. }
  831. else
  832. {
  833. ex := new MfException(MfEnvironment.Instance.GetResourceString("Exception_Error", A_ThisFunc), e)
  834. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  835. throw ex
  836. }
  837. }
  838. }
  839. ; End:CopyFromIndex ;}
  840. ;{ Difference
  841. /*
  842. Method: Difference()
  843. Gets the Difference between argument obj and argument this instance with an included Max Distance.
  844. obj
  845. The value to compare
  846. Can be instance of MfMemoryString or MfMemStrView or any object derived from MfObject
  847. maxDistance
  848. Integer tells the algorithm to stop if the strings are already too different.
  849. Returns:
  850. Returns returns the difference between the strings as a float between 0 and 1.
  851. 0 means strings are identical. 1 means they have nothing in common.
  852. */
  853. Difference(obj, maxOffset=5) {
  854. ; test show to be 3 to 6 thmes faster then old string method depending on length of String
  855. ; short string show a bigger difference
  856. if (MfNull.IsNull(obj))
  857. {
  858. return 1.0
  859. }
  860.  
  861. wf := A_FormatFloat
  862. SetFormat, FloatFast, 0.15
  863. try
  864. {
  865. maxOffset := Abs(MfInteger.GetValue(maxOffset, 5))
  866. mStr := this._FromAny(obj)
  867. result := MfMemStrView.Diff(this.m_MemView, mStr.m_MemView, maxOffset)
  868. return result
  869. }
  870. catch e
  871. {
  872. ex := new MfException(MfEnvironment.Instance.GetResourceString("Exception_Error", A_ThisFunc), e)
  873. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  874. throw ex
  875. }
  876. finally
  877. {
  878. SetFormat, FloatFast, %wf%
  879. }
  880.  
  881. }
  882. ; End:Difference ;}
  883. ;{ EndsWith
  884. /*
  885. Method: EndsWith()
  886.  
  887. EndsWith()
  888. Gets a boolean value true or false if this instance ends with obj
  889. Parameters:
  890. obj
  891. The value to compare with end
  892. Can be instance of MfMemoryString or MfMemStrView or any object derived from MfObject
  893. IgnoreCase
  894. Boolean value. If true case is ignored; Otherwise case is case is not ignored
  895. Returns:
  896. Returns true if current instance ends with obj; Otherwise false
  897. */
  898. EndsWith(obj, IgnoreCase=true) {
  899. if (MfNull.IsNull(obj))
  900. {
  901. return false
  902. }
  903. IgnoreCase := MfBool.GetValue(IgnoreCase, true)
  904. mStr := this._FromAny(obj)
  905. if (mStr.m_MemView.Pos = 0)
  906. {
  907. return false
  908. }
  909. if (mStr.m_MemView.Pos > this.m_MemView.Pos)
  910. {
  911. return false
  912. }
  913. result := this.m_MemView.EndsWithFromPos(mStr.m_MemView, IgnoreCase)
  914.  
  915. return result
  916. }
  917. ;{ EndsWith
  918. ;{ Equals
  919. /*
  920. Method: Equals()
  921.  
  922. Equals()
  923. Checks to see if obj is equals this instance
  924. Parameters:
  925. obj
  926. The value to compare
  927. Can be instance of MfMemoryString or MfMemStrView or any object derived from MfObject
  928. IgnoreCase
  929. Boolean value. If true case is ignored; Otherwise case is case is not ignored
  930. Returns:
  931. Returns true if obj is equal to this instance, Otherwide false.
  932. Throws:
  933. Throws MfArgumentException
  934. */
  935. Equals(obj, IgnoreCase=true) {
  936. IgnoreCase := MfBool.GetValue(IgnoreCase, true)
  937. mStr := this._FromAny(obj)
  938. return this.m_MemView.Equals(mStr.m_MemView, IgnoreCase)
  939. }
  940. ; End:Equals ;}
  941. ;{ EqualsSubString
  942. /*
  943. Method: EqualsSubString()
  944.  
  945. EqualsSubString()
  946. Compares a substring of current instance with a substrign of obj instance
  947. Parameters:
  948. obj
  949. The value to compare
  950. Can be instance of MfMemoryString or MfMemStrView or any object derived from MfObject
  951. objIndex
  952. The starting index of obj get substring from
  953. index
  954. The starting index of currentinstance to get substring from
  955. length
  956. The length of the substring to compare.
  957. Optional Value, If ommited or value is less then zero then the length of the shorotest string
  958. minuse is index becomes the length.
  959. IgnoreClase
  960. Optional - Default value is true
  961. If false then Case is considered; Otherwise case is ignored.
  962. Returns:
  963. Returns
  964. Throws:
  965. Throws MfException if
  966. Remarks:
  967. If EqualsSubString
  968. */
  969. EqualsSubString(obj, objIndex, index, length=-1, IgnoreCase=true) {
  970. IgnoreCase := MfBool.GetValue(IgnoreCase, true)
  971. objIndex := MfInteger.GetValue(objIndex)
  972. index := MfInteger.GetValue(index)
  973. length := MfInteger.GetValue(length, -1)
  974. if (Length = 0)
  975. {
  976. return false
  977. }
  978. if ((index < 0) || (index >= this.m_CharCount))
  979. {
  980. ex := new MfArgumentOutOfRangeException("index", MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_IndexLength"))
  981. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  982. throw ex
  983. }
  984. mStr := this._FromAny(obj)
  985. if (mStr.m_CharCount = 0)
  986. {
  987. return false
  988. }
  989. if ((objIndex < 0) || (objIndex >= mStr.m_CharCount))
  990. {
  991. ex := new MfArgumentOutOfRangeException("objIndex", MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_IndexLength"))
  992. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  993. throw ex
  994. }
  995. if (Length < 0)
  996. {
  997. Length := MfMath.Min(this.m_CharCount - index, mStr.m_CharCount - objIndex)
  998. }
  999. If (this.m_CharCount < (index + length))
  1000. {
  1001. return false
  1002. }
  1003. If (mStr.m_CharCount < (objIndex + length))
  1004. {
  1005. return false
  1006. }
  1007. return MfMemStrView.EqualsSubString(this.m_MemView, index, mStr.m_MemView, objIndex, Length, IgnoreCase)
  1008. }
  1009. ; End:EqualsSubString ;}
  1010. ;{ Expand
  1011. /*
  1012. Method: Expand()
  1013.  
  1014. Expand()
  1015. Expands the current instance of MfMemoryString by AddChars ammount
  1016. Parameters:
  1017. AddChars
  1018. The number of Chars to add to the current instance
  1019. Returns:
  1020. Returns current instance
  1021. Throws:
  1022. Throws MfArgumentNullException if AddChars is null
  1023. Throws MfArgumentException if AddChars cannot be converted into valid integer or AddBytes is less then 0
  1024. */
  1025. Expand(AddChars) {
  1026. if (MfNull.IsNull(AddChars))
  1027. {
  1028. ex := new MfArgumentNullException("AddChars")
  1029. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  1030. throw ex
  1031. }
  1032. i := MfInteger.GetValue(AddChars)
  1033. if (i < 0)
  1034. {
  1035. ex := new MfArgumentException(MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_NegativeCount"), "AddChars")
  1036. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  1037. throw ex
  1038. }
  1039. if (i = 0)
  1040. {
  1041. return this
  1042. }
  1043. i := i * this.m_BytesPerChar
  1044. this.m_MemView.Expand(i)
  1045. return this
  1046.  
  1047. }
  1048. ; End:Expand ;}
  1049. ;{ FromAny
  1050. /*
  1051. Method: FromAny()
  1052.  
  1053. FromAny()
  1054. Creates a new instance of MfMemStrView from any source
  1055. Parameters:
  1056. x
  1057. The object or var to create the instance from
  1058. Returns:
  1059. Returns new instance of MfMemoryString containing the value of x
  1060. */
  1061. FromAny(x, encoding="UTF-16") {
  1062. this.VerifyIsNotInstance(A_ThisFunc, A_LineFile, A_LineNumber, A_ThisFunc)
  1063. return MfMemoryString._FromAnyStatic(x, encoding)
  1064. }
  1065. ; End:FromAny ;}
  1066. ;{ FromBase64
  1067. /*
  1068. Method: FromBase64()
  1069.  
  1070. FromBase64()
  1071. Encodes Obj to base64 instance of MfMemoryString
  1072. Parameters:
  1073. obj
  1074. The value that represents base64
  1075. Can be instance of MfMemoryString or MfMemStrView or any object derived from MfObject
  1076. Returns:
  1077. Returns instance of MfMemoryString with decoded base64 value
  1078. Throws:
  1079. Throws MfInvalidOperationException if not called as a static method
  1080. Throws MfArgumentNullException if obj is null
  1081. Throws MfFormatException if obj does not contain valid base64
  1082. Remarks:
  1083. Static Method
  1084. */
  1085. FromBase64(obj) {
  1086. this.VerifyIsNotInstance(A_ThisFunc, A_LineFile, A_LineNumber, A_ThisFunc)
  1087. if (MfNull.IsNull(obj))
  1088. {
  1089. ex := new MfArgumentNullException("obj")
  1090. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  1091. throw ex
  1092. }
  1093. mStr := MfMemoryString._FromAnyStatic(obj, "UTF-8") ; base64 string, Use UTF-8
  1094. if (!(mStr.m_Encoding = "UTF-8"))
  1095. {
  1096. ; if MfMemoryString instance was passed in not encoded as UTF-8 then
  1097. ; call method again to convert to UTF-8
  1098. mStr := MfMemoryString._FromAnyStatic(mStr.ToString(), "UTF-8")
  1099. }
  1100. mv := MfMemStrView.FromBase64(mStr.m_MemView,0, mStr.m_CharCount)
  1101.  
  1102. objMemRW := new MfMemoryString(mv.m_BytesPerChar, mv.m_FillBytes, mv.m_Encoding)
  1103. objMemRW.m_MemView := ""
  1104. objMemRW.m_MemView := mv
  1105. objMemRW.m_CharCount := mv.GetCharCount()
  1106. return objMemRW
  1107. }
  1108. ; End:FromBase64 ;}
  1109. ;{ FromByteList
  1110. /*
  1111. Method: FromByteList()
  1112.  
  1113. FromByteList()
  1114. Converts MfByteList into MfMemoryString instance
  1115. Parameters:
  1116. bytes
  1117. instance of MfByteList containing byte values to convert
  1118. encoding
  1119. The encoding type of the bytes such as UTF-16 or UTF-8
  1120. Default value is UTF-16 which means each char is expected to be two bytes
  1121. startIndex
  1122. The starting index in the MfByteList to start the conversion
  1123. Default value is 0
  1124. length
  1125. the length in bytes to convert.
  1126. Default value is -1
  1127. When length is less then 0 then all bytes past startIndex are included
  1128. littleEndian
  1129. Default value is true.
  1130. If true then byte order is considered to be reversed and the bytes are written into
  1131. memory from last byte to first after considering startIndex and length; Oterwise bytes
  1132. are written from start to end.
  1133. Returns:
  1134. Returns instance of MfMemoryString
  1135. Throws:
  1136. Throws MfArgumentException, MfArgumentOutOfRangeException
  1137. Remarks:
  1138. Both startIndex and length operate the same no mater the state of littleEndian.
  1139. Static Method
  1140. */
  1141. FromByteList(bytes, encoding="UTF-16", startIndex=0, length=-1, littleEndian=true) {
  1142. this.VerifyIsNotInstance(A_ThisFunc, A_LineFile, A_LineNumber, A_ThisFunc)
  1143. startIndex := MfInteger.GetValue(startIndex, 0)
  1144. length := MfInteger.GetValue(length, -1)
  1145. littleEndian := MfBool.GetValue(littleEndian, true)
  1146.  
  1147. mv := MfMemStrView.FromByteList(bytes, encoding, startIndex, length, littleEndian)
  1148.  
  1149. objMemRW := new MfMemoryString(0, mv.m_FillBytes, mv.m_Encoding)
  1150. objMemRW.m_MemView := ""
  1151. objMemRW.m_MemView := mv
  1152. objMemRW.m_CharCount := mv.GetCharCount()
  1153. return objMemRW
  1154. }
  1155. ; End:FromByteList ;}
  1156. ;{ GetStringIgnoreNull
  1157. /*
  1158. Method: GetStringIgnoreNull()
  1159.  
  1160. GetStringIgnoreNull()
  1161. Gets an instance of MfMemoryString from current instance that has excluded all null values
  1162. Returns:
  1163. Returns MfMemoryString instance without any nulls
  1164. */
  1165. GetStringIgnoreNull() {
  1166. this.VerifyIsInstance(this, A_LineFile, A_LineNumber, A_ThisFunc)
  1167. mv := this.m_MemView.GetStringIgnoreNull()
  1168.  
  1169. objMemRW := new MfMemoryString(0, mv.m_FillBytes, mv.m_Encoding)
  1170. objMemRW.m_MemView := ""
  1171. objMemRW.m_MemView := mv
  1172. objMemRW.m_CharCount := mv.GetCharCount()
  1173. return objMemRW
  1174. }
  1175. ; End:GetStringIgnoreNull ;}
  1176. ;{ IndexOf
  1177. /*
  1178. Method: IndexOf()
  1179.  
  1180. IndexOf()
  1181. Gets the zero based position of obj within the currrent instance from start
  1182. Parameters:
  1183. obj
  1184. The value to search for
  1185. Can be instance of MfMemoryString or MfMemStrView or any object derived from MfObject
  1186. Offset
  1187. The offset in char count to start looking for obj
  1188. Default value is 0
  1189. Count
  1190. The Number of Chacters to examine.
  1191. Default is -1
  1192. If Count less then 0 then character within startIndex range are examined
  1193. IgnoreCase
  1194. If true then case is ignored: Otherwise case is considered
  1195. Returns:
  1196. Returns the zero base index of obj within current instance if found; Otherwise -1
  1197. Throws:
  1198. Throws MfArgumentException
  1199. Remarks:
  1200. Case sensitive method
  1201. */
  1202. IndexOf(obj, startIndex=0, Count=-1, IgnoreCase=true) {
  1203. if (MfNull.IsNull(obj))
  1204. {
  1205. return -1
  1206. }
  1207. startIndex := MfInteger.GetValue(startIndex, 0)
  1208. IgnoreCase := MfBool.GetValue(IgnoreCase, true)
  1209. Count := MfInteger.GetValue(Count, -1)
  1210. If (Count = 0)
  1211. {
  1212. return -1
  1213. }
  1214. if (startIndex < 0 || startIndex >= this.m_CharCount)
  1215. {
  1216. return -1
  1217. }
  1218.  
  1219. mStr := this._FromAny(obj)
  1220. if (IgnoreCase && Count < 0)
  1221. {
  1222. return this.m_MemView.InBuffer(mStr.m_MemView, startIndex)
  1223. }
  1224. return this.m_MemView.IndexOf(mStr.m_MemView, startIndex, Count, IgnoreCase)
  1225. }
  1226. ; End:IndexOf ;}
  1227. ;{ Insert
  1228. /*
  1229. Method: Insert()
  1230.  
  1231. Insert()
  1232. Inserts obj into current instance
  1233. Parameters:
  1234. index
  1235. The zero base index to insert obj into current instance
  1236. obj
  1237. The value to insert into current instance
  1238. Can be instance of MfMemoryString or MfMemStrView or any object derived from MfObject
  1239. Returns:
  1240. Returns
  1241. Throws:
  1242. Throws MfArgumentNullException, MfArgumentException, MfIndexOutOfRangeException
  1243. Remarks:
  1244. If index greater then or equal to current character count then obj is appended to end of this instance
  1245. */
  1246. Insert(index, obj) {
  1247. if (MfNull.IsNull(obj))
  1248. {
  1249. ex := new MfArgumentNullException("obj")
  1250. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  1251. throw ex
  1252. }
  1253. index := MfInteger.GetValue(index)
  1254. if ((index < 0) || (index > this.m_CharCount))
  1255. {
  1256. ex := new MfIndexOutOfRangeException(MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_IndexLength"))
  1257. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  1258. throw ex
  1259. }
  1260. if (index = this.m_CharCount)
  1261. {
  1262. return this.Append(obj)
  1263. }
  1264. mStr := this._FromAny(obj)
  1265. iFree := this.FreeCharCapacity
  1266. if (mStr.m_CharCount > iFree)
  1267. {
  1268. ex := new MfArgumentOutOfRangeException("obj.Length", MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_IndexCount"))
  1269. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  1270. throw ex
  1271. }
  1272. try
  1273. {
  1274. index := index * this.m_BytesPerChar
  1275. cc := this.m_MemView.Insert(index, mStr.m_MemView)
  1276. }
  1277. catch e
  1278. {
  1279. e.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  1280. throw e
  1281. }
  1282.  
  1283. this.m_CharCount := cc
  1284. return this
  1285. }
  1286. ; End:Insert ;}
  1287. ;{ LastIndexOf
  1288. /*
  1289. Method: LastIndexOf()
  1290.  
  1291. LastIndexOf()
  1292. Gets the zero based position of obj within the currrent instance from end
  1293. Parameters:
  1294. obj
  1295. The value to search for
  1296. Can be instance of MfMemoryString or MfMemStrView or any object derived from MfObject
  1297. startIndex
  1298. The offset in char count to start looking for obj
  1299. Default value is 0
  1300. Proceeds from the startIndex to the beginning of the string
  1301. Count
  1302. The Number of Chacters to examine.
  1303. Default is -1
  1304. If Count less then 0 then character within startIndex range are examined
  1305. IgnoreCase
  1306. If true then case is ignored: Otherwise case is considered
  1307. Returns:
  1308. Returns the zero base index of obj within current instance if found; Otherwise -1
  1309. Throws:
  1310. Throws MfArgumentException
  1311. Remarks:
  1312. Case sensitive method
  1313. */
  1314. LastIndexOf(obj, startIndex=-1, Count=-1, IgnoreCase=true) {
  1315. if (MfNull.IsNull(obj))
  1316. {
  1317. return -1
  1318. }
  1319. startIndex := MfInteger.GetValue(startIndex, -1)
  1320. Count := MfInteger.GetValue(Count, -1)
  1321. If (Count = 0)
  1322. {
  1323. return -1
  1324. }
  1325. if (startIndex >= this.m_CharCount)
  1326. {
  1327. return -1
  1328. }
  1329. mStr := this._FromAny(obj)
  1330. if (IgnoreCase && Count <= -1)
  1331. {
  1332. if (startIndex >= 0)
  1333. {
  1334. startIndex++
  1335. }
  1336. ; InbufferRev is faster then LastIndexOf so use it where we can
  1337. return this.m_MemView.InBufferRev(mStr.m_MemView, startIndex)
  1338.  
  1339. }
  1340. return this.m_MemView.LastIndexOf(mStr.m_MemView, startIndex, Count, IgnoreCase)
  1341. }
  1342. ; End:LastIndexOf ;}
  1343. ;{ MoveCharsLeft
  1344. /*
  1345. Method: MoveCharsLeft()
  1346.  
  1347. MoveCharsLeft()
  1348. Move the characters in memory to the left overwriting any characters in position before move
  1349. Parameters:
  1350. StartIndex
  1351. The zero based char index to start overwriting
  1352. ShiftAmt
  1353. The number of characters from StartIndex to start the shift
  1354. The First character at ShiftAmt will be written into the Position
  1355. of StartIndex, the second character from shiftAmount will be written
  1356. into the second position from StartIndex and so on.
  1357. Length
  1358. Length Limits how many character are shifted left from ShiftAmout
  1359. Default Value of Length is -1.
  1360. When omitted or less then 0 then all characters right of ShiftAmt are shift left.
  1361. If Length is greater then the last Character Position then all characters right of shiftamt
  1362. will still be moved left
  1363. ZeroFillSpace
  1364. Optional Boolean value
  1365. Defautl Vaue is false
  1366. If True then the Space created when the bytes are moved are overwritten with 0
  1367. Returns:
  1368. Returns current instance
  1369. Throws:
  1370. Throws MfArgumentOutOfRangeException, MfException
  1371. Remarks:
  1372. The Pos will be adjusted to reflect then new location
  1373. If Length is included and is less then the number of characters past ShiftAmt to Pos
  1374. then all characters from Length to Previous Pos are erased
  1375. */
  1376. MoveCharsLeft(StartIndex, ShiftAmt, Length=-1, ZeroFillSpace=false) {
  1377. try
  1378. {
  1379. BytesPerChar := this.m_BytesPerChar
  1380. StartIndex := MfInteger.GetValue(StartIndex) * BytesPerChar
  1381. Length := MfInteger.GetValue(Length, -1)
  1382. ShiftAmt := MfInteger.GetValue(ShiftAmt) * BytesPerChar
  1383. ZeroFillSpace := MfBool.GetValue(ZeroFillSpace, false)
  1384. if (Length = 0 || ShiftAmt = 0)
  1385. {
  1386. return this
  1387. }
  1388. if (Length > 0)
  1389. {
  1390. Length := Length * BytesPerChar
  1391. }
  1392.  
  1393. this.m_MemView.MoveBytesLeft(StartIndex, ShiftAmt, Length, ZeroFillSpace)
  1394. this.m_CharCount := this.m_MemView.GetCharCount()
  1395. return this
  1396. }
  1397. catch e
  1398. {
  1399. if (MfObject.IsObjInstance(e, MfArgumentOutOfRangeException))
  1400. {
  1401. e.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  1402. throw e
  1403. }
  1404. ex := new MfException(MfEnvironment.Instance.GetResourceString("Exception_Error", A_ThisFunc), e)
  1405. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  1406. throw ex
  1407. }
  1408. }
  1409. ; End:MoveCharsLeft ;}
  1410. ;{ MoveCharsRight
  1411. /*
  1412. Method: MoveCharsRight()
  1413.  
  1414. MoveCharsRight()
  1415. Move the characters in memory to the Right inserting null (unicode 0) from StartIndex to ShiftAmt
  1416. Parameters:
  1417. StartIndex
  1418. The zero based Starting index in chars to inserting null char
  1419. ShiftAmt
  1420. The Number of null chars to insert at the StartIndex
  1421. Length
  1422. Length Limits how many Char are moved to the end.
  1423. Default Value is -1.
  1424. If Omitted or less then zero then all chars from the StartIndex are moved to the right
  1425. Throws:
  1426. Throws MfArgumentOutOfRangeException If StartIndex, Length or ShiftAmout are out of range
  1427. Throws MfArgumentOutOfRangeException if Shifting to right will exceed current Size
  1428. Throw MfException for all other errors
  1429. Remarks:
  1430. Pos is set to the new location after the chars have been moved.
  1431. This method does not increase the size of the current instance and there must be
  1432. room in the buffer to ensure the move is successfull. An error will be throw if there is not
  1433. enough room in the buffer.
  1434. When Chars are moved to the right the ToString() method will stop at the first null char found.
  1435. Use GetStringIgnoreNull().ToString() if current string value is needed.
  1436. The Primary usage for this method is to move characters to the right so new characters can be inserted.
  1437. See the OverWrite method as well.
  1438. */
  1439. MoveCharsRight(StartIndex, ShiftAmt, Length=-1) {
  1440.  
  1441. try
  1442. {
  1443. BytesPerChar := this.m_BytesPerChar
  1444. StartIndex := MfInteger.GetValue(StartIndex) * BytesPerChar
  1445. Length := MfInteger.GetValue(Length, -1)
  1446. if (Length = 0 || ShiftAmt = 0)
  1447. {
  1448. return this
  1449. }
  1450. if (Length > 0)
  1451. {
  1452. Length := Length * BytesPerChar
  1453. }
  1454. ShiftAmt := MfInteger.GetValue(ShiftAmt) * BytesPerChar
  1455. if (Length = 0 || ShiftAmt = 0)
  1456. {
  1457. ; cannot move left already at the start or no shift amount to move
  1458. return this
  1459. }
  1460. this.m_MemView.MoveBytesRight(StartIndex, ShiftAmt, Length)
  1461. this.m_CharCount := this.m_MemView.GetCharCount()
  1462. return this
  1463. }
  1464. catch e
  1465. {
  1466. if (MfObject.IsObjInstance(e, MfArgumentOutOfRangeException))
  1467. {
  1468. e.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  1469. throw e
  1470. }
  1471. ex := new MfException(MfEnvironment.Instance.GetResourceString("Exception_Error", A_ThisFunc), e)
  1472. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  1473. throw ex
  1474. }
  1475.  
  1476. }
  1477. ; End:MoveCharsRight ;}
  1478. ;{ OverWrite
  1479. /*
  1480. Method: OverWrite()
  1481.  
  1482. OverWrite()
  1483. Overwrites the chars in this instance with the chars in obj instance
  1484. Parameters:
  1485. obj
  1486. The value to overwrite in the curren instance
  1487. Can be instance of MfMemoryString or MfMemStrView or any object derived from MfObject
  1488. StartIndex
  1489. The zero based index to start overwriting bytes in this instance
  1490. Default value is 0
  1491. Length
  1492. The number of chars to read from obj and to ovrwrite in this instance
  1493. Default value is -1.
  1494. When Length is -1 the entire chars of obj will be read and overwritten in this instance.
  1495. Returns:
  1496. Returns the current char count.
  1497. Throws:
  1498. Throws MfArgumentException, MfArgumentOutOfRangeException, MfException
  1499. Remarks:
  1500. The Current char count should remain the same as this method overwrites chars and does not add or remove chars
  1501. */
  1502. OverWrite(obj, StartIndex=0, Length=-1) {
  1503. if (MfNull.IsNull(obj))
  1504. {
  1505. ex := new MfArgumentNullException("obj")
  1506. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  1507. throw ex
  1508. }
  1509. startIndex := MfInteger.GetValue(startIndex, 0)
  1510. Length := MfInteger.GetValue(Length, -1)
  1511. if ((StartIndex < 0) || ((StartIndex + 1) * this.m_BytesPerChar >= this.m_MemView.Size))
  1512. {
  1513. ex := new MfArgumentOutOfRangeException("StartIndex", MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_IndexString"))
  1514. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  1515. throw ex
  1516. }
  1517. mStr := this._FromAny(obj)
  1518. this.m_CharCount := this.m_MemView.OverWrite(mStr.m_MemView, StartIndex, Length)
  1519. return this
  1520. }
  1521. ; End:OverWrite ;}
  1522. ;{ Replace
  1523. /*
  1524. Method: Replace()
  1525.  
  1526. Replace()
  1527. Replaces instances of oldValue with Instances of newValue
  1528. Parameters:
  1529. oldValue
  1530. The Value to find and replace
  1531. newValue
  1532. The replacemet value
  1533. startIndex
  1534. the zero based index with this string to start looking for oldValue
  1535. count
  1536. The number of characters to limit the replacemt;
  1537. Or -1 to replace all occurences in the string;
  1538. Or -2 to replace only the first occurence in a string
  1539. Returns:
  1540. Returns the number of replacements made
  1541. Throws:
  1542. Throws MfArgumentNullException
  1543. Throws MfIndexOutOfRangeException
  1544. Throws MfArgumentException
  1545. Remarks:
  1546. If count is -1 then all instances of oldValue are replaced
  1547. If count is -2 only the first instance of oldValue is replaced
  1548. If newValue is empty the oldValue instances will be removed
  1549. */
  1550. Replace(oldValue, newValue, ByRef startIndex=0, count=-1) {
  1551.  
  1552. if (this.m_CharCount = 0)
  1553. {
  1554. return 0
  1555. }
  1556. if (MfNull.IsNull(oldValue))
  1557. {
  1558. ex := new MfArgumentNullException("oldValue")
  1559. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  1560. throw ex
  1561. }
  1562. startIndex := MfInteger.GetValue(startIndex)
  1563. if ((startIndex < 0) || (startIndex >= this.m_CharCount))
  1564. {
  1565. ex := new MfIndexOutOfRangeException(MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_IndexLength"))
  1566. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  1567. throw ex
  1568. }
  1569.  
  1570. count := MfInteger.GetValue(count)
  1571.  
  1572. mStrNew := this._FromAny(newValue)
  1573. mStrOld := this._FromAny(oldValue)
  1574.  
  1575. ; -2 represents replacing a single occurence
  1576. if (Count = -2)
  1577. {
  1578. result := this._Replace(mStrOld, mStrNew, startIndex)
  1579. if (result)
  1580. {
  1581. return 1
  1582. }
  1583. return 0
  1584. }
  1585. length := this.m_CharCount
  1586. ; -1 represents replacing all counts in the entire string
  1587. if (count = -1)
  1588. {
  1589. count := length
  1590. }
  1591.  
  1592. if (count < 0 || startIndex > length - count)
  1593. {
  1594. return 0
  1595. }
  1596. if (count <= 0)
  1597. {
  1598. return 0
  1599. }
  1600. if (Count < length && startIndex > length - count)
  1601. {
  1602. return 0
  1603. }
  1604.  
  1605. NewLen := mStrNew.m_CharCount
  1606. OldLen := mStrOld.m_CharCount
  1607. fIndex := startIndex
  1608. icount := 0
  1609. loop
  1610. {
  1611. result := this._Replace(mStrOld, mStrNew, fIndex)
  1612. if (result = false || fIndex >= count)
  1613. {
  1614. break
  1615. }
  1616. count -= OldLen
  1617. iCount++
  1618. }
  1619. return iCount
  1620. }
  1621. ; End:Replace ;}
  1622. ;{ _Replace
  1623. ; replace a single item
  1624. ; returns false if no replacement; Otherwise true
  1625. _Replace(byRef mStrOld, ByRef mStrNew, ByRef startIndex) {
  1626. startIndex := this.IndexOf(mStrOld, startIndex)
  1627. if (startIndex = -1)
  1628. {
  1629. return false
  1630. }
  1631. delta := mStrOld.m_CharCount - mStrNew.m_CharCount
  1632. if (delta = 0)
  1633. {
  1634. ; when both old and new value are the same length just overwrite the bytes
  1635. this.m_MemView.OverWrite(mStrNew.m_MemView, startIndex, mStrNew.m_CharCount)
  1636. return true
  1637. }
  1638. this.Remove(startIndex, mStrOld.m_CharCount)
  1639. If (mStrNew.m_CharCount > 0)
  1640. {
  1641. this.Insert(startIndex, mStrNew)
  1642. }
  1643. return true
  1644. }
  1645. ; End:_Replace ;}
  1646. ;{ ReplaceAtIndex
  1647. /*
  1648. Method: ReplaceAtIndex()
  1649.  
  1650. ReplaceAtIndex()
  1651. Replaces as section of the string with newValue
  1652. Parameters:
  1653. Index
  1654. The index to Start The insert of newValue
  1655. Length
  1656. The number of chars to remove before insert newValue
  1657. newValue
  1658. The New Value to insert into this instance at the index location
  1659. Can be instance of MfMemoryString or MfMemStrView or any object derived from MfObject
  1660. Returns:
  1661. Returns
  1662. Throws:
  1663. Throws MfException if
  1664. Remarks:
  1665. If ReplaceAtIndex
  1666. */
  1667. ReplaceAtIndex(Index, Length, newValue) {
  1668. index := MfInteger.GetValue(index)
  1669. length := MfInteger.GetValue(length)
  1670. if (this.m_CharCount = 0)
  1671. {
  1672. return this
  1673. }
  1674. if ((index < 0) || (index >= this.m_CharCount))
  1675. {
  1676. ex := new MfArgumentOutOfRangeException("index", MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_IndexLength"))
  1677. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  1678. throw ex
  1679. }
  1680. mStr := this._FromAny(newValue)
  1681. if (mStr.m_CharCount = 0)
  1682. {
  1683. return this
  1684. }
  1685. delta := mStr.m_CharCount - Length
  1686. if (delta = 0)
  1687. {
  1688. BytesPerChar := this.m_BytesPerChar
  1689. ; when both old and new value are the same length just overwrite the bytes
  1690. ptr := this.m_MemView[] + (Index * BytesPerChar)
  1691. sourcePtr := mStr.m_MemView[]
  1692. Length := (Length * BytesPerChar)
  1693. DllCall("RtlMoveMemory", "PTR", ptr + 0, "PTR", sourcePtr + 0, "UCHAR", Length)
  1694. ;DllCall("RtlMoveMemory", "Ptr", sourcePtr + 0, "Ptr", ptr + 0, "UChar", Length)
  1695. ;str := StrGet(ptr,Length, this.m_Encoding)
  1696. return this
  1697. }
  1698. if (delta > this.FreeCharCapacity)
  1699. {
  1700. ex := new MfArgumentOutOfRangeException("newValue.Length", MfEnvironment.Instance.GetResourceString("Arg_ArrayTooSmall"))
  1701. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  1702. throw ex
  1703. }
  1704.  
  1705. this.Remove(Index, Length)
  1706. If (newValue.m_CharCount > 0)
  1707. {
  1708. this.Insert(Index, newValue)
  1709. }
  1710. return this
  1711. }
  1712. ; End:ReplaceAtIndex ;}
  1713. ;{ Remove
  1714. /*
  1715. Method: Remove()
  1716.  
  1717. Remove()
  1718. Removes a number of chars from currrent instance
  1719. Parameters:
  1720. index
  1721. The zero base index to insert obj into current instance
  1722. count
  1723. The number of chars to remove from the current instance.
  1724. Default value is -1
  1725. If Ommited or value is less then 0 then all chars past index are deleted
  1726. Returns:
  1727. Returns current instance
  1728. Throws:
  1729. Throws MfIndexOutOfRangeException,MfArgumentOutOfRangeException, MfArgumentException
  1730. */
  1731. Remove(index, count=-1) {
  1732. index := MfInteger.GetValue(index)
  1733. count := MfInteger.GetValue(count, -1)
  1734. if ((index < 0) || (index >= this.m_CharCount))
  1735. {
  1736. ex := new MfArgumentOutOfRangeException("index", MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_Index"))
  1737. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  1738. throw ex
  1739. }
  1740.  
  1741. If (count = 0)
  1742. {
  1743. return this
  1744. }
  1745.  
  1746. BytesPerChar := this.m_BytesPerChar
  1747.  
  1748. PI := this.m_MemView.Pos
  1749. StartIndex := index * BytesPerChar
  1750. if (count < 0)
  1751. {
  1752. ; No count so just move the pos to reflect index
  1753. ; index 0 is char 1
  1754. this.m_MemView.Pos := StartIndex + (BytesPerChar * 2)
  1755. this.m_CharCount := this.m_MemView.GetCharCount()
  1756. return this
  1757. }
  1758. Else
  1759. {
  1760. count := count * BytesPerChar
  1761. }
  1762.  
  1763. if ((count + index) >= PI)
  1764. {
  1765. ex := new MfArgumentOutOfRangeException("Count", MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_IndexCount"))
  1766. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  1767. throw ex
  1768. }
  1769.  
  1770. ShiftAmout := (PI - StartIndex) ;+ 2 ; - BytesPerChar
  1771. ptr := this.m_MemView[]
  1772. startPtr := ptr + StartIndex
  1773. iCount := (PI - BytesPerChar) - (count + StartIndex)
  1774. MfMemStrView.CopyFromAddress(ptr + count + StartIndex, this.m_MemView, StartIndex, iCount)
  1775.  
  1776. this.m_MemView.Pos -= count
  1777. this.m_CharCount := this.m_MemView.GetCharCount()
  1778. return this
  1779. }
  1780. ; End:Remove ;}
  1781. ;{ Reverse
  1782. /*
  1783. Method: Reverse()
  1784.  
  1785. Reverse()
  1786. Reverses the contentes of the currrent instance and returne it as a new instance
  1787. Parameters:
  1788. LimitBytes
  1789. If True then the return instance will have its size limited to the number of chars in the current instaned;
  1790. Otherwise the size will be the same size as the current instance
  1791. Returns:
  1792. Returns a new instance of MfMemoryString with the chars reversed
  1793. Remarks:
  1794. New line char sequences set in the framework will not be reversed in the return output.
  1795. the default new line chars are 13, 10 when the string is reversed the order will still be 13, 10
  1796. the order and char for new line are read from MfEnviroment.Instance.NewLine
  1797. */
  1798. Reverse(LimitBytes=false) {
  1799. LimitBytes := MfBool.GetValue(LimitBytes, false)
  1800. objRev := new MfMemoryString(0, this.m_FillBytes, this.m_Encoding)
  1801. objRev.m_MemView := ""
  1802. objRev.m_MemView := this.m_MemView.Reverse(LimitBytes)
  1803. objRev.m_CharCount := this.m_CharCount
  1804. return objRev
  1805. }
  1806. ; End:Reverse ;}
  1807. ;{ SetPosFromCharIndex
  1808. /*
  1809. Method: SetPosFromCharIndex()
  1810.  
  1811. SetPosFromCharIndex()
  1812. Moves the Location of Pos from index based upon char index
  1813. Parameters:
  1814. index
  1815. The new Char index to set the pos to
  1816. AdvanceByOne
  1817. Default value is true
  1818. If True then Pos in moved forward by the value of BytePerChar; Otherwise
  1819. the pos is set at the exact location of the of the char index ( considering encoding and BytesPerChar)
  1820. Returns:
  1821. Returns this instance
  1822. Throws:
  1823. Throws MfArgumentException, MfArgumentOutOfRangeException
  1824. Remarks:
  1825. Changing the position of Pos can affect the ToString() method
  1826. */
  1827. SetPosFromCharIndex(index, AdvanceByOne=true) {
  1828. index := MfInteger.GetValue(index)
  1829. AdvanceByOne := MfBool.GetValue(AdvanceByOne, true)
  1830. BytesPerChar := this.m_BytesPerChar
  1831. bIndex := index * BytesPerChar
  1832. if (index < 0 || bIndex > this.m_MemView.Size)
  1833. {
  1834. ex := new MfArgumentOutOfRangeException(MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_Index"))
  1835. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  1836. throw ex
  1837. }
  1838. this.Pos := bIndex
  1839. If (AdvanceByOne && this.Pos < this.m_MemView.Size)
  1840. {
  1841. this.Pos += BytesPerChar
  1842. }
  1843. this.m_CharCount := this.m_MemView.GetCharCount()
  1844.  
  1845. return this
  1846. }
  1847. ; End:SetPosFromCharIndex ;}
  1848. _ResetPos() {
  1849. ; add one for line end
  1850. i := (this.m_CharCount + 1) * this.m_BytesPerChar
  1851. this.m_MemView.Pos := i
  1852. }
  1853. ;{ StartsWith
  1854. /*
  1855. Method: StartsWith()
  1856.  
  1857. StartsWith()
  1858. Gets if current instance starts with obj
  1859. Parameters:
  1860. obj
  1861. The value to see if current instance starts with
  1862. Can be instance of MfMemoryString or MfMemStrView or any object derived from MfObject
  1863. IgnoreCase
  1864. Boolean value, Default is true. If True Case will be ignored; Otherwise case will be considered
  1865. Default value is true
  1866. Returns:
  1867. Returns True if current instane starts with obj; Otherwise false
  1868. Throws:
  1869. Throws MfArgumentNullException if obj is null
  1870. */
  1871. StartsWith(obj, IgnoreCase=true) {
  1872. if (MfNull.IsNull(obj))
  1873. {
  1874. ex := new MfArgumentNullException("obj")
  1875. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  1876. throw ex
  1877. }
  1878. IgnoreCase := MfBool.GetValue(IgnoreCase, true)
  1879.  
  1880. mStr := this._FromAny(obj)
  1881. len := mStr.m_CharCount
  1882. if (len = 0)
  1883. {
  1884. return false
  1885. }
  1886. if (len > this.m_CharCount)
  1887. {
  1888. return false
  1889. }
  1890. ; by searching for last index of we can limit the number of chars searched
  1891. ; using LasdIndexOf method first is likely the faster method
  1892. ; LasdIndexOf search method is extreamly fast as it runs machine code
  1893. result := this.LastIndexOf(mStr, this.m_CharCount - len) = 0
  1894. ;result := this.IndexOf(str) = 0
  1895. if (result = false && IgnoreCase = false)
  1896. {
  1897. len := mStr.m_CharCount
  1898. result := MfMemStrView.EqualsSubString(this.m_MemView, 0, mStr.m_MemView, 0, len, IgnoreCase)
  1899. ; startStr := this.Substring(0, len)
  1900. ; result := startStr = str
  1901. }
  1902. return result
  1903. }
  1904. ; End:StartsWith ;}
  1905. ;{ SubString
  1906. /*
  1907. Method: SubString()
  1908.  
  1909. SubString()
  1910. Gets a new instance of MfMemoryString that represents a subset of the current instance chars
  1911. Parameters:
  1912. StartIndex
  1913. The zero based index to start the subset from.
  1914. Length
  1915. The length of the subset in Chars.
  1916. Default value is -1.
  1917. If value is -1 then all chars from startindex will be included
  1918. Returns:
  1919. Returns new instance of MfMemoryString
  1920. Throws:
  1921. Throws MfArgumentException
  1922. */
  1923. SubString(StartIndex, Length=-1) {
  1924. BytesPerChar := this.m_BytesPerChar
  1925. Try
  1926. {
  1927. StartIndex := MfInteger.GetValue(StartIndex) * BytesPerChar
  1928. }
  1929. Catch e
  1930. {
  1931. ex := new MfArgumentException(MfEnvironment.Instance.GetResourceString("Argument_Value_Error", "StartIndex"), e)
  1932. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  1933. throw ex
  1934. }
  1935.  
  1936. Length := MfInteger.GetValue(Length, -1)
  1937. if (Length > 0)
  1938. {
  1939. Length := Length * BytesPerChar
  1940. }
  1941. mv := this.m_MemView.SubSet(StartIndex, Length)
  1942. objMemRW := new MfMemoryString(0, mv.m_FillBytes, mv.m_Encoding)
  1943. objMemRW.m_MemView := ""
  1944. objMemRW.m_MemView := mv
  1945. objMemRW.m_CharCount := mv.GetCharCount()
  1946. return objMemRW
  1947. }
  1948. ; End:SubString ;}
  1949. ;{ ToArray
  1950. /*
  1951. Method: ToArray()
  1952.  
  1953. ToArray()
  1954. Gets Byte array of current chars
  1955. Parameters:
  1956. startIndex
  1957. Optional. The zero based start array to get the bytes for.
  1958. Default is 0
  1959. length
  1960. Optional. the total number of bytes to get.
  1961. Default -1
  1962. Any value less then 0 will result in all char bytes from startIndex to char count
  1963. Returns:
  1964. Returns AutoHotkey one based array of bytes (values from 0 to 255) in Big Endian order
  1965. Throws:
  1966. Throws MfArgumentOutOfRangeException startIndex or length is out of range
  1967. */
  1968. ToArray(startIndex=0, length=-1) {
  1969. startIndex := MfInteger.GetValue(startIndex, 0)
  1970. length := MfInteger.GetValue(length, 0)
  1971. if ((StartIndex < 0) || (StartIndex >= this.m_CharCount))
  1972. {
  1973. ex := new MfArgumentOutOfRangeException("StartIndex", MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_IndexString"))
  1974. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  1975. throw ex
  1976. }
  1977. if (Length < 0)
  1978. {
  1979. Length := (this.m_CharCount - StartIndex)
  1980. }
  1981. if ((Length + StartIndex) > this.m_CharCount)
  1982. {
  1983. ex := new MfArgumentOutOfRangeException("Length", MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_IndexString"))
  1984. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  1985. throw ex
  1986. }
  1987. StartIndex := StartIndex * this.m_BytesPerChar
  1988. length := length * this.m_BytesPerChar
  1989. return this.m_MemView.ToArray(startIndex, length, "UChar")
  1990. }
  1991. ; End:ToArray ;}
  1992. ;{ ToBase64
  1993. /*
  1994. Method: ToBase64()
  1995.  
  1996. ToBase64()
  1997. Reads current instance and returns a new MfMemoryString instance endoced as UTF-8 base64
  1998. Parameters:
  1999. addLineBreaks
  2000. Boolean Value, If True a line break will be added to the output every 76 chars;
  2001. Otherwise no line breaks will be added.
  2002. Returns:
  2003. Returns instance of MfMemoryString
  2004. Throws:
  2005. Throws MfException if
  2006. Remarks:
  2007. Return MfMemoryString instance is always encoded as UTF-8
  2008. */
  2009. ToBase64(addLineBreaks=false) {
  2010. this.VerifyIsInstance(this, A_LineFile, A_LineNumber, A_ThisFunc)
  2011. addLineBreaks := MfBool.GetValue(addLineBreaks, false)
  2012. result := ""
  2013. mv := MfMemStrView.ToBase64(this.m_MemView, 0, this.m_CharCount, addLineBreaks)
  2014.  
  2015. objMemRW := new MfMemoryString(0, mv.m_FillBytes, mv.m_Encoding)
  2016. objMemRW.m_MemView := ""
  2017. objMemRW.m_MemView := mv
  2018. objMemRW.m_CharCount := mv.GetCharCount()
  2019. return objMemRW
  2020. }
  2021. ; End:ToBase64 ;}
  2022.  
  2023. ;{ ToByteList
  2024. /*
  2025. Method: ToByteList()
  2026.  
  2027. ToByteList()
  2028. Creates an MfByteList of bytes from current instance of MfMemoryString
  2029. Parameters:
  2030. startIndex
  2031. The zero based index to start reading current instance chars as bytes
  2032. length
  2033. The length in chars to read from current instance
  2034. Default value is -1
  2035. When value is -1 chars are read from startIndex to current char count
  2036. littleEndian
  2037. Default is true, If True byte order is in Little Endian;
  2038. Otherwise byte order is in Big Endian ( same as ToArray )
  2039. Returns:
  2040. Returns MfByteList
  2041. Throws:
  2042. Throws MfArgumentOutOfRangeException startIndex or length is out of range
  2043. */
  2044. ToByteList(startIndex=0, length=-1, littleEndian=true) {
  2045. startIndex := MfInteger.GetValue(startIndex, 0)
  2046. length := MfInteger.GetValue(length, 0)
  2047. if ((StartIndex < 0) || (StartIndex >= this.m_CharCount))
  2048. {
  2049. ex := new MfArgumentOutOfRangeException("StartIndex", MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_IndexString"))
  2050. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  2051. throw ex
  2052. }
  2053. if (Length < 0)
  2054. {
  2055. Length := (this.m_CharCount - StartIndex)
  2056. }
  2057. if ((Length + StartIndex) > this.m_CharCount)
  2058. {
  2059. ex := new MfArgumentOutOfRangeException("Length", MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_IndexString"))
  2060. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  2061. throw ex
  2062. }
  2063. littleEndian := MfBool.GetValue(littleEndian, true)
  2064. StartIndex := StartIndex * this.m_BytesPerChar
  2065. length := length * this.m_BytesPerChar
  2066. return this.m_MemView.ToByteList(startIndex, length, littleEndian)
  2067. }
  2068. ; End:ToByteList ;}
  2069. ;{ ToCharList
  2070. /*
  2071. Method: ToCharList()
  2072.  
  2073. ToCharList()
  2074. Gets a copy of the current instance as MfCharList
  2075. Parameters:
  2076. startIndex
  2077. Optional: The Char Index to start filling the return list with
  2078. length
  2079. Optional: The length of the retrun list
  2080. Returns:
  2081. Returns instance of MfCharList containing Numer Char valus
  2082. Throws:
  2083. Throws MfArgumentOutOfRangeException
  2084. */
  2085. ToCharList(startIndex=0, length=-1) {
  2086. startIndex := MfInteger.GetValue(startIndex, 0)
  2087. length := MfInteger.GetValue(length, -1)
  2088. if ((StartIndex < 0) || (StartIndex >= this.m_CharCount))
  2089. {
  2090. ex := new MfArgumentOutOfRangeException("StartIndex", MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_IndexString"))
  2091. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  2092. throw ex
  2093. }
  2094. If (length > 0)
  2095. {
  2096. If (length - startIndex > this.m_CharCount)
  2097. {
  2098. ex := new MfArgumentOutOfRangeException("Length", MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_IndexString"))
  2099. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  2100. throw ex
  2101. }
  2102. }
  2103. return this.m_MemView.ToCharList(startIndex, length)
  2104. }
  2105. ; End:ToCharList ;}
  2106. ;{ _SubString
  2107. ; gets substring as string var of current instance
  2108. ; see ToString()
  2109. _SubString(StartIndex, Length) {
  2110. if (Length = 0)
  2111. {
  2112. return ""
  2113. }
  2114. if ((StartIndex < 0) || (StartIndex >= this.m_CharCount))
  2115. {
  2116. ex := new MfArgumentOutOfRangeException("StartIndex", MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_IndexString"))
  2117. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  2118. throw ex
  2119. }
  2120. if ((Length < 0) || ((Length + StartIndex) > this.m_CharCount))
  2121. {
  2122. ex := new MfArgumentOutOfRangeException("Length", MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_IndexString"))
  2123. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  2124. throw ex
  2125. }
  2126.  
  2127. _StartIndex := StartIndex * this.m_BytesPerChar
  2128. PI := this.m_MemView.Pos
  2129. this.m_MemView.Seek(_StartIndex)
  2130. methodName := "Read" . this.m_EncodingName
  2131. ; Read method will read the proper length no matter the encoding
  2132. len := Length
  2133. retval := this.m_MemView.__Call(methodName, len)
  2134. this.m_MemView.Pos := PI
  2135. return retval
  2136. }
  2137. ; End:_SubString ;}
  2138.  
  2139. ;{ ToString
  2140. /*
  2141. Method: ToString()
  2142.  
  2143. ToString()
  2144. Retunrs the contents of the current instance as a string var
  2145. Parameters:
  2146. StartIndex
  2147. The zero based index to start the output string from.
  2148. Default value is 0
  2149. Length
  2150. The length of the output string in chars.
  2151. Default value is -1
  2152. If Length value is -1 this all characters from StartIndex are returned
  2153. Returns:
  2154. Returns String Var
  2155. Throws:
  2156. Throws MfArgumentOutOfRangeException
  2157. */
  2158. ToString(StartIndex=0, Length=-1) {
  2159. StartIndex := MfInteger.GetValue(StartIndex, 0)
  2160. Length := MfInteger.GetValue(Length, -1)
  2161. if (StartIndex != 0)
  2162. {
  2163. if (Length < 0)
  2164. {
  2165. Length := (this.m_CharCount - StartIndex)
  2166. }
  2167. return this._SubString(StartIndex,Length)
  2168. }
  2169. else if (Length < 0)
  2170. {
  2171. return this.m_MemView.ToString()
  2172. }
  2173. if (Length >= 0)
  2174. {
  2175. return this._SubString(StartIndex,Length)
  2176. }
  2177. return this.m_MemView.ToString()
  2178. }
  2179. ; End:ToString ;}
  2180. ;{ Trim
  2181. /*
  2182. Method: Trim()
  2183.  
  2184. Trim()
  2185. Trims TrimChars or whitespace from this instance start and end
  2186. Parameters:
  2187. trimChars
  2188. Optional string var. The char(s) to trim from this instance.
  2189. If omitted then all unicode whitespace chars are trimed
  2190. IgnoreCase
  2191. Boolean value. Default value is true, If True then case will be ignored; Otherwise
  2192. case will be considered.
  2193. Ignore Case only applies when trimChars has a value
  2194. Returns:
  2195. Returns this instance
  2196. */
  2197. Trim(trimChars="", IgnoreCase=true) {
  2198. If (this.m_CharCount = 0)
  2199. {
  2200. return this
  2201. }
  2202. this.TrimStart(trimChars, IgnoreCase)
  2203. return this.TrimEnd(trimChars, IgnoreCase)
  2204. }
  2205. ; End:Trim ;}
  2206. ;{ TrimBuffer
  2207. /*
  2208. Method: TrimBuffer()
  2209.  
  2210. TrimBuffer()
  2211. Trims the internal buffer to the size of the current chars
  2212. Returns:
  2213. Returns this instance
  2214. Remarks:
  2215. Trims the buffer down to the size of the current text
  2216. */
  2217. TrimBuffer() {
  2218. this.m_CharCount := this.m_MemView.TrimBufferToPos()
  2219. return this
  2220. }
  2221. ; End:TrimBuffer ;}
  2222. ;{ TrimStart
  2223. /*
  2224. Method: Trim()
  2225.  
  2226. TrimStart()
  2227. Trims TrimChars or whitespace from this instance start
  2228. Parameters:
  2229. trimChars
  2230. Optional string var. The char(s) to trim from this instance.
  2231. If omitted then all unicode whitespace chars are trimed
  2232. IgnoreCase
  2233. Boolean value. Default value is true, If True then case will be ignored; Otherwise
  2234. case will be considered.
  2235. Ignore Case only applies when trimChars has a value
  2236. Returns:
  2237. Returns this instance
  2238. */
  2239. TrimStart(trimChars="", IgnoreCase=true) {
  2240. If (this.m_CharCount = 0)
  2241. {
  2242. return this
  2243. }
  2244. trimChars := MfString.GetValue(trimChars)
  2245. IgnoreCase := MfBool.GetValue(IgnoreCase, true)
  2246. if (trimChars == "")
  2247. {
  2248. TrimCount := this.m_MemView.TrimStart()
  2249. this.m_CharCount -= TrimCount
  2250. return this
  2251. }
  2252. TrimCount := this.m_MemView.TrimStartChars(trimChars, IgnoreCase)
  2253. this.m_CharCount -= TrimCount
  2254. return this
  2255. }
  2256. ; End:TrimStart ;}
  2257. ;{ TrimEnd
  2258. /*
  2259. Method: Trim()
  2260.  
  2261. TrimStart()
  2262. Trims TrimChars or whitespace from this instance end
  2263. Parameters:
  2264. trimChars
  2265. Optional string var. The char(s) to trim from this instance.
  2266. If omitted then all unicode whitespace chars are trimed
  2267. IgnoreCase
  2268. Boolean value. Default value is true, If True then case will be ignored; Otherwise
  2269. case will be considered.
  2270. Ignore Case only applies when trimChars has a value
  2271. Returns:
  2272. Returns this instance
  2273. */
  2274. TrimEnd(trimChars="", IgnoreCase=true) {
  2275. If (this.m_CharCount = 0)
  2276. {
  2277. return this
  2278. }
  2279. trimChars := MfString.GetValue(trimChars)
  2280. IgnoreCase := MfBool.GetValue(IgnoreCase, true)
  2281. if (trimChars == "")
  2282. {
  2283. TrimCount := this.m_MemView.TrimEnd()
  2284. this.m_CharCount -= TrimCount
  2285. return this
  2286. }
  2287. TrimCount := this.m_MemView.TrimEndChars(trimChars, IgnoreCase)
  2288. this.m_CharCount -= TrimCount
  2289. return this
  2290. }
  2291. ; End:TrimEnd ;}
  2292. ;{ _FromAnyStatic
  2293. ; static method for converting var or obj into MfMemoryString
  2294. _FromAnyStatic(x, encoding) {
  2295.  
  2296. ;BytesPerChar := MfMemStrView.GetBytesPerChar(encoding)
  2297. if (IsObject(x))
  2298. {
  2299. if(MfObject.IsObjInstance(x, MfMemoryString))
  2300. {
  2301. if (!(x.m_Encoding = encoding))
  2302. {
  2303. return MfMemoryString._FromAnyStatic(x.ToString(), encoding)
  2304. }
  2305. return x
  2306. }
  2307.  
  2308. else if (MfObject.IsObjInstance(x, MfString))
  2309. {
  2310. retval := new MfMemoryString(x.Length, , encoding)
  2311. if (x.Length > 0)
  2312. {
  2313. retval.Append(x)
  2314. }
  2315. return retval
  2316. }
  2317. else if (MfObject.IsObjInstance(x, MfCharList))
  2318. {
  2319. retval := new MfMemoryString(0, 0, x.m_Encoding)
  2320. retval.m_MemView := ""
  2321. retval.m_MemView := MfMemStrView.FromCharList(x)
  2322. retval.m_CharCount := x.GetCharCount()
  2323. return this._FromAnyStatic(retval, x.m_Encoding) ; do another _FromAny in case encoding is different
  2324. }
  2325. else if (MfObject.IsObjInstance(x, MfObject))
  2326. {
  2327. str := x.ToString()
  2328. len := StrLen(str)
  2329. retval := new MfMemoryString(len, , encoding)
  2330. if (len > 0)
  2331. {
  2332. retval.Append(str)
  2333. }
  2334. return retval
  2335. }
  2336. else if (x.__Class = "MfMemStrView")
  2337. {
  2338. retval := new MfMemoryString(0, x.m_FillBytes, x.m_Encoding)
  2339. retval.m_MemView := ""
  2340. retval.m_MemView := x
  2341. retval.m_CharCount := x.GetCharCount()
  2342. return this._FromAnyStatic(retval, x.m_Encoding) ; do another _FromAny in case encoding is different
  2343. }
  2344. else
  2345. {
  2346. return new MfMemoryString(0, , encoding)
  2347. }
  2348. }
  2349. if (x = "")
  2350. {
  2351. return new MfMemoryString(0, , encoding)
  2352. }
  2353.  
  2354. len := StrLen(x)
  2355. retval := new MfMemoryString(len, , encoding)
  2356. if (len > 0)
  2357. {
  2358. retval.Append(x)
  2359. }
  2360. return retval
  2361. }
  2362. ; End:_FromAnyStatic ;}
  2363. ;{ _FromAny
  2364. ; instance method for converting var or obj into MfMemoryString
  2365. _FromAny(x) {
  2366. if (IsObject(x))
  2367. {
  2368. if(MfObject.IsObjInstance(x, MfMemoryString))
  2369. {
  2370. if (!(x.m_Encoding = this.m_Encoding))
  2371. {
  2372. return this._FromAny(x.ToString())
  2373. }
  2374. return x
  2375. }
  2376. else if (MfObject.IsObjInstance(x, MfString))
  2377. {
  2378. retval := new MfMemoryString(x.Length, this.m_FillBytes, this.m_Encoding)
  2379. if (x.Length > 0)
  2380. {
  2381. retval.Append(x.Value)
  2382. }
  2383. return retval
  2384. }
  2385. else if (MfObject.IsObjInstance(x, MfCharList))
  2386. {
  2387. retval := new MfMemoryString(0, x.m_FillBytes, x.m_Encoding)
  2388. retval.m_MemView := ""
  2389. retval.m_MemView := MfMemStrView.FromCharList(x)
  2390. retval.m_CharCount := x.GetCharCount()
  2391. return this._FromAny(retval) ; do another _FromAny in case encoding is different
  2392. }
  2393. else if (MfObject.IsObjInstance(x, MfObject))
  2394. {
  2395. str := x.ToString()
  2396. len := StrLen(str)
  2397. retval := new MfMemoryString(len, this.m_FillBytes, this.m_Encoding)
  2398. if (len > 0)
  2399. {
  2400. retval.Append(str)
  2401. }
  2402. return retval
  2403. }
  2404. else if (x.__Class = "MfMemStrView")
  2405. {
  2406. retval := new MfMemoryString(0, x.m_FillBytes, x.m_Encoding)
  2407. retval.m_MemView := ""
  2408. retval.m_MemView := x
  2409. retval.m_CharCount := x.GetCharCount()
  2410. return this._FromAny(retval) ; do another _FromAny in case encoding is different
  2411. }
  2412. else
  2413. {
  2414. return new MfMemoryString(0, this.m_FillBytes, this.m_Encoding)
  2415. }
  2416. }
  2417. if (x = "")
  2418. {
  2419. return new MfMemoryString(0, this.m_FillBytes, this.m_Encoding)
  2420. }
  2421.  
  2422. len := StrLen(x)
  2423. retval := new MfMemoryString(len, this.m_FillBytes, this.m_Encoding)
  2424. if (len > 0)
  2425. {
  2426. retval.Append(x)
  2427. }
  2428. return retval
  2429. }
  2430. ; End:_FromAny ;}
  2431. ;{ BufferPtr
  2432. /*!
  2433. Property: BufferPtr [get]
  2434. Gets the Buffer memory addres pointer for this instance
  2435. Value:
  2436. Var integer ptr representing the address
  2437. Remarks:
  2438. Readonly Property
  2439. */
  2440. BufferPtr[]
  2441. {
  2442. get {
  2443. return this.m_MemView[]
  2444. }
  2445. set {
  2446. ex := new MfNotSupportedException(MfEnvironment.Instance.GetResourceString("NotSupportedException_Readonly_Property"))
  2447. ex.SetProp(A_LineFile, A_LineNumber, "BufferPtr")
  2448. Throw ex
  2449. }
  2450. }
  2451. ; End:BufferPtr ;}
  2452. ;{ Length
  2453. /*!
  2454. Property: Length [get]
  2455. Gets the Length value associated with the this instance
  2456. Value:
  2457. Var representing the Length property of the instance
  2458. Remarks:
  2459. Readonly Property
  2460. */
  2461. Length[]
  2462. {
  2463. get {
  2464. return this.m_CharCount
  2465. }
  2466. set {
  2467. ex := new MfNotSupportedException(MfEnvironment.Instance.GetResourceString("NotSupportedException_Readonly_Property"))
  2468. ex.SetProp(A_LineFile, A_LineNumber, "Length")
  2469. Throw ex
  2470. }
  2471. }
  2472. ;
  2473. ; End:Length ;}
  2474. ;{ Capacity
  2475. /*!
  2476. Property: Capacity [get]
  2477. Gets the Capacity of the current instance in bytes
  2478. Value:
  2479. Var integer
  2480. Remarks:
  2481. Readonly Property
  2482. */
  2483. Capacity[]
  2484. {
  2485. get {
  2486. return this.m_MemView.Size
  2487. }
  2488. set {
  2489. ex := new MfNotSupportedException(MfEnvironment.Instance.GetResourceString("NotSupportedException_Readonly_Property"))
  2490. ex.SetProp(A_LineFile, A_LineNumber, "Size")
  2491. Throw ex
  2492. }
  2493. }
  2494. ; End:Capacity ;}
  2495. ;{ CharCapacity
  2496. /*!
  2497. Property: CharCapacity [get]
  2498. Gets the Capacity value in Chars for the current instance
  2499. Value:
  2500. Var integer
  2501. Remarks:
  2502. Readonly Property
  2503. */
  2504. CharCapacity[]
  2505. {
  2506. get {
  2507. return (this.m_MemView.Size - this.m_MemView.m_BytesPerChar) // this.m_MemView.m_BytesPerChar
  2508. }
  2509. set {
  2510. ex := new MfNotSupportedException(MfEnvironment.Instance.GetResourceString("NotSupportedException_Readonly_Property"))
  2511. ex.SetProp(A_LineFile, A_LineNumber, "CharCapacity")
  2512. Throw ex
  2513. }
  2514. }
  2515. ; End:CharCapacity ;}
  2516. ;{ FreeCapacity
  2517. /*!
  2518. Property: FreeCapacity [get]
  2519. Gets the FreeCapacity of the current instance in bytes
  2520. Value:
  2521. Var integer
  2522. Remarks:
  2523. Readonly Property
  2524. */
  2525. FreeCapacity[]
  2526. {
  2527. get {
  2528. return this.m_MemView.Size - (this.m_MemView.Pos + this.m_MemView.m_BytesPerChar)
  2529. }
  2530. set {
  2531. ex := new MfNotSupportedException(MfEnvironment.Instance.GetResourceString("NotSupportedException_Readonly_Property"))
  2532. ex.SetProp(A_LineFile, A_LineNumber, "FreeCapacity")
  2533. Throw ex
  2534. }
  2535. }
  2536. ; End:FreeCapacity ;}
  2537. ;{ FreeCharCapacity
  2538. /*!
  2539. Property: FreeCharCapacity [get]
  2540. Gets the number of characters that can be added to the current instance wihtout overflow
  2541. Value:
  2542. Var integer count in chars
  2543. Remarks:
  2544. Readonly Property
  2545. */
  2546. FreeCharCapacity[]
  2547. {
  2548. get {
  2549. retval := (this.m_MemView.Size - this.m_MemView.Pos) // this.m_MemView.m_BytesPerChar
  2550. return retval
  2551. }
  2552. set {
  2553. ex := new MfNotSupportedException(MfEnvironment.Instance.GetResourceString("NotSupportedException_Readonly_Property"))
  2554. ex.SetProp(A_LineFile, A_LineNumber, "FreeCharCapacity")
  2555. Throw ex
  2556. }
  2557. }
  2558. ; End:FreeCharCapacity ;}
  2559. ;{ UsedCapacity
  2560. /*!
  2561. Property: UsedCapacity [get]
  2562. Gets the UsedCapacity in bytes associated with the this instance
  2563. Value:
  2564. Var integer
  2565. Remarks:
  2566. Readonly Property
  2567. */
  2568. UsedCapacity[]
  2569. {
  2570. get {
  2571. return this.m_MemView.Pos - this.m_MemView.m_BytesPerChar
  2572. }
  2573. set {
  2574. ex := new MfNotSupportedException(MfEnvironment.Instance.GetResourceString("NotSupportedException_Readonly_Property"))
  2575. ex.SetProp(A_LineFile, A_LineNumber, "UsedCapacity")
  2576. Throw ex
  2577. }
  2578. }
  2579. ; End:UsedCapacity ;}
  2580. ;{ Byte
  2581. /*!
  2582. Property: Byte [get]
  2583. Gets/Sets the Byte value at the value of index
  2584. Value:
  2585. Var integer representing the Byte property of the instance from 0 to 255
  2586. Remarks:
  2587. Returns or sets byte value from 0 to 255 no matter the encoding.
  2588. Index is based on Capacity and not on char count
  2589. For UTF-16 valid byte reange will be 0 to char count x 2
  2590. Bytes can be read or set in any position with the current MfMemStrView inststance size
  2591. regardless of the current MfMemStrView Pos
  2592. */
  2593. Byte[index]
  2594. {
  2595. get {
  2596. _index := MfInteger.GetValue(index)
  2597. if (_index < 0 || _index >= this.m_MemView.Size)
  2598. {
  2599. ex := new MfArgumentOutOfRangeException(MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_Index"))
  2600. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  2601. throw ex
  2602. }
  2603. _index := _index
  2604. ptr := this.m_MemView[] + _index
  2605. num := NumGet(ptr + 0, 0, "UChar")
  2606. return num
  2607. }
  2608. set {
  2609. _index := MfInteger.GetValue(index)
  2610. if (_index < 0 || _index >= this.m_MemView.Size)
  2611. {
  2612. ex := new MfArgumentOutOfRangeException(MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_Index"))
  2613. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  2614. throw ex
  2615. }
  2616. _value := MfInteger.GetValue(value)
  2617. if (_value < 0x0 || _value > 0xff)
  2618. {
  2619. ex := new MfException(MfEnvironment.Instance.GetResourceString("InvalidCastException_ValueToChar"))
  2620. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  2621. throw ex
  2622. }
  2623. ptr := this.m_MemView[] + _index
  2624. NumPut(_value, ptr + 0, 0, "UChar")
  2625. }
  2626. }
  2627. ; End:Byte ;}
  2628. ;{ CharCode
  2629. /*!
  2630. Property: CharCode [get/set]
  2631. Gets or sets the CharCode value matching the index value
  2632. Value:
  2633. Var integer
  2634. Remarks:
  2635. If Bytes per char is 2 then value can be from 0x0 to 0xFFFF,
  2636. bytes per char 4 then value can be from 0x0 to 0xFFFFFFFF; Otherwise
  2637. value will be between 0x0 and 0xFF
  2638. */
  2639. CharCode[index]
  2640. {
  2641. get {
  2642. _index := MfInteger.GetValue(index)
  2643. if (_index < 0 || _index >= this.m_CharCount)
  2644. {
  2645. ex := new MfArgumentOutOfRangeException(MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_Index"))
  2646. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  2647. throw ex
  2648. }
  2649. _index := _index * this.m_BytesPerChar
  2650. ptr := this.m_MemView[] + _index
  2651. num := NumGet(ptr + 0, 0, this.m_sType)
  2652. return num
  2653. }
  2654. set {
  2655. _index := MfInteger.GetValue(index)
  2656. if (_index < 0 || _index >= this.m_CharCount)
  2657. {
  2658. ex := new MfArgumentOutOfRangeException(MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_Index"))
  2659. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  2660. throw ex
  2661. }
  2662. if (this.m_BytesPerChar = 4)
  2663. {
  2664. _value := MfInt64.GetValue(value)
  2665. if (_value < 0x0 || _value > 0xffffffff)
  2666. {
  2667. ex := new MfException(MfEnvironment.Instance.GetResourceString("InvalidCastException_ValueToInteger"))
  2668. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  2669. throw ex
  2670. }
  2671. }
  2672. else if (this.m_BytesPerChar = 2)
  2673. {
  2674. _value := MfInteger.GetValue(value)
  2675. if (_value < 0x0 || _value > 0xffff)
  2676. {
  2677. ex := new MfException(MfEnvironment.Instance.GetResourceString("InvalidCastException_ValueToByte"))
  2678. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  2679. throw ex
  2680. }
  2681. }
  2682. else
  2683. {
  2684. _value := MfInteger.GetValue(value)
  2685. if (_value < 0x0 || _value > 0xff)
  2686. {
  2687. ex := new MfException(MfEnvironment.Instance.GetResourceString("InvalidCastException_ValueToChar"))
  2688. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  2689. throw ex
  2690. }
  2691. }
  2692. _index := _index * this.m_BytesPerChar
  2693. ptr := this.m_MemView[] + _index
  2694. NumPut(_value, ptr+0, 0, this.m_sType)
  2695. }
  2696. }
  2697. ; End:CharCode ;}
  2698. ;{ Char
  2699. /*!
  2700. Property: Char [get/set]
  2701. Gets or sets the Char value matching the index value
  2702. Value:
  2703. Var strign representing the Char
  2704. Remarks:
  2705. If setting value then only the first character is consider of a string
  2706. */
  2707. Char[index]
  2708. {
  2709. get {
  2710. _index := MfInteger.GetValue(index)
  2711. if (_index < 0 || _index >= this.m_CharCount)
  2712. {
  2713. ex := new MfArgumentOutOfRangeException(MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_Index"))
  2714. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  2715. throw ex
  2716. }
  2717. _index := _index * this.m_BytesPerChar
  2718. ptr := this.m_MemView[] + _index
  2719. num := NumGet(ptr + 0, 0, this.m_sType)
  2720. if (num = 0)
  2721. {
  2722. return ""
  2723. }
  2724. return Chr(num)
  2725. }
  2726. set {
  2727. _index := MfInteger.GetValue(index)
  2728. if (_index < 0 || _index >= this.m_CharCount)
  2729. {
  2730. ex := new MfArgumentOutOfRangeException(MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_Index"))
  2731. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  2732. throw ex
  2733. }
  2734. _index := _index * this.m_BytesPerChar
  2735. ptr := this.m_MemView[] + _index
  2736. NumPut(Asc(value), ptr + 0, 0, this.m_sType)
  2737. }
  2738. }
  2739. ; End:Char ;}
  2740.  
  2741. ;{ Pos
  2742. /*!
  2743. Property: Pos [get/set]
  2744. Gets or sets the Pos value associated with the this instance
  2745. Value:
  2746. Var integer representing the Pos property of the instance
  2747. Throws:
  2748. Throws MfIndexOutOfRangeException
  2749. Remarks:
  2750. Changing the value Pos can affect the ToString() and other methods
  2751. */
  2752. Pos[]
  2753. {
  2754. get {
  2755. return this.m_MemView.Pos
  2756. }
  2757. set {
  2758. pos := MfInteger.GetValue(Value)
  2759. if (pos < 0)
  2760. {
  2761. ex := new MfIndexOutOfRangeException(MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"))
  2762. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  2763. throw ex
  2764. }
  2765. if (Pos > this.m_MemView.Size)
  2766. {
  2767. ex := new MfIndexOutOfRangeException(MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_ArrayListInsert"))
  2768. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  2769. throw ex
  2770. }
  2771. this.m_MemView.Pos := pos
  2772.  
  2773. }
  2774. }
  2775. ; End:Pos ;}
  2776. ;{ Size
  2777. /*!
  2778. Property: Size [get]
  2779. Gets the Size in bytes of the current buffer
  2780. Value:
  2781. Var representing the Size property of the instance
  2782. Remarks:
  2783. Readonly Property
  2784. */
  2785. Size[]
  2786. {
  2787. get {
  2788. return this.m_MemView.Size
  2789. }
  2790. set {
  2791. ex := new MfNotSupportedException(MfEnvironment.Instance.GetResourceString("NotSupportedException_Readonly_Property"))
  2792. ex.SetProp(A_LineFile, A_LineNumber, "Size")
  2793. Throw ex
  2794. }
  2795. }
  2796. ; End:Size ;}
  2797.  
  2798.  
  2799. }
  2800.  
  2801. /* Class: MfMemStrView
  2802. * Methods
  2803. * _NewEnum() Gets an enumerator that loops through the current instance char numbers
  2804. * Append() Appends obj instance to this instance
  2805. * AppendCharCode() Appends a Charcode number to current instance
  2806. * AppendString() Appends a string var to current instance
  2807. * GetStringIgnoreNull() Gets an instance of MfMemStrView from current instance that has excluded all null values
  2808. * Clone() Clones the current instance and returns a copy
  2809. * CompareOrdinal() Compares two instance of MfMemStrView as Ordinal
  2810. * CompareOrdinalIgnoreCase() Compares two instance of MfMemStrView as Ordinal ignoring case
  2811. * CompareOrdinalSub() Compares two sub values of instances of MfMemStrView as Ordinal, optionally ignoring case.
  2812. * Copy() Copies the Source MfMemStrView bytes instance to destination MfMemStrView
  2813. * CopyFromAddress() Copies the Source address bytes to destination MfMemStrView
  2814. * CopyFromAddressToCharList() Copies the Source address bytes to destination MfCharList
  2815. * Diff() Gets the Difference between argument objA and argument objB argument with an included Max Distance.
  2816. * EndsWithFromPos() Checks to see if obj ends with the same char as this instance
  2817. * EqualsSubString() Compares two MfMemStrView objects to see if their subPositions are equal
  2818. * Equals() Check to see if current instance is equal string as Obj
  2819. * EqualsString() Check to see if current instance is equal with str
  2820. * Expand() Expands the current buffer Adding new bytes
  2821. * FromArray() Creates new isntance of MfMemBlkView from AutoHotkey one based byte array
  2822. * FromByteList() Converts MfByteList into MfMemStrView instance
  2823. * FromBase64() Reads buffer and returns UTF-8 or UTF-16 buffer from base64
  2824. * GetCharCount() Gets the number of chars currently in this buffer instance
  2825. * GetStringIgnoreNull() Gets an instance of MfMemStrView from current instance that has excluded all null values
  2826. * InBuffer() Searches current instance for the first instance of NeedleObj from StartOffset
  2827. * InBufferRev() Searches current instance for the last instance of NeedleObj from EndOffset
  2828. * InBuf() Blazing fast machine-code CASE-SENSITIVE searching in a (binary) buffer for a sequence of bytes,
  2829. * that may include NULL characters.
  2830. * InBufRev() Blazing fast machine-code CASE-SENSITIVE searching in a (binary) buffer for a sequence of bytes,
  2831. * that may include NULL characters. Reverse look for binary Needle in binary Buffer
  2832. * IndexOf() Gets the First index of NeedleObj in current instance
  2833. * Insert() Inserts the contents of obj into current instance
  2834. * InsertStr() Inserts the contents of str into current instance
  2835. * IsWhiteSpace() Check to see if a char number is considered to be whitespace
  2836. * LastIndexOf() Gets the last index of NeedleObj in current instance
  2837. * MoveBytesLeft() Moves bytes to the left in the current instance.
  2838. * MoveBytesRight() Moves Bytes to the Right in the current instance
  2839. * OverWrite() Overwrites the bytes in this instance with the bytes in obj instance
  2840. * Reverse() Reverses the contentes of the currrent instance and returne it as a new instance
  2841. * ToBase64() Reads instanceof MfMemStrView and returns a new MfMemStrView as base64 equal UTF-8 Encoded
  2842. * ToCharList() Gets a copy of the current instance as MfCharList
  2843. * ToString() Gets the value of this instance as string var
  2844. * TrimBufferToPos() Trims the current size to the current Pos
  2845. * TrimStart() Trims all whitespace char from start of current instance
  2846. * TrimStartChars() Trims char(s) from the start of a string
  2847. * TrimEnd() Trims all whitespace char from end of current instance
  2848. * TrimStartChars() Trims char(s) from the end of a string
  2849. * TrimMemoryRight() Overwrites memory bytes with fillbytes for the end of a string, Erases end of a string
  2850. * StringsAreEqual() Binary comparsion of string in memory
  2851. * SubSet() Gets a sub set (sub string) of the currrent instance chars
  2852. *
  2853. * Internal Class
  2854. * A MfMemStrView object is used to represent a raw binary data buffer. This class
  2855. * extends from MfMemBlkView allowing you to directly manipulate its contents.
  2856. */
  2857. class MfMemStrView extends MfMemBlkView
  2858. {
  2859. m_FillBytes := ""
  2860. m_Encoding := ""
  2861. m_EncodingName := ""
  2862. m_BytesPerChar := ""
  2863. m_sType := ""
  2864. m_isAddr := False
  2865. /* Constructor: __New
  2866. * Instantiates an object that represents a memory-block array
  2867. * Syntax:
  2868. * oBuf := new MfMemStrView( size [ , FillByte := 0 ] )
  2869. * Parameter(s):
  2870. * oBuf [retval] - a MfMemStrView object
  2871. * size [in] - size of the buffer in bytes
  2872. * FillByte [in, opt] - similar to VarSetCapacity's 'FillByte' parameter
  2873. */
  2874. __New(size, FillByte:=0, encoding:="", address:=0) {
  2875. if (MfString.IsNullOrEmpty(Encoding))
  2876. {
  2877. If (A_IsUnicode)
  2878. {
  2879. Encoding := "UTF-16"
  2880. }
  2881. else
  2882. {
  2883. Encoding := "cp1252"
  2884. }
  2885. }
  2886. StringReplace, _Encoding, Encoding, -, , ALL
  2887. this.m_Encoding := Encoding
  2888. if (Encoding = "UTF-32")
  2889. {
  2890. this.m_BytesPerChar := 4
  2891. this.m_sType := "UInt"
  2892. }
  2893. else if (Encoding = "UTF-16" || Encoding = "CP1200")
  2894. {
  2895. this.m_BytesPerChar := 2
  2896. this.m_sType := "UShort"
  2897. }
  2898. else
  2899. {
  2900. this.m_BytesPerChar := 1
  2901. this.m_sType := "UChar"
  2902. }
  2903. address := MfInt64.GetValue(address, 0)
  2904.  
  2905. this.m_EncodingName := _Encoding
  2906. this.m_FillBytes := FillByte
  2907.  
  2908. if (Address > 0)
  2909. {
  2910. base.__New(Address + 0,, size)
  2911. this.m_isAddr := true
  2912. }
  2913. else
  2914. {
  2915. ObjSetCapacity(this, "_Buffer", size)
  2916. base.__New(ObjGetAddress(this, "_Buffer"),, size)
  2917. this._FillByte(size, Fillbyte, this.m_BytesPerChar)
  2918. }
  2919.  
  2920. }
  2921.  
  2922. ;{ _FillByte
  2923. ; Fill the memory space with fillbyte considering BytesPerChar
  2924. _FillByte(Size, FillByte, BytesPerChar, Address="") {
  2925. if (Address == "")
  2926. {
  2927. Address := this[]
  2928. }
  2929. if (FillByte = 0x0 || BytesPerChar = 1)
  2930. {
  2931. DllCall("RtlFillMemory", "PTR", Address + 0, "PTR", size, "UCHAR", FillByte)
  2932. return
  2933. }
  2934. if (BytesPerChar = 2 && FillByte >= 0x0 && FillByte <= 0xFFFF)
  2935. {
  2936. i := 0
  2937. addr := Address
  2938. sType := "UShort"
  2939. While (i < Size)
  2940. {
  2941. NumPut(FillByte, addr + i, 0, sType)
  2942. i += 2
  2943. }
  2944. return
  2945. }
  2946. if (BytesPerChar = 4 && FillByte >= 0x0 && FillByte <= 0xFFFFFFFF)
  2947. {
  2948. i := 0
  2949. addr := Address
  2950. sType := "UInt"
  2951. While (i < Size)
  2952. {
  2953. NumPut(FillByte, addr + i, 0, sType)
  2954. i += 4
  2955. }
  2956. return
  2957. }
  2958. }
  2959. ; End:_FillByte ;}
  2960. ;{ Append
  2961.  
  2962. /*
  2963. Method: Append()
  2964.  
  2965. Append()
  2966. Appends obj instance to this instance
  2967. Parameters:
  2968. obj
  2969. Instance of MfMemStrView
  2970. Returns:
  2971. Returns the number of chars in this instance
  2972. Throws:
  2973. Throws MfArgumentException
  2974. Remarks:
  2975. see AppendString to append string var
  2976. */
  2977. Append(obj) {
  2978.  
  2979. if (obj.__Class != "MfMemStrView")
  2980. {
  2981. ex := new MfArgumentException(MfEnvironment.Instance.GetResourceString("Argument_NonMfObjectWithParamName", "obj", "MfMemStrView"), "obj")
  2982. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  2983. throw ex
  2984. }
  2985.  
  2986. If (obj.Pos <= obj.m_BytesPerChar)
  2987. {
  2988. return 0 ; this.GetCharCount()
  2989. }
  2990. if (!(this.m_Encoding = obj.m_Encoding))
  2991. {
  2992. return this.AppendString(obj.ToString())
  2993. }
  2994. BytesPerChar := this.m_BytesPerChar
  2995. len := obj.Pos - BytesPerChar
  2996. if (len <= 0)
  2997. {
  2998. return 0
  2999. }
  3000.  
  3001. BufferFree := this.Size - this.Pos
  3002.  
  3003. if (len > BufferFree)
  3004. {
  3005. ex := new MfOverflowException(MfEnvironment.Instance.GetResourceString("Overflow_General"))
  3006. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  3007. throw ex
  3008. }
  3009. if (!(obj.m_Encoding = this.m_Encoding))
  3010. {
  3011. ; if encodingis different then add by string
  3012. return this.AppendString(obj.ToString())
  3013. }
  3014. PI := this.Pos
  3015. BytesPerChar := this.m_BytesPerChar
  3016. if (PI > 0)
  3017. {
  3018. this.Pos -= BytesPerChar
  3019. }
  3020.  
  3021. ;~ sType := this.m_sType
  3022. ;~ i := 0
  3023. ;~ thisAddress := this[]
  3024. ;~ objAddress := obj[]
  3025.  
  3026. ;~ while ( i < len)
  3027. ;~ {
  3028. ;~ num := NumGet(objAddress + 0 ,i, sType)
  3029. ;~ NumPut(num, thisAddress + 0, this.Pos, sType)
  3030. ;~ this.Pos += BytesPerChar
  3031. ;~ i += BytesPerChar
  3032. ;~ }
  3033.  
  3034. ptr := this[] + this.Pos
  3035. sourcePtr := obj[]
  3036. Length := obj.Pos - BytesPerChar
  3037. DllCall("RtlMoveMemory", "PTR", ptr + 0, "PTR", sourcePtr + 0, "UCHAR", Length)
  3038. ;this.Pos := PI + Length
  3039. if (PI + Length + BytesPerChar <= this.Size)
  3040. {
  3041. this.Pos += Length + BytesPerChar
  3042. }
  3043. else
  3044. {
  3045. this.Pos := this.Size
  3046. }
  3047. chars := Length // BytesPerChar
  3048. return chars
  3049. }
  3050. ; End:Append ;}
  3051. ;{ AppendCharCode
  3052. /*
  3053. Method: AppendCharCode()
  3054.  
  3055. AppendCharCode()
  3056. Appends a Charcode number to current instance
  3057. Parameters:
  3058. cc
  3059. Char code as integer number to add
  3060. Returns:
  3061. Returns the number of chars in this instance
  3062. Throws:
  3063. Throws MfArgumentException if cc is outsite of current encoding range
  3064. Remarks:
  3065. cc must be a positive number
  3066. */
  3067. AppendCharCode(cc) {
  3068. if (cc < 0x0)
  3069. {
  3070. ex := new MfArgumentException(MfEnvironment.Instance.GetResourceString("InvalidCastException_ValueToChar"), "cc")
  3071. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  3072. throw ex
  3073. }
  3074. BytesPerChar := this.m_BytesPerChar
  3075. sType := this.m_sType
  3076. if (BytesPerChar = 1)
  3077. {
  3078. if ( cc > 0xFF)
  3079. {
  3080. ex := new MfArgumentException(MfEnvironment.Instance.GetResourceString("InvalidCastException_ValueToChar"), "cc")
  3081. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  3082. throw ex
  3083. }
  3084. }
  3085. else if (BytesPerChar = 2)
  3086. {
  3087. if ( cc > 0xFFFF)
  3088. {
  3089. ex := new MfArgumentException(MfEnvironment.Instance.GetResourceString("InvalidCastException_ValueToChar"), "cc")
  3090. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  3091. throw ex
  3092. }
  3093. }
  3094. else if (BytesPerChar = 4)
  3095. {
  3096. if ( cc > 0xFFFFFFFF)
  3097. {
  3098. ex := new MfArgumentException(MfEnvironment.Instance.GetResourceString("InvalidCastException_ValueToChar"), "cc")
  3099. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  3100. throw ex
  3101. }
  3102. }
  3103. PI := this.Pos
  3104. if (PI > 0)
  3105. {
  3106. this.Pos -= BytesPerChar
  3107. }
  3108. else
  3109. {
  3110. PI := BytesPerChar
  3111. }
  3112. ptr := this[] + this.Pos
  3113. NumPut(cc, ptr + 0, 0, sType)
  3114. this.Pos := PI + BytesPerChar
  3115. chars := 1 ;(this.Pos - PI) // BytesPerChar
  3116. return chars
  3117. }
  3118. ; End:AppendCharCode ;}
  3119. ;{ AppendString
  3120. /*
  3121. Method: AppendString()
  3122.  
  3123. AppendString()
  3124. Appends a string var to current instance
  3125. Parameters:
  3126. s
  3127. Teh string var to append
  3128. Returns:
  3129. Returns the number of chars in this instance
  3130. Remarks:
  3131. see Append to append instance of MfMemStrView
  3132. */
  3133. AppendString(s) {
  3134. len := ""
  3135. if (IsObject(s))
  3136. {
  3137. if (MfObject.IsObjInstance(s, MfString))
  3138. {
  3139. len := s.Length * this.m_BytesPerChar
  3140. str := s.Value
  3141. }
  3142. else if (MfObject.IsObjInstance(s, MfObject))
  3143. {
  3144. str := s.ToString()
  3145. len := StrLen(str) * this.m_BytesPerChar
  3146. }
  3147. else
  3148. {
  3149. ex := new MfArgumentException(MfEnvironment.Instance.GetResourceString("NonMfObjectException_General"), "s")
  3150. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  3151. throw ex
  3152. }
  3153. }
  3154. else
  3155. {
  3156. str := s
  3157. ;len := StrPut(str, this.m_Encoding) * this.m_BytesPerChar
  3158. len := StrLen(str) * this.m_BytesPerChar
  3159. }
  3160.  
  3161. if (len <= 0)
  3162. {
  3163. return 0
  3164. }
  3165.  
  3166. BufferFree := this.Size - this.Pos
  3167.  
  3168.  
  3169. if (len > BufferFree)
  3170. {
  3171. ex := new MfOverflowException(MfEnvironment.Instance.GetResourceString("Overflow_General"))
  3172. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  3173. throw ex
  3174. }
  3175. ;this.m_MemView.Seek()
  3176. if (this.Pos > 0)
  3177. {
  3178. ; remove line terminator befor addign new text
  3179. this.Pos -= this.m_BytesPerChar
  3180. }
  3181. methodName := "Write" . this.m_EncodingName
  3182. chars := this.__Call(methodName, str)
  3183. chars := chars > 0 ? chars - 1 : chars
  3184. return chars
  3185. }
  3186. ; End:AppendString ;}
  3187. ;{ Clone
  3188. /*
  3189. Method: Clone()
  3190.  
  3191. Clone()
  3192. Clones the current instance and returns a copy
  3193. Returns:
  3194. Returns copy of current instance
  3195. */
  3196. Clone() {
  3197. objMemBlk := new MfMemStrView(this.Size, this.m_FillBytes, this.m_Encoding)
  3198. newAddress := objMemBlk[]
  3199. Address := this[]
  3200. DllCall("RtlMoveMemory", "PTR", newAddress + 0, "PTR", Address + 0, "UCHAR", this.Size)
  3201. objMemBlk.Pos := this.Pos
  3202. return objMemBlk
  3203. }
  3204. ; End:Clone ;}
  3205. ;{ CompareOrdinal
  3206. /*
  3207. Method: CompareOrdinal()
  3208.  
  3209. CompareOrdinal()
  3210. Compares two instance of MfMemStrView as Ordinal
  3211. Parameters:
  3212. objA
  3213. The first instance of MfMemStrView to compare
  3214. objB
  3215. The Second instance of MfMemStrView to compare
  3216. Returns:
  3217. Returns integer of 0 if equal, if objA is greater then objB the positive number is returned; Otherwise negative number
  3218. Throws:
  3219. Throws MfArgumentException
  3220. Throw MfFormatException is encodings are not the same
  3221. Remarks:
  3222. Static Method
  3223. */
  3224. CompareOrdinal(objA, objB) {
  3225. if (ObjA.__Class != "MfMemStrView")
  3226. {
  3227. ex := new MfArgumentException(MfEnvironment.Instance.GetResourceString("Argument_NonMfObjectWithParamName", "ObjA", "MfMemStrView"), "ObjA")
  3228. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  3229. throw ex
  3230. }
  3231. if (ObjB.__Class != "MfMemStrView")
  3232. {
  3233. ex := new MfArgumentException(MfEnvironment.Instance.GetResourceString("Argument_NonMfObjectWithParamName", "ObjB", "MfMemStrView"), "ObjB")
  3234. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  3235. throw ex
  3236. }
  3237. if (!(objA.m_Encoding = objB.m_Encoding))
  3238. {
  3239. ex := new MfFormatException(MfEnvironment.Instance.GetResourceString("Format_Encoding_MisMatch"))
  3240. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  3241. throw ex
  3242. }
  3243. if (objA == "")
  3244. {
  3245. return -1
  3246. }
  3247. if (objB == "")
  3248. {
  3249. return 1
  3250. }
  3251. BytesPerChar := objA.m_BytesPerChar
  3252. sType := objA.m_sType
  3253. ptrA := objA[] ; first char address
  3254. ptrB := objB[] ; frist char address
  3255. numA := NumGet(ptrA + 0, 0, sType)
  3256. numB := NumGet(ptrB + 0, 0, sType)
  3257. comp := numA - numB
  3258. if (comp != 0)
  3259. {
  3260. return comp
  3261. }
  3262. return MfMemStrView._CompareOrdinalHelper(objA, objB)
  3263. }
  3264. ; End:CompareOrdinal ;}
  3265. ;{ CompareIgnoreCase
  3266. ;{ CompareOrdinalIgnoreCase
  3267. /*
  3268. Method: CompareOrdinalIgnoreCase()
  3269.  
  3270. CompareOrdinalIgnoreCase()
  3271. Compares two instance of MfMemStrView as Ordinal ignoring case
  3272. Parameters:
  3273. objA
  3274. The first instance of MfMemStrView to compare
  3275. objB
  3276. The Second instance of MfMemStrView to compare
  3277. Returns:
  3278. Returns integer of 0 if equal, if objA is greater then objB the positive number is returned; Otherwise negative number
  3279. Throws:
  3280. Throws MfArgumentException
  3281. Throw MfFormatException is encodings are not the same
  3282. Remarks:
  3283. Static Method
  3284. */
  3285. CompareOrdinalIgnoreCase(ByRef objA, ByRef objB) {
  3286. if (ObjA.__Class != "MfMemStrView")
  3287. {
  3288. ex := new MfArgumentException(MfEnvironment.Instance.GetResourceString("Argument_NonMfObjectWithParamName", "ObjA", "MfMemStrView"), "ObjA")
  3289. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  3290. throw ex
  3291. }
  3292. if (ObjB.__Class != "MfMemStrView")
  3293. {
  3294. ex := new MfArgumentException(MfEnvironment.Instance.GetResourceString("Argument_NonMfObjectWithParamName", "ObjB", "MfMemStrView"), "ObjB")
  3295. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  3296. throw ex
  3297. }
  3298. if (!(objA.m_Encoding = objB.m_Encoding))
  3299. {
  3300. ex := new MfFormatException(MfEnvironment.Instance.GetResourceString("Format_Encoding_MisMatch"))
  3301. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  3302. throw ex
  3303. }
  3304. BytesPerChar := objA.m_BytesPerChar
  3305. sType := objA.m_sType
  3306. i := objA.Pos > objB.Pos ? objB.Pos : objA.Pos
  3307. i -= BytesPerChar
  3308. num := -1
  3309. AddressA := objA[]
  3310. AddressB := objB[]
  3311. ptrA := objA[] ; first char address
  3312. ptrB := objB[] ; frist char address
  3313. While (i >= 5 * BytesPerChar)
  3314. {
  3315. numA := NumGet(ptrA + 0, 0, sType)
  3316. numB := NumGet(ptrB + 0, 0, sType)
  3317. if (numA != numB)
  3318. {
  3319. If (MfMemStrView._IsLatin1(numA) && MfMemStrView._IsLatin1(numB))
  3320. {
  3321. if (!MfMemStrView._IsEqualLatin1IgnoreCase(numA, numB))
  3322. {
  3323. num := 0
  3324. break
  3325. }
  3326. }
  3327. Else
  3328. {
  3329. chrA := Chr(NumA)
  3330. chrB := Chr(NumB)
  3331. if (!(chrA = chrB))
  3332. {
  3333. num := 0
  3334. break
  3335. }
  3336. }
  3337.  
  3338. }
  3339. numA := NumGet(ptrA + BytesPerChar, 0, sType)
  3340. numB := NumGet(ptrB + BytesPerChar, 0, sType)
  3341. if (numA != numB)
  3342. {
  3343. If (MfMemStrView._IsLatin1(numA) && MfMemStrView._IsLatin1(numB))
  3344. {
  3345. if (!MfMemStrView._IsEqualLatin1IgnoreCase(numA, numB))
  3346. {
  3347. num := BytesPerChar
  3348. break
  3349. }
  3350. }
  3351. Else
  3352. {
  3353. chrA := Chr(NumA)
  3354. chrB := Chr(NumB)
  3355. if (!(chrA = chrB))
  3356. {
  3357. num := BytesPerChar
  3358. break
  3359. }
  3360. }
  3361. }
  3362. numA := NumGet(ptrA + (BytesPerChar * 2), 0, sType)
  3363. numB := NumGet(ptrB + (BytesPerChar * 2), 0, sType)
  3364. if (numA != numB)
  3365. {
  3366. If (MfMemStrView._IsLatin1(numA) && MfMemStrView._IsLatin1(numB))
  3367. {
  3368. if (!MfMemStrView._IsEqualLatin1IgnoreCase(numA, numB))
  3369. {
  3370. num := BytesPerChar * 2
  3371. break
  3372. }
  3373. }
  3374. Else
  3375. {
  3376. chrA := Chr(NumA)
  3377. chrB := Chr(NumB)
  3378. if (!(chrA = chrB))
  3379. {
  3380. num := BytesPerChar * 2
  3381. break
  3382. }
  3383. }
  3384. }
  3385. numA := NumGet(ptrA + (BytesPerChar * 3), 0, sType)
  3386. numB := NumGet(ptrB + (BytesPerChar * 3), 0, sType)
  3387. if (numA != numB)
  3388. {
  3389. If (MfMemStrView._IsLatin1(numA) && MfMemStrView._IsLatin1(numB))
  3390. {
  3391. if (!MfMemStrView._IsEqualLatin1IgnoreCase(numA, numB))
  3392. {
  3393. num := BytesPerChar * 3
  3394. break
  3395. }
  3396. }
  3397. Else
  3398. {
  3399. chrA := Chr(NumA)
  3400. chrB := Chr(NumB)
  3401. if (!(chrA = chrB))
  3402. {
  3403. num := BytesPerChar * 3
  3404. break
  3405. }
  3406. }
  3407. }
  3408. numA := NumGet(ptrA + (BytesPerChar * 4), 0, sType)
  3409. numB := NumGet(ptrB + (BytesPerChar * 4), 0, sType)
  3410. if (numA != numB)
  3411. {
  3412. If (MfMemStrView._IsLatin1(numA) && MfMemStrView._IsLatin1(numB))
  3413. {
  3414. if (!MfMemStrView._IsEqualLatin1IgnoreCase(numA, numB))
  3415. {
  3416. num := BytesPerChar * 4
  3417. break
  3418. }
  3419. }
  3420. Else
  3421. {
  3422. chrA := Chr(NumA)
  3423. chrB := Chr(NumB)
  3424. if (!(chrA = chrB))
  3425. {
  3426. num := BytesPerChar * 4
  3427. break
  3428. }
  3429. }
  3430. }
  3431. ptrA += BytesPerChar * 5
  3432. ptrB += BytesPerChar * 5
  3433. i -= BytesPerChar * 5
  3434. }
  3435. if (num != -1)
  3436. {
  3437. ptrA += num
  3438. ptrB += num
  3439. numA := NumGet(ptrA + 0, 0, sType)
  3440. numB := NumGet(ptrB + 0, 0, sType)
  3441. If (MfMemStrView._IsLatin1(numA) && MfMemStrView._IsLatin1(numB))
  3442. {
  3443. if (MfMemStrView._IsEqualLatin1IgnoreCase(numA, numB))
  3444. {
  3445. result := 0
  3446. }
  3447. Else
  3448. {
  3449. result := numA - numB
  3450. }
  3451. }
  3452. else
  3453. {
  3454. chrA := Chr(NumA)
  3455. chrB := Chr(NumB)
  3456. if (chrA = chrB)
  3457. {
  3458. result := 0
  3459. }
  3460. else
  3461. {
  3462. result := numA - numB
  3463. }
  3464. }
  3465. if (result != 0)
  3466. {
  3467. return result
  3468. }
  3469. numA := NumGet(ptrA + BytesPerChar, 0, sType)
  3470. numB := NumGet(ptrB + BytesPerChar, 0, sType)
  3471. If (MfMemStrView._IsLatin1(numA) && MfMemStrView._IsLatin1(numB))
  3472. {
  3473. if (MfMemStrView._IsEqualLatin1IgnoreCase(numA, numB))
  3474. {
  3475. result := 0
  3476. }
  3477. Else
  3478. {
  3479. result := numA - numB
  3480. }
  3481. }
  3482. else
  3483. {
  3484. chrA := Chr(NumA)
  3485. chrB := Chr(NumB)
  3486. if (chrA = chrB)
  3487. {
  3488. result := 0
  3489. }
  3490. else
  3491. {
  3492. result := numA - numB
  3493. }
  3494. }
  3495. return result
  3496. }
  3497. else
  3498. {
  3499. while (i > 0)
  3500. {
  3501. numA := NumGet(ptrA + 0, 0, sType)
  3502. numB := NumGet(ptrB + 0, 0, sType)
  3503. if (numA != numB)
  3504. {
  3505. If (MfMemStrView._IsLatin1(numA) && MfMemStrView._IsLatin1(numB))
  3506. {
  3507. if (!MfMemStrView._IsEqualLatin1IgnoreCase(numA, numB))
  3508. {
  3509. break
  3510. }
  3511. }
  3512. else
  3513. {
  3514. chrA := Chr(NumA)
  3515. chrB := Chr(NumB)
  3516. if (!(chrA = chrB))
  3517. {
  3518. break
  3519. }
  3520. }
  3521. }
  3522. ptrA += BytesPerChar
  3523. ptrB += BytesPerChar
  3524. i -= BytesPerChar
  3525. }
  3526. if (i <= 0)
  3527. {
  3528. return objA.Pos - objB.Pos
  3529. }
  3530. numA := NumGet(ptrA + 0, 0, sType)
  3531. numB := NumGet(ptrB + 0, 0, sType)
  3532. result := 0
  3533. if (numA != numB)
  3534. {
  3535. If (MfMemStrView._IsLatin1(numA) && MfMemStrView._IsLatin1(numB))
  3536. {
  3537. if (!MfMemStrView._IsEqualLatin1IgnoreCase(numA, numB))
  3538. {
  3539. result := numA - numB
  3540. }
  3541. }
  3542. else
  3543. {
  3544. chrA := Chr(NumA)
  3545. chrB := Chr(NumB)
  3546. if (!(chrA = chrB))
  3547. {
  3548. result := numA - numB
  3549. }
  3550. }
  3551. }
  3552. if (result != 0)
  3553. {
  3554. return result
  3555. }
  3556. numA := NumGet(ptrA + BytesPerChar, 0, sType)
  3557. numB := NumGet(ptrB + BytesPerChar, 0, sType)
  3558. if (numA != numB)
  3559. {
  3560. If (MfMemStrView._IsLatin1(numA) && MfMemStrView._IsLatin1(numB))
  3561. {
  3562. if (!MfMemStrView._IsEqualLatin1IgnoreCase(numA, numB))
  3563. {
  3564. result := numA - numB
  3565. }
  3566. }
  3567. else
  3568. {
  3569. chrA := Chr(NumA)
  3570. chrB := Chr(NumB)
  3571. if (!(chrA = chrB))
  3572. {
  3573. result := numA - numB
  3574. }
  3575. }
  3576. }
  3577. return result
  3578. }
  3579. }
  3580. ; End:CompareIgnoreCase ;}
  3581. ;{ CompareOrdinalSub
  3582. /*
  3583. Method: CompareOrdinalSub()
  3584.  
  3585. CompareOrdinalSub()
  3586. Compares two sub values of instances of MfMemStrView as Ordinal, optionally ignoring case.
  3587. Parameters:
  3588. objA
  3589. The first instance of MfMemStrView to compare
  3590. indexA
  3591. The zero based index location within objA to start comparing.
  3592. Index location is base upon the char count
  3593. objB
  3594. The Second instance of MfMemStrView to compare
  3595. indexB
  3596. The zero based index location within objB to start comparing.
  3597. Index location is base upon the char count
  3598. len
  3599. The length of the string to compare, this is the length of number of characters
  3600. Default value is -1. If default then len is converted to the length of the shortest value after index of objA and objB.
  3601. ignoreCase
  3602. If true case is considered when comparing; Otherwise case is ignored.
  3603. The default is false
  3604. Returns:
  3605. Returns integer of 0 if equal, if objA is greater then objB the positive number is returned; Otherwise negative number
  3606. Throws:
  3607. Throws MfArgumentException
  3608. Throws MfIndexOutOfRangeException
  3609. Throw MfFormatException is encodings are not the same
  3610. Remarks:
  3611. Static Method
  3612. */
  3613. CompareOrdinalSub(byref objA, indexA, byRef objB, indexB, len=-1, ignoreCase=false) {
  3614. if (ObjA.__Class != "MfMemStrView")
  3615. {
  3616. ex := new MfArgumentException(MfEnvironment.Instance.GetResourceString("Argument_NonMfObjectWithParamName", "ObjA", "MfMemStrView"), "ObjA")
  3617. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  3618. throw ex
  3619. }
  3620. if (ObjB.__Class != "MfMemStrView")
  3621. {
  3622. ex := new MfArgumentException(MfEnvironment.Instance.GetResourceString("Argument_NonMfObjectWithParamName", "ObjB", "MfMemStrView"), "ObjB")
  3623. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  3624. throw ex
  3625. }
  3626. if (!(objA.m_Encoding = objB.m_Encoding))
  3627. {
  3628. ex := new MfFormatException(MfEnvironment.Instance.GetResourceString("Format_Encoding_MisMatch"))
  3629. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  3630. throw ex
  3631. }
  3632. BytesPerChar := objA.m_BytesPerChar
  3633. sType := objA.m_sType
  3634.  
  3635. PIA := objA.Pos
  3636. PIB := objB.Pos
  3637. if (indexA < 0 || indexA > PIA || len > PIA)
  3638. {
  3639. ex := new MfIndexOutOfRangeException(MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_ArrayListInsert"))
  3640. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  3641. throw ex
  3642. }
  3643. if (indexB < 0 || indexB > PIB || len > PIB)
  3644. {
  3645. ex := new MfIndexOutOfRangeException(MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_ArrayListInsert"))
  3646. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  3647. throw ex
  3648. }
  3649.  
  3650. objA.Seek(indexA * BytesPerChar)
  3651. objB.Seek(indexB * BytesPerChar)
  3652.  
  3653. HasLen := true
  3654. if (len = -1)
  3655. {
  3656. aEnd := PIA - BytesPerChar
  3657. bEnd := PIB - BytesPerChar
  3658. aLen := aEnd - objA.Pos ; aLen may be 1 or two bytes per char
  3659. bLen := bEnd - objB.Pos ; bLen may be 1 or two bytes per char
  3660. HasLen := false
  3661. len := aLen > bLen ? bLen : aLen
  3662. }
  3663.  
  3664. i := len
  3665. ;i -= BytesPerChar
  3666. num := -1
  3667. AddressA := objA[] + objA.Pos
  3668. AddressB := objB[] + objB.Pos
  3669. ptrA := AddressA ; first char address
  3670. ptrB := AddressB ; frist char address
  3671.  
  3672. ; reset object positions
  3673. objA.Pos := PIA
  3674. objB.Pos := PIB
  3675.  
  3676. While (i >= 5 * BytesPerChar)
  3677. {
  3678. numA := NumGet(ptrA + 0, 0, sType)
  3679. numB := NumGet(ptrB + 0, 0, sType)
  3680. if (numA != numB)
  3681. {
  3682. If (!ignoreCase)
  3683. {
  3684. num := 0
  3685. break
  3686. }
  3687. If (MfMemStrView._IsLatin1(numA) && MfMemStrView._IsLatin1(numB))
  3688. {
  3689. if (MfMemStrView._IsEqualLatin1IgnoreCase(numA, numB) = False)
  3690. {
  3691. num := 0
  3692. break
  3693. }
  3694. }
  3695. else
  3696. {
  3697. char1 := Chr(numA)
  3698. char2 := Chr(numB)
  3699. if (!(char1 = char2))
  3700. {
  3701. num := 0
  3702. break
  3703. }
  3704. }
  3705. }
  3706. numA := NumGet(ptrA + BytesPerChar, 0, sType)
  3707. numB := NumGet(ptrB + BytesPerChar, 0, sType)
  3708. if (numA != numB)
  3709. {
  3710. If (!ignoreCase)
  3711. {
  3712. num := BytesPerChar
  3713. break
  3714. }
  3715. If (MfMemStrView._IsLatin1(numA) && MfMemStrView._IsLatin1(numB))
  3716. {
  3717. if (MfMemStrView._IsEqualLatin1IgnoreCase(numA, numB) = False)
  3718. {
  3719. num := BytesPerChar
  3720. break
  3721. }
  3722. }
  3723. else
  3724. {
  3725. char1 := Chr(numA)
  3726. char2 := Chr(numB)
  3727. if (!(char1 = char2))
  3728. {
  3729. num := BytesPerChar
  3730. break
  3731. }
  3732. }
  3733. }
  3734. numA := NumGet(ptrA + (BytesPerChar * 2), 0, sType)
  3735. numB := NumGet(ptrB + (BytesPerChar * 2), 0, sType)
  3736. if (numA != numB)
  3737. {
  3738. If (!ignoreCase)
  3739. {
  3740. num := BytesPerChar * 2
  3741. break
  3742. }
  3743. If (MfMemStrView._IsLatin1(numA) && MfMemStrView._IsLatin1(numB))
  3744. {
  3745. if (MfMemStrView._IsEqualLatin1IgnoreCase(numA, numB) = False)
  3746. {
  3747. num := BytesPerChar * 2
  3748. break
  3749. }
  3750. }
  3751. else
  3752. {
  3753. char1 := Chr(numA)
  3754. char2 := Chr(numB)
  3755. if (!(char1 = char2))
  3756. {
  3757. num := BytesPerChar * 2
  3758. break
  3759. }
  3760. }
  3761. }
  3762. numA := NumGet(ptrA + (BytesPerChar * 3), 0, sType)
  3763. numB := NumGet(ptrB + (BytesPerChar * 3), 0, sType)
  3764. if (numA != numB)
  3765. {
  3766. If (!ignoreCase)
  3767. {
  3768. num := BytesPerChar * 3
  3769. break
  3770. }
  3771. If (MfMemStrView._IsLatin1(numA) && MfMemStrView._IsLatin1(numB))
  3772. {
  3773. if (MfMemStrView._IsEqualLatin1IgnoreCase(numA, numB) = False)
  3774. {
  3775. num := BytesPerChar * 3
  3776. break
  3777. }
  3778. }
  3779. else
  3780. {
  3781. char1 := Chr(numA)
  3782. char2 := Chr(numB)
  3783. if (!(char1 = char2))
  3784. {
  3785. num := BytesPerChar * 3
  3786. break
  3787. }
  3788. }
  3789. }
  3790. numA := NumGet(ptrA + (BytesPerChar * 4), 0, sType)
  3791. numB := NumGet(ptrB + (BytesPerChar * 4), 0, sType)
  3792. if (numA != numB)
  3793. {
  3794. If (!ignoreCase)
  3795. {
  3796. num := BytesPerChar * 4
  3797. break
  3798. }
  3799. If (MfMemStrView._IsLatin1(numA) && MfMemStrView._IsLatin1(numB))
  3800. {
  3801. if (MfMemStrView._IsEqualLatin1IgnoreCase(numA, numB) = False)
  3802. {
  3803. num := BytesPerChar * 4
  3804. break
  3805. }
  3806. }
  3807. else
  3808. {
  3809. char1 := Chr(numA)
  3810. char2 := Chr(numB)
  3811. if (!(char1 = char2))
  3812. {
  3813. num := BytesPerChar * 4
  3814. break
  3815. }
  3816. }
  3817. }
  3818. ptrA += BytesPerChar * 5
  3819. ptrB += BytesPerChar * 5
  3820. i -= BytesPerChar * 5
  3821. }
  3822. if (num != -1)
  3823. {
  3824. ptrA += num
  3825. ptrB += num
  3826. numA := NumGet(ptrA + 0, 0, sType)
  3827. numB := NumGet(ptrB + 0, 0, sType)
  3828. result := numA - numB
  3829. if (result != 0)
  3830. {
  3831. return result
  3832. }
  3833. numA := NumGet(ptrA + BytesPerChar, 0, sType)
  3834. numB := NumGet(ptrB + BytesPerChar, 0, sType)
  3835. return numA - numB
  3836. }
  3837. else
  3838. {
  3839. while (i > 0)
  3840. {
  3841. numA := NumGet(ptrA + 0, 0, sType)
  3842. numB := NumGet(ptrB + 0, 0, sType)
  3843. if (numA != numB)
  3844. {
  3845. If (!ignoreCase)
  3846. {
  3847. break
  3848. }
  3849. If (MfMemStrView._IsLatin1(numA) && MfMemStrView._IsLatin1(numB))
  3850. {
  3851. if (MfMemStrView._IsEqualLatin1IgnoreCase(numA, numB) = False)
  3852. {
  3853. break
  3854. }
  3855. }
  3856. else
  3857. {
  3858. char1 := Chr(numA)
  3859. char2 := Chr(numB)
  3860. if (!(char1 = char2))
  3861. {
  3862. break
  3863. }
  3864. }
  3865. }
  3866. ptrA += BytesPerChar
  3867. ptrB += BytesPerChar
  3868. i -= BytesPerChar
  3869. }
  3870. if (i <= 0)
  3871. {
  3872. if (!HasLen)
  3873. {
  3874. return aLen - bLen
  3875. }
  3876. return i
  3877. }
  3878. numA := NumGet(ptrA + 0, 0, sType)
  3879. numB := NumGet(ptrB + 0, 0, sType)
  3880. result := 0
  3881. if (NumA != numB)
  3882. {
  3883. If (!ignoreCase)
  3884. {
  3885. result := numA - numB
  3886. }
  3887. else If (MfMemStrView._IsLatin1(numA) && MfMemStrView._IsLatin1(numB))
  3888. {
  3889. if (MfMemStrView._IsEqualLatin1IgnoreCase(numA, numB) = False)
  3890. {
  3891. result := numA - numB
  3892. }
  3893. }
  3894. else
  3895. {
  3896. char1 := Chr(numA)
  3897. char2 := Chr(numB)
  3898. if (!(char1 = char2))
  3899. {
  3900. result := numA - numB
  3901. }
  3902. }
  3903. }
  3904. if (result != 0)
  3905. {
  3906. return result
  3907. }
  3908. numA := NumGet(ptrA + BytesPerChar, 0, sType)
  3909. numB := NumGet(ptrB + BytesPerChar, 0, sType)
  3910. result := 0
  3911. if (numA != numB)
  3912. {
  3913. If (!ignoreCase)
  3914. {
  3915. result := numA - numB
  3916. }
  3917. else If (MfMemStrView._IsLatin1(numA) && MfMemStrView._IsLatin1(numB))
  3918. {
  3919. if (MfMemStrView._IsEqualLatin1IgnoreCase(numA, numB) = False)
  3920. {
  3921. result := numA - numB
  3922. }
  3923. }
  3924. else
  3925. {
  3926. char1 := Chr(num1)
  3927. char2 := Chr(numB)
  3928. if (!(char1 = char2))
  3929. {
  3930. result := numA - numB
  3931. }
  3932. }
  3933. }
  3934. return result
  3935. }
  3936. }
  3937. ; End:CompareOrdinalSub ;}
  3938. ;{ Diff
  3939. /*
  3940. Method: Diff()
  3941. Gets the Difference between argument objA and argument objB argument with an included Max Distance.
  3942. objA
  3943. the frist MfMemStrView to compare.
  3944. objB
  3945. the second MfMemStrView to compare.
  3946. maxDistance
  3947. Integer tells the algorithm to stop if the strings are already too different.
  3948. Returns:
  3949. Returns returns the difference between the strings as a float between 0 and 1.
  3950. 0 means strings are identical. 1 means they have nothing in common.
  3951. */
  3952. Diff(objA, objB, maxOffset=5) {
  3953. if (ObjA.__Class != "MfMemStrView")
  3954. {
  3955. ex := new MfArgumentException(MfEnvironment.Instance.GetResourceString("Argument_NonMfObjectWithParamName", "ObjA", "MfMemStrView"), "ObjA")
  3956. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  3957. throw ex
  3958. }
  3959. if (ObjB.__Class != "MfMemStrView")
  3960. {
  3961. ex := new MfArgumentException(MfEnvironment.Instance.GetResourceString("Argument_NonMfObjectWithParamName", "ObjB", "MfMemStrView"), "ObjB")
  3962. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  3963. throw ex
  3964. }
  3965. if (!(objA.m_Encoding = objB.m_Encoding))
  3966. {
  3967. ex := new MfFormatException(MfEnvironment.Instance.GetResourceString("Format_Encoding_MisMatch"))
  3968. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  3969. throw ex
  3970. }
  3971. BytesPerChar := objA.m_BytesPerChar
  3972.  
  3973. if (objA.Pos <= 1 || objB.Pos <= 1)
  3974. {
  3975. return (objA.Pos = objB.Pos ? 0/1 : 1/1)
  3976. }
  3977. lenA := objA.Pos
  3978. lenA -= BytesPerChar
  3979. lenB := objB.Pos
  3980. lenB -= BytesPerChar
  3981. lcs := 0
  3982. ni := 1
  3983. mi := 1
  3984. n0 := (lenA // BytesPerChar)
  3985. m0 := (lenB // BytesPerChar)
  3986. if (objA.Equals(objB, false))
  3987. {
  3988. result := objA.Equals(objB, true)
  3989. retval := result = true? (0/1) : (0.2/n0)
  3990. return retval
  3991. }
  3992.  
  3993. sType := objA.m_sType
  3994. ptrA := objA[] ; first char address
  3995. ptrB := objB[] ; frist char address
  3996.  
  3997. i := 0
  3998.  
  3999. while ((ni <= n0) && (mi <= m0))
  4000. {
  4001. num1 := NumGet(ptrA + 0, ((ni - 1) * BytesPerChar), sType)
  4002. num2 := NumGet(ptrB + 0, ((mi - 1) * BytesPerChar), sType)
  4003. if (num1 = num2)
  4004. {
  4005. lcs += 1
  4006. ni += 1
  4007. mi += 1
  4008. continue
  4009. }
  4010. else If (MfMemStrView._IsLatin1(num1) && MfMemStrView._IsLatin1(num2))
  4011. {
  4012. if (MfMemStrView._IsEqualLatin1IgnoreCase(num1, num2))
  4013. {
  4014. lcs += 0.8
  4015. ni += 1
  4016. mi += 1
  4017. continue
  4018. }
  4019. }
  4020. else
  4021. {
  4022. char1 := Chr(num1)
  4023. char2 := Chr(num2)
  4024. if (char1 = char2)
  4025. {
  4026. lcs += 0.8
  4027. ni += 1
  4028. mi += 1
  4029. continue
  4030. }
  4031. }
  4032. Loop, % maxOffset
  4033. {
  4034. oi := ni + A_Index, pi := mi + A_Index
  4035. num1 := oi <= n0 ? NumGet(ptrA + 0, ((oi - 1) * BytesPerChar), sType) : 0
  4036. num2 := mi <= m0 ? NumGet(ptrB + 0, ((mi - 1) * BytesPerChar), sType) : 0
  4037. if ((num1 > 0 ) && (num1 = num2))
  4038. {
  4039. ;ni := oi, lcs += (num1 = num2 ? 1 : 0.8)
  4040. ni := oi, lcs += 1
  4041. break
  4042. }
  4043. else If (num1 > 0 && MfMemStrView._IsLatin1(num1) && MfMemStrView._IsLatin1(num2))
  4044. {
  4045. if (MfMemStrView._IsEqualLatin1IgnoreCase(num1, num2))
  4046. {
  4047. ni := oi, lcs += 0.8
  4048. break
  4049. }
  4050. }
  4051. else if (num1 > 0)
  4052. {
  4053. char1 := Chr(num1)
  4054. char2 := Chr(num2)
  4055. if ((char1 = char2))
  4056. {
  4057. ;ni := oi, lcs += (char1 = char1 ? 1 : 0.8)
  4058. ni := oi, lcs += 0.8
  4059. break
  4060. }
  4061. }
  4062.  
  4063. num1 := ni <= n0 ? NumGet(ptrA + 0, ((ni - 1) * BytesPerChar), sType) : 0
  4064. num2 := pi <= m0 ? NumGet(ptrB + 0, ((pi - 1) * BytesPerChar), sType) : 0
  4065. if ((num2 > 0) && (num1 = num2))
  4066. {
  4067. mi := pi, lcs += 1
  4068. break
  4069. }
  4070. else If (num2 > 0 && MfMemStrView._IsLatin1(num1) && MfMemStrView._IsLatin1(num2))
  4071. {
  4072. if (MfMemStrView._IsEqualLatin1IgnoreCase(num1, num2))
  4073. {
  4074. mi := pi, lcs += 0.8
  4075. break
  4076. }
  4077. }
  4078. else if (num2 > 0)
  4079. {
  4080. char1 := Chr(num1)
  4081. char2 := Chr(num2)
  4082. if (char1 = char2)
  4083. {
  4084. mi := pi, lcs += 0.8
  4085. break
  4086. }
  4087. }
  4088. }
  4089. ni += 1
  4090. mi += 1
  4091. }
  4092.  
  4093. return ((n0 + m0)/2 - lcs) / (n0 > m0 ? n0 : m0)
  4094. }
  4095. ; End:Diff ;}
  4096. ;{ EndsWithFromPos
  4097. /*
  4098. Method: EndsWithFromPos()
  4099.  
  4100. EndsWithFromPos()
  4101. Checks to see if obj ends with the same char as this instance
  4102. Parameters:
  4103. obj
  4104. the obj instance to compare to this instance
  4105. IgnoreCase
  4106. If True case is ignored; Otherwise case is compared
  4107. Returns:
  4108. Returns true if this instance ends with the same chars as obj
  4109. Remarks:
  4110. Obj.Pos must not be bigger then this instance or false will be returned
  4111. */
  4112. EndsWithFromPos(Obj, IgnoreCase=true) {
  4113. if (Obj.Pos = 0 || this.Pos = 0)
  4114. {
  4115. return false
  4116. }
  4117. if (Obj.Pos > this.Pos)
  4118. {
  4119. return false
  4120. }
  4121. PI := this.Pos
  4122. this.Pos := this.Pos - Obj.Pos
  4123.  
  4124. BytesPerChar := this.m_BytesPerChar
  4125. ; move address to this plus this position
  4126. Address1 := this[] + this.Pos
  4127. len := (Obj.Pos - BytesPerChar) // BytesPerChar
  4128. Address2 := Obj[]
  4129. retval := MfMemStrView.StringsAreEqual(Address1, len, Address2, len, this.m_Encoding, IgnoreCase)
  4130. this.Pos := PI ; reset this pos to originl location
  4131. return retval
  4132. }
  4133. ; End:EndsWithFromPos ;}
  4134. ;{ EqualsSubString
  4135. /*
  4136. Method: EqualsSubString()
  4137.  
  4138. EqualsSubString()
  4139. Compares two MfMemStrView objects to see if their subPositions are equal
  4140. Parameters:
  4141. ObjA
  4142. The first MfMemStrView to compare
  4143. ObjAStartIndex
  4144. The zero base start index of ObjA to compare, this is char index and not base on bytes ber char
  4145. ObjA
  4146. The second MfMemStrView to compare
  4147. ObjAStartIndex
  4148. The zero base start index of ObjB to compare, this is char index and not base on bytes ber char
  4149. Len
  4150. The Length to Compare
  4151. IgnoreCase
  4152. Boolean value indicating if case to to be ignored
  4153. Returns:
  4154. Boolean var of True if Sub-Positions are equal; Otherwise false
  4155. Throws:
  4156. Throws MfArgumentException
  4157. Throws MfFormatException if encodings for both objects do not match
  4158. Remarks:
  4159. static method
  4160. */
  4161. EqualsSubString(ByRef ObjA, ObjAStartIndex, ByRef ObjB, ObjbStartIndex, Len, IgnoreCase=true) {
  4162. if (ObjA.__Class != "MfMemStrView")
  4163. {
  4164. ex := new MfArgumentException(MfEnvironment.Instance.GetResourceString("Argument_NonMfObjectWithParamName", "ObjA", "MfMemStrView"), "ObjA")
  4165. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  4166. throw ex
  4167. }
  4168. if (ObjB.__Class != "MfMemStrView")
  4169. {
  4170. ex := new MfArgumentException(MfEnvironment.Instance.GetResourceString("Argument_NonMfObjectWithParamName", "ObjB", "MfMemStrView"), "ObjB")
  4171. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  4172. throw ex
  4173. }
  4174. if (!(objA.m_Encoding = objB.m_Encoding))
  4175. {
  4176. ex := new MfFormatException(MfEnvironment.Instance.GetResourceString("Format_Encoding_MisMatch"))
  4177. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  4178. throw ex
  4179. }
  4180. ObjAStartIndex := MfInteger.GetValue(ObjAStartIndex)
  4181. Len := MfInteger.GetValue(Len)
  4182.  
  4183. ObjbStartIndex := MfInteger.GetValue(ObjbStartIndex)
  4184.  
  4185.  
  4186. IgnoreCase := MfBool.GetValue(IgnoreCase, true)
  4187. If (objA.Size <= (ObjAStartPos + Len))
  4188. {
  4189. return false
  4190. }
  4191. If (ObjB.Size <= (ObjAStartIndex + Len))
  4192. {
  4193. return false
  4194. }
  4195. PIA := objA.Pos
  4196. PIB := objB.Pos
  4197. BytesPerChar := objA.m_BytesPerChar
  4198. try
  4199. {
  4200. objA.Seek(ObjAStartIndex * BytesPerChar)
  4201. objB.Seek(ObjbStartIndex * BytesPerChar)
  4202. AddressA := objA[] + objA.Pos
  4203. AddressB := objB[] + objB.Pos
  4204. retval := MfMemStrView.StringsAreEqual(AddressA, Len, AddressB, Len, objA.m_Encoding, IgnoreCase)
  4205. return retval
  4206. }
  4207. catch e
  4208. {
  4209. ex := new MfException(MfEnvironment.Instance.GetResourceString("Exception_Error", A_ThisFunc), e)
  4210. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  4211. throw ex
  4212. }
  4213. Finally
  4214. {
  4215. objA.Pos := PIA
  4216. objB.Pos := PIB
  4217. }
  4218. }
  4219. ; End:EqualsSubString ;}
  4220. ;{ Equals
  4221. /*
  4222. Method: Equals()
  4223.  
  4224. Equals()
  4225. Check to see if current instance is equal string as Obj
  4226. Parameters:
  4227. Obj
  4228. Instance of MfMemStrView to compare to current instance
  4229. IgnoreCase
  4230. Boolean value indicating if case should be ignored when comparing
  4231. Returns:
  4232. Boolean var true if equal; Otherwise false
  4233. Throws:
  4234. Throws MfArgumentException
  4235. Remarks:
  4236. See EqualsString for comparsion of String var
  4237. */
  4238. Equals(Obj, IgnoreCase=true) {
  4239. if (Obj.__Class != "MfMemStrView")
  4240. {
  4241. ex := new MfArgumentException(MfEnvironment.Instance.GetResourceString("Argument_NonMfObjectWithParamName", "Obj", "MfMemStrView"), "Obj")
  4242. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  4243. throw ex
  4244. }
  4245. if (Obj.Pos = 0 && this.Pos = 0)
  4246. {
  4247. return true
  4248. }
  4249. if (Obj.Pos <> this.Pos)
  4250. {
  4251. return false
  4252. }
  4253.  
  4254. BytesPerChar := this.m_BytesPerChar
  4255. Address1 := this[]
  4256. len1 := (this.Pos - BytesPerChar) // BytesPerChar
  4257. Address2 := Obj[]
  4258. len2 := (Obj.Pos - BytesPerChar) // BytesPerChar
  4259. retval := MfMemStrView.StringsAreEqual(Address1, len1, Address2, len2, this.m_Encoding, IgnoreCase)
  4260. return retval
  4261. }
  4262. ; End:Equals ;}
  4263. ;{ EqualsString
  4264. /*
  4265. Method: EqualsString()
  4266.  
  4267. EqualsString()
  4268. Check to see if current instance is equal with str
  4269. Parameters:
  4270. str
  4271. Var strgin to compare to current instance
  4272. IgnoreCase
  4273. Boolean value indicating if case should be ignored when comparing
  4274. Returns:
  4275. Boolean var true if equal; Otherwise false
  4276. Remarks:
  4277. See Equals for comparsion of MfMemStrView obj
  4278. */
  4279. EqualsString(str, IgnoreCase=true) {
  4280. len := StrLen(str)
  4281. objMemBlk := new MfMemStrView((len + 1) * this.m_BytesPerChar, this.m_FillBytes, this.m_Encoding)
  4282. methodName := "Write" . this.m_EncodingName
  4283. chars := objMemBlk.__Call(methodName, str)
  4284. if (objMemBlk.Pos <> this.Pos)
  4285. {
  4286. return false
  4287. }
  4288. retval := this.Equals(objMemBlk, IgnoreCase)
  4289. return retval
  4290. }
  4291. ; End:EqualsString ;}
  4292. ;{ Expand
  4293. /*
  4294. Method: Expand()
  4295.  
  4296. Expand()
  4297. Expands the current buffer Adding new bytes
  4298. Parameters:
  4299. AddBytes
  4300. The number of bytes to add the buffer
  4301. Remarks:
  4302. this[] will be a new addresss after expansion
  4303. Caller is responsible for handling Bytes per char as this
  4304. method will add bytes without factoring encoding or BytesPerChar
  4305.  
  4306. According to https://autohotkey.com/docs/objects/Object.htm#SetCapacity
  4307. Adding bytes all data is perserved so no need to copy memory
  4308. */
  4309. Expand(AddBytes) {
  4310. if (AddBytes = "" || AddBytes <= 0)
  4311. {
  4312. return this.Size
  4313. }
  4314. FB := this.m_FillBytes
  4315. R := AddBytes + this.Size
  4316. if (FB < 0 || FB > 255)
  4317. {
  4318. FB := 0
  4319. }
  4320.  
  4321. if (this.m_isAddr = false)
  4322. {
  4323. oldSize := this.Size
  4324. ; add bytes to current _Buffer
  4325. this.Size := ObjSetCapacity(this, "_Buffer", R)
  4326. ; test show address gets changed
  4327. this.__Ptr := ObjGetAddress(this, "_Buffer")
  4328. ; fill the bytes for the expanded memory only. Do no overwrite existing data
  4329. DllCall("RtlFillMemory", "PTR", this[] + oldSize + 1, "PTR", AddBytes - 1, "UCHAR", FB)
  4330. return this.Size
  4331. }
  4332. ; if we are currently using an address then wil copy address contents
  4333. ; into tmp var and copy back to expanded _buffer
  4334.  
  4335.  
  4336. tmp := 0
  4337. size := this.Size
  4338. sType := "UChar"
  4339. VarSetCapacity(tmp, size, FB)
  4340. DllCall("RtlMoveMemory", "PTR", &tmp, "PTR", this[], sType, Size)
  4341.  
  4342. this.m_isAddr := false
  4343.  
  4344. this.Size := ObjSetCapacity(this, "_Buffer", R)
  4345. this.__Ptr := ObjGetAddress(this, "_Buffer")
  4346. ; only call fill byte if not greater then 0 and less then or equal 255
  4347. ; default fill should be zero so no need to call unless FB is greater then 0
  4348. DllCall("RtlFillMemory", "PTR", this[], "PTR", size, "UCHAR", FB)
  4349. ;this.Size := this.GetCapacity("_Buffer")
  4350.  
  4351. DllCall( "RtlMoveMemory", "PTR", this[], "PTR", &tmp, sType, Size )
  4352. VarSetCapacity(tmp, 0)
  4353. return this.Size
  4354. }
  4355. ; End:Expand ;}
  4356. ;{ FromArray
  4357. /*
  4358. Method: FromArray()
  4359.  
  4360. FromArray()
  4361. Creates new isntance of MfMemBlkView from AutoHotkey one based byte array
  4362. Parameters:
  4363. objArray
  4364. The array containing the bytes
  4365. encoding
  4366. The encoding of the byte array.
  4367. Default value is UTF-16
  4368. startIndex
  4369. The zero based index to start read bytes from with the array.
  4370. Default value is zero
  4371. length
  4372. The lengt of byte to read from startIndex forward in the array.
  4373. The default value is -1
  4374. Values less then 0 will read all array bytes from startIndex forward
  4375. Returns:
  4376. Returns MfMemStrView instance
  4377. Throws:
  4378. Throws MfArgumentNullException, MfArgumentOutOfRangeException
  4379. */
  4380. FromArray(byref objArray, encoding="UTF-16", startIndex=0, length=-1) {
  4381. if (MfNull.IsNull(objArray))
  4382. {
  4383. ex := new MfArgumentNullException("ojbArray")
  4384. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  4385. throw ex
  4386. }
  4387. if (startIndex < 0)
  4388. {
  4389. ex := new MfArgumentOutOfRangeException("startIndex", MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_IndexString"))
  4390. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  4391. throw ex
  4392. }
  4393. if (length = 0)
  4394. {
  4395. ex := new MfArgumentException(MfEnvironment.Instance.GetResourceString("Arg_ArrayZeroError", "objArray"))
  4396. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  4397. throw ex
  4398. }
  4399. aLength := objArray.Length()
  4400. if (!aLength)
  4401. {
  4402. ex := new MfException(MfEnvironment.Instance.GetResourceString("Arg_ArrayTooSmall"))
  4403. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  4404. throw ex
  4405. }
  4406. if (length < 0)
  4407. {
  4408. length := (aLength - startIndex) + 1
  4409. }
  4410. if ((startIndex + length) - 1 > aLength)
  4411. {
  4412. ex := new MfArgumentException(MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_IndexLength"))
  4413. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  4414. throw ex
  4415. }
  4416. BytesPerChar := MfMemStrView.GetBytesPerChar(encoding)
  4417. EvenOffset := 0
  4418. if (BytesPerChar = 2)
  4419. {
  4420. ; if Even number add on more for even number of bytes
  4421. ; even number is because we are zero based
  4422. if (!(length & 1))
  4423. {
  4424. EvenOffset++
  4425. }
  4426. }
  4427. mv := new MfMemStrView(length - 1 + BytesPerChar + EvenOffset, 0, encoding)
  4428. addr := mv[]
  4429. i := 1
  4430. sType := "UChar"
  4431. while (i <= length)
  4432. {
  4433. NumPut(objArray[i], addr + 0, i -1 , sType)
  4434. mv.Pos++
  4435. i++
  4436. }
  4437. if (i > 1)
  4438. {
  4439. mv.Pos--
  4440. }
  4441. if (EvenOffset)
  4442. {
  4443. NumPut(0, addr + 0, i - 1 , sType)
  4444. mv.Pos++
  4445. i++
  4446. }
  4447. ; add last byte for null string end
  4448. NumPut(0, addr + 0, i -1 , sType)
  4449. mv.Pos++
  4450. if (BytesPerChar = 2)
  4451. {
  4452. NumPut(0, addr + 0, i , sType)
  4453. mv.Pos++
  4454.  
  4455. }
  4456. return mv
  4457. }
  4458. ; End:FromArray ;}
  4459. ;{ FromByteList
  4460. /*
  4461. Method: FromByteList()
  4462.  
  4463. FromByteList()
  4464. Converts MfByteList into MfMemStrView instance
  4465. Parameters:
  4466. bytes
  4467. instance of MfByteList containing byte values to convert
  4468. encoding
  4469. The encoding type of the bytes such as UTF-16 or UTF-8
  4470. Default value is UTF-16 which means each char is expected to be two bytes
  4471. startIndex
  4472. The starting index in the MfByteList to start the conversion
  4473. Default value is 0
  4474. length
  4475. the length in bytes to convert.
  4476. Default value is -1
  4477. When length is less then 0 then all bytes past startIndex are included
  4478. littleEndian
  4479. Default value is true.
  4480. If true then byte order is considered to be reversed and the bytes are written into
  4481. memory from last byte to first after considering startIndex and length; Oterwise bytes
  4482. are written from start to end.
  4483. Returns:
  4484. Returns instance of MfMemStrView
  4485. Throws:
  4486. Throws MfArgumentException, MfArgumentOutOfRangeException
  4487. Remarks:
  4488. Both startIndex and length operate the same no mater the state of littleEndian.
  4489. Static Method
  4490. */
  4491. FromByteList(bytes, encoding="UTF-16", startIndex=0, length=-1, littleEndian=true) {
  4492. if(MfObject.IsObjInstance(bytes, MfByteList) = false)
  4493. {
  4494. ex := new MfArgumentException(MfEnvironment.Instance.GetResourceString("Argument_Incorrect_List", "bytes"))
  4495. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  4496. throw ex
  4497. }
  4498. if(bytes.Count = 0)
  4499. {
  4500. ex := new MfArgumentException(MfEnvironment.Instance.GetResourceString("Arg_ArrayZeroError", "bytes"))
  4501. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  4502. throw ex
  4503. }
  4504. if(!littleEndian)
  4505. {
  4506. return MfMemStrView.FromArray(bytes.m_InnerList, encoding, startIndex, length)
  4507. }
  4508. if (startIndex < 0)
  4509. {
  4510. ex := new MfArgumentOutOfRangeException("startIndex", MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_IndexString"))
  4511. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  4512. throw ex
  4513. }
  4514. if (length = 0)
  4515. {
  4516. ex := new MfArgumentOutOfRangeException("length", MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_IndexString"))
  4517. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  4518. throw ex
  4519. }
  4520. aLength := bytes.Count
  4521.  
  4522. if (length < 0)
  4523. {
  4524. length := (aLength - startIndex) + 1
  4525. }
  4526. if ((startIndex + length) -1 > aLength)
  4527. {
  4528. ex := new MfArgumentException(MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_IndexLength"))
  4529. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  4530. throw ex
  4531. }
  4532. BytesPerChar := MfMemStrView.GetBytesPerChar(encoding)
  4533. EvenOffset := 0
  4534. if (BytesPerChar = 2)
  4535. {
  4536. ; if Even number add on more for even number of bytes
  4537. ; even number is because we are zero based
  4538. if (!(length & 1))
  4539. {
  4540. EvenOffset++
  4541. }
  4542. }
  4543. mv := new MfMemStrView(length - 1 + BytesPerChar + EvenOffset, 0, encoding)
  4544. addr := mv[]
  4545. objArray := bytes.m_InnerList
  4546. i := 1
  4547. j := bytes.Count
  4548. sType := "UChar"
  4549. while (i <= length)
  4550. {
  4551. NumPut(objArray[j], addr + 0, i -1 , sType)
  4552. mv.Pos++
  4553. i++
  4554. j--
  4555. }
  4556. if (i > 1 )
  4557. {
  4558. mv.Pos--
  4559. }
  4560. if (EvenOffset)
  4561. {
  4562. NumPut(0, addr + 0, i - 1 , sType)
  4563. mv.Pos++
  4564. i++
  4565. }
  4566. ; add last byte for null string end
  4567. NumPut(0, addr + 0, i - 1 , sType)
  4568. mv.Pos++
  4569. if (BytesPerChar = 2)
  4570. {
  4571. NumPut(0, addr + 0, i , sType)
  4572. mv.Pos++
  4573. }
  4574.  
  4575. return mv
  4576. }
  4577. ; End:FromByteList ;}
  4578. ;{ FromCharList
  4579. /*
  4580. Method: FromCharList()
  4581.  
  4582. FromCharList()
  4583. Converts MfCharList into MfMemStrView instance
  4584. Parameters:
  4585. chars
  4586. instance of MfCharList containing byte values to convert
  4587. startIndex
  4588. The starting index in the MfCharList to start the conversion
  4589. Default value is 0
  4590. length
  4591. the length in bytes to convert.
  4592. Default value is -1
  4593. When length is less then 0 then all chars past startIndex are included
  4594. Returns:
  4595. Returns instance of MfMemStrView
  4596. Throws:
  4597. Throws MfArgumentException, MfArgumentOutOfRangeException
  4598. Remarks:
  4599. Static Method
  4600. */
  4601. FromCharList(chars, startIndex=0, length=-1) {
  4602. if(MfObject.IsObjInstance(chars, MfCharList) = false)
  4603. {
  4604. ex := new MfArgumentException(MfEnvironment.Instance.GetResourceString("Argument_Incorrect_List", "chars"))
  4605. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  4606. throw ex
  4607. }
  4608. if(chars.m_Count = 0)
  4609. {
  4610. ex := new MfArgumentException(MfEnvironment.Instance.GetResourceString("Arg_ArrayZeroError", "chars"))
  4611. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  4612. throw ex
  4613. }
  4614. if (startIndex < 0)
  4615. {
  4616. ex := new MfArgumentOutOfRangeException("startIndex", MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_IndexString"))
  4617. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  4618. throw ex
  4619. }
  4620. if (length = 0)
  4621. {
  4622. ex := new MfArgumentOutOfRangeException("length", MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_IndexString"))
  4623. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  4624. throw ex
  4625. }
  4626. aLength := chars.m_Count
  4627.  
  4628. if (length < 0)
  4629. {
  4630. length := (aLength - startIndex) + 1
  4631. }
  4632. if ((startIndex + length) - 1 > aLength)
  4633. {
  4634. ex := new MfArgumentException(MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_IndexLength"))
  4635. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  4636. throw ex
  4637. }
  4638. BytesPerChar := chars.m_BytesPerChar
  4639. encoding := chars.m_Encoding
  4640. sType := chars.m_sType
  4641.  
  4642. mv := new MfMemStrView((length + BytesPerChar) * BytesPerChar, 0, encoding)
  4643. addr := mv[]
  4644. objArray := chars.m_InnerList
  4645. i := 0
  4646. j := startIndex + 1
  4647. LastCharPos := 0
  4648.  
  4649. while (i < length)
  4650. {
  4651. num := objArray[j]
  4652. idx := i * BytesPerChar
  4653. NumPut(num, addr + 0, idx , sType)
  4654. if (num > 0)
  4655. {
  4656. LastCharPos := i + 1
  4657. }
  4658. i++
  4659. j++
  4660. }
  4661. LastCharPos := LastCharPos * BytesPerChar
  4662. if (LastCharPos < mv.Size)
  4663. {
  4664. mv.Pos := LastCharPos + BytesPerChar
  4665. }
  4666. else
  4667. {
  4668. mv.Pos := mv.Size
  4669. }
  4670. return mv
  4671. }
  4672. ; End:FromCharList ;}
  4673. ;{ FromBase64
  4674. /*
  4675. Method: FromBase64()
  4676.  
  4677. FromBase64()
  4678. Reads buffer and returns UTF-8 or UTF-16 buffer from base64
  4679. Parameters:
  4680. InData
  4681. The buffer to convert from Base64, In Data is expected to be UTF-8
  4682. offset
  4683. The offset in bytes to start the conversion
  4684. length
  4685. The number of bytes to convert
  4686. Returns:
  4687. Returns a MfMemStrView UTF-8 encoded buffer containing basd64 value
  4688. Throws:
  4689. Throws MfArgumentException
  4690. Remarks:
  4691. Static method
  4692. */
  4693. FromBase64(ByRef InData, offset, length) {
  4694. if (InData.__Class != "MfMemStrView")
  4695. {
  4696. ex := new MfArgumentException(MfEnvironment.Instance.GetResourceString("Argument_NonMfObjectWithParamName", "InData", "MfMemStrView"), "InData")
  4697. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  4698. throw ex
  4699. }
  4700.  
  4701. BytesPerChar := InData.m_BytesPerChar
  4702.  
  4703. inputPtr := InData[] + offset
  4704. inputLength := length
  4705. while (inputLength > 0)
  4706. {
  4707. num := NumGet(inputPtr + 0, inputLength - 1, "UChar")
  4708. if (num != 32 && num != 10 && num != 13 && num != 9)
  4709. {
  4710. break
  4711. }
  4712. inputLength--
  4713. }
  4714. ResultSize := MfMemStrView._FromBase64_ComputeResultLength(inputPtr, inputLength)
  4715. if (ResultSize < 1)
  4716. {
  4717. return new MfMemStrView(1,,"UTF-8")
  4718. }
  4719.  
  4720. retval := new MfMemStrView(ResultSize + BytesPerChar,, "UTF-8")
  4721. ptr := retval[]
  4722.  
  4723. MfMemStrView._FromBase64_Decode(inputPtr, inputLength, ptr, ResultSize)
  4724. retval.Pos := ResultSize + BytesPerChar
  4725. return retval
  4726. }
  4727. ; End:FromBase64 ;}
  4728. ;{ _FromBase64_ComputeResultLength
  4729. ; computes the length of decoded base64
  4730. _FromBase64_ComputeResultLength(inputPtr, inputLength) {
  4731. sType := "UChar"
  4732. ptr := inputPtr + inputLength
  4733. num := inputLength
  4734. num2 := 0
  4735. while (inputPtr < ptr)
  4736. {
  4737. num3 := NumGet(inputPtr + 0, 0, sType)
  4738. inputPtr++
  4739. if (num3 <= 32)
  4740. {
  4741. num--
  4742. }
  4743. else if (num3 = 61)
  4744. {
  4745. num--
  4746. num2++
  4747. }
  4748. }
  4749. if (num2 != 0)
  4750. {
  4751. if (num2 = 1)
  4752. {
  4753. num2 := 2
  4754. }
  4755. else
  4756. {
  4757. if (num2 != 2)
  4758. {
  4759. ex := new MfFormatException(MfEnvironment.Instance.GetResourceString("Format_BadBase64Char"))
  4760. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  4761. throw ex
  4762. }
  4763. num2 := 1
  4764. }
  4765. }
  4766. return num // 4 * 3 + num2
  4767. }
  4768. ; End:_FromBase64_ComputeResultLength ;}
  4769. ;{ _FromBase64_Decode
  4770. /*
  4771. Method: _FromBase64_Decode()
  4772.  
  4773. _FromBase64_Decode()
  4774. _FromBase64_Decode description
  4775. Parameters:
  4776. startInputPtr
  4777. The memory address of the base64 input
  4778. inputLength
  4779. The length in bytes of the base64 input
  4780. startDestPtr
  4781. The memory address of the buffer to hold the decoded base64 bytes
  4782. destLength
  4783. The length of the decoded base64 input
  4784. Returns:
  4785. Returns integer
  4786. Throws:
  4787. Throws MfFormatException if non-base64 char is found while decoding or bad char length
  4788. Remarks:
  4789. If _FromBase64_Decode
  4790. Static method
  4791. */
  4792. _FromBase64_Decode(startInputPtr, inputLength, startDestPtr, destLength) {
  4793. sType := "UChar"
  4794. sInType := "UChar"
  4795. ptr := startInputPtr
  4796. ptr2 := startDestPtr
  4797. ptr3 := ptr + inputLength
  4798. ptr4 := ptr2 + destLength
  4799. num := 255
  4800. ;strDebug := ""
  4801. while (ptr < ptr3)
  4802. {
  4803. num2 := NumGet(ptr + 0, 0, sInType)
  4804. ;OutputDebug % "_FromBase64_Decode: num2 :" . num2
  4805.  
  4806. ptr++
  4807. if (num2 >= 65 && num2 - 65 <= 25)
  4808. {
  4809. num2 -= 65
  4810. }
  4811. else if (num2 >= 97 && num2 - 97 <= 25)
  4812. {
  4813. num2 -= 71
  4814. }
  4815. else
  4816. {
  4817. ;OutputDebug % "_FromBase64_Decode: Else: num2 :" . num2
  4818. if ((num2 >= 48 && num2 - 48 > 9) || (num2 - 48 < 0))
  4819. {
  4820. if (num2 <= 32)
  4821. {
  4822. if (num2 = 9 || num2 = 10 || num2 = 13 || num2 = 32)
  4823. {
  4824. Continue
  4825. }
  4826. break
  4827. }
  4828. else
  4829. {
  4830. if (num2 = 43)
  4831. {
  4832. num2 := 62
  4833. if (MfMemStrView._FromBase64_DecodeHelper(num, num2, ptr2, ptr4))
  4834. {
  4835. ;OutputDebug % strDebug
  4836. return -1
  4837. }
  4838. continue
  4839. }
  4840. else if (num2 = 47)
  4841. {
  4842. num2 := 63
  4843. if (MfMemStrView._FromBase64_DecodeHelper(num, num2, ptr2, ptr4))
  4844. {
  4845. ;OutputDebug % strDebug
  4846. return -1
  4847. }
  4848. continue
  4849. }
  4850. else if (num2 = 61)
  4851. {
  4852. if (ptr = ptr3)
  4853. {
  4854. num <<= 6
  4855. if ((num & 2147483648) = 0)
  4856. {
  4857. ex := new MfFormatException(MfEnvironment.Instance.GetResourceString("Format_BadBase64CharArrayLength"))
  4858. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  4859. throw ex
  4860. }
  4861. if ((ptr4 - ptr2) < 2)
  4862. {
  4863. return -1
  4864. }
  4865. NumPut(num >> 16, ptr2 + 0, 0, sType)
  4866. ptr2++
  4867. NumPut(num >> 8, ptr2 + 0, 0, sType)
  4868. ptr2++
  4869. num := 255
  4870. break
  4871. }
  4872. else
  4873. {
  4874. while (ptr < ptr3 - 1)
  4875. {
  4876. num3 := NumGet(ptr + 0, 0, sInType)
  4877. if (num3 != 32 && num3 != 10 && num3 != 13 && num3 != 9)
  4878. {
  4879. break
  4880. }
  4881. ptr++
  4882. }
  4883. ; 61 is char '='
  4884. if (ptr != ptr3 - 1 || NumGet(ptr + 0, 0, sInType) != 61)
  4885. {
  4886. ex := new MfFormatException(MfEnvironment.Instance.GetResourceString("Format_BadBase64Char"))
  4887. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  4888. throw ex
  4889. }
  4890. num <<= 12
  4891. if ((num & 2147483648) = 0)
  4892. {
  4893. ex := new MfFormatException(MfEnvironment.Instance.GetResourceString("Format_BadBase64CharArrayLength"))
  4894. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  4895. throw ex
  4896. }
  4897. if ((ptr4 - ptr2) < 1)
  4898. {
  4899. return -1
  4900. }
  4901. NumPut(num >> 16, ptr2 + 0, 0, sType)
  4902. ptr2++
  4903. num := 255
  4904. break
  4905. }
  4906. }
  4907. }
  4908. ex := new MfFormatException(MfEnvironment.Instance.GetResourceString("Format_BadBase64Char"))
  4909. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  4910. throw ex
  4911. }
  4912. num2 -= 4294967292
  4913. }
  4914. if (MfMemStrView._FromBase64_DecodeHelper(num, num2, ptr2, ptr4))
  4915. {
  4916. ;OutputDebug % strDebug
  4917. return -1
  4918. }
  4919. }
  4920. ;OutputDebug % strDebug
  4921. return ptr2 - startDestPtr
  4922. }
  4923. ; End:_FromBase64_Decode ;}
  4924. ;{ _FromBase64_DecodeHelper
  4925. ; helper method for _FromBase64_Decode
  4926. _FromBase64_DecodeHelper(ByRef num, ByRef num2, ByRef ptr2, ptr4) {
  4927. sType :="UChar"
  4928. num := (num << 6 | num2)
  4929. if ((num & 2147483648) != 0)
  4930. {
  4931. if ((ptr4 - ptr2) < 3)
  4932. {
  4933. return true
  4934. }
  4935.  
  4936. NumPut(num >> 16, ptr2 + 0, 0, sType)
  4937. NumPut(num >> 8, ptr2 + 0, 1, sType)
  4938. NumPut(num, ptr2 + 0, 2, sType)
  4939. ptr2 += 3
  4940. num = 255
  4941. }
  4942. return false
  4943. }
  4944. ; End:_FromBase64_DecodeHelper ;}
  4945. ;{ GetBytesPerChar
  4946. GetBytesPerChar(Encoding) {
  4947. if (Encoding = "UTF-32")
  4948. {
  4949. return 4
  4950. }
  4951. else if (Encoding = "UTF-16" || Encoding = "CP1200")
  4952. {
  4953. return 2
  4954. }
  4955. else
  4956. {
  4957. return 1
  4958. }
  4959. }
  4960. ; End:GetBytesPerChar ;}
  4961.  
  4962. ;{ GetCharCount
  4963. /*
  4964. Method: GetCharCount()
  4965.  
  4966. GetCharCount()
  4967. Gets the number of chars currently in this buffer instance
  4968. Returns:
  4969. Returns the Count actual count of chars
  4970. Remarks:
  4971. If this.Pos <= Bytes Per Char then 0 is returned
  4972. The numberof bytes in the buffer are ignore and
  4973. return result is based on number of chars an not bytes
  4974. */
  4975. GetCharCount() {
  4976. if (this.Pos <= this.m_BytesPerChar)
  4977. {
  4978. return 0
  4979. }
  4980. return (this.Pos - this.m_BytesPerChar) // this.m_BytesPerChar
  4981. }
  4982. ; End:GetCharCount ;}
  4983. ;{ GetStringIgnoreNull
  4984. /*
  4985. Method: GetStringIgnoreNull()
  4986.  
  4987. GetStringIgnoreNull()
  4988. Gets an instance of MfMemStrView from current instance that has excluded all null values
  4989. Returns:
  4990. Returns MfMemStrView instance without any nulls
  4991. */
  4992. GetStringIgnoreNull() {
  4993. mv := new MfMemStrView(this.Size, this.m_FillBytes, this.m_Encoding)
  4994. BytesPerChar := mv.m_BytesPerChar
  4995. sType := mv.m_sType
  4996. mvAddr := mv[]
  4997. iCount := 0
  4998. for i, n in this
  4999. {
  5000. if (!MfMemStrView.IsIgnoreCharLatin1(n))
  5001. {
  5002. NumPut(n, mvAddr + 0, iCount, sType)
  5003. iCount += BytesPerChar
  5004. }
  5005. }
  5006. mv.Pos := iCount
  5007. if (mv.Pos < mv.Size)
  5008. {
  5009. mv.Pos += BytesPerChar
  5010. }
  5011. return mv
  5012. }
  5013. ; End:GetStringIgnoreNull ;}
  5014. ;{ IsIgnoreCharLatin1
  5015. /*
  5016. Method: IsIgnoreCharLatin1()
  5017.  
  5018. IsIgnoreCharLatin1()
  5019. Get if Char in Latin1 range can be displayed as text
  5020. Parameters:
  5021. cc
  5022. The char code to check
  5023. Returns:
  5024. Returns true if the char is no printable; Otherwise false
  5025. Remarks:
  5026. If cc is outside of range of Latin1 ( Greater then 255 ) then false will be returned
  5027. */
  5028. IsIgnoreCharLatin1(cc) {
  5029. if (cc > 255)
  5030. {
  5031. return false
  5032. }
  5033. if (cc < 9)
  5034. {
  5035. return true
  5036. }
  5037. If (cc > 13 && cc < 32)
  5038. {
  5039. return true
  5040. }
  5041. if (cc > 126 && cc < 160)
  5042. {
  5043. return true
  5044. }
  5045. return false
  5046. }
  5047. ; End:IsIgnoreCharLatin1 ;}
  5048. ;{ InBuffer
  5049. /*
  5050. Method: InBuffer()
  5051.  
  5052. InBuffer()
  5053. Searches current instance for the first instance of NeedleObj from StartOffset
  5054. Parameters:
  5055. NeedleObj
  5056. Instanece of MfMemStrView that represents needle in bytes to search for
  5057. StartOffset
  5058. The zero based index offset in bytes to start the search from
  5059. Returns:
  5060. Returns -1 if SearchString is not found; Otherwise zero based index of found position
  5061. Remarks:
  5062. Wraper method for InBuf
  5063. This method is super fast due to the machine code that performs the search
  5064. */
  5065. InBuffer(ByRef NeedleObj, StartOffset=0) {
  5066. if (NeedleObj.__Class != "MfMemStrView")
  5067. {
  5068. ex := new MfArgumentException(MfEnvironment.Instance.GetResourceString("Argument_NonMfObjectWithParamName", "ObjA", "MfMemStrView"), "ObjA")
  5069. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  5070. throw ex
  5071. }
  5072. if (!(this.m_Encoding = NeedleObj.m_Encoding))
  5073. {
  5074. ex := new MfFormatException(MfEnvironment.Instance.GetResourceString("Format_Encoding_MisMatch"))
  5075. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  5076. throw ex
  5077. }
  5078. ;NeedleStr := "over"
  5079. ;haystack := "the quick brown fox jumped over the lazy dog which is funny"
  5080. if (NeedleObj.Pos = 0)
  5081. {
  5082. return -1
  5083. }
  5084. haystackAddr := this[]
  5085. BytesPerChar := this.m_BytesPerChar
  5086. StartOffset := StartOffset * BytesPerChar
  5087.  
  5088. needleAddr := NeedleObj[]
  5089. needleSize := (NeedleObj.Pos - BytesPerChar)
  5090. haystackSize := this.Pos
  5091. result := MfMemStrView.InBuf(haystackAddr, needleAddr, this.Pos, needleSize, StartOffset)
  5092. if (result > 0)
  5093. {
  5094. result := result // BytesPerChar
  5095. }
  5096. return result
  5097. }
  5098. ; End:InBuffer ;}
  5099. ;{ InBufferRev
  5100. ;{ InBufferRev
  5101. /*
  5102. Method: InBufferRev()
  5103.  
  5104. InBufferRev()
  5105. Searches current instance for the last instance of NeedleObj from EndOffset
  5106. Parameters:
  5107. NeedleObj
  5108. Instanece of MfMemStrView that represents needle in bytes to search for
  5109. EndOffset
  5110. The zero based maximum hayStack offset to contain Needle's bytes, The is the conut from the
  5111. right to left of the string to look for the needle in.
  5112. Default value is -1
  5113. If value is -1 then reverse search is started from the first byte
  5114. Returns:
  5115. Returns -1 if SearchString is not found; Otherwise zero based index of found position
  5116. Remarks:
  5117. Wraper method for InBufRev
  5118. This method is super fast due to the machine code that performs the search
  5119. */
  5120. InBufferRev(ByRef NeedleObj, EndOffset=-1) {
  5121. if (NeedleObj.__Class != "MfMemStrView")
  5122. {
  5123. ex := new MfArgumentException(MfEnvironment.Instance.GetResourceString("Argument_NonMfObjectWithParamName", "ObjA", "MfMemStrView"), "ObjA")
  5124. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  5125. throw ex
  5126. }
  5127. if (!(this.m_Encoding = NeedleObj.m_Encoding))
  5128. {
  5129. ex := new MfFormatException(MfEnvironment.Instance.GetResourceString("Format_Encoding_MisMatch"))
  5130. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  5131. throw ex
  5132. }
  5133. if (NeedleObj.Pos = 0)
  5134. {
  5135. return -1
  5136. }
  5137. BytesPerChar := this.m_BytesPerChar
  5138. haystackAddr := this[]
  5139.  
  5140. if (EndOffset > 0)
  5141. {
  5142. EndOffset := EndOffset * BytesPerChar
  5143. }
  5144. else
  5145. {
  5146. EndOffset := -1 ; ensure set not less then -1
  5147. }
  5148.  
  5149. needleAddr := NeedleObj[]
  5150. needleSize := (NeedleObj.Pos - BytesPerChar)
  5151. haystackSize := this.Pos - BytesPerChar
  5152. result := MfMemStrView.InBufRev(haystackAddr, needleAddr, haystackSize, needleSize, EndOffset)
  5153. if (result > 0)
  5154. {
  5155. result := result // BytesPerChar
  5156. }
  5157. return result
  5158. }
  5159. ; End:InBufferRev ;}
  5160. ;{ InBuf
  5161. /*
  5162. Method: InBuf()
  5163.  
  5164. InBuf()
  5165. Blazing fast machine-code CASE-SENSITIVE searching in a (binary) buffer for a sequence of bytes,
  5166. that may include NULL characters.
  5167. Parameters:
  5168. haystackAddr
  5169. The memory address of the string to search
  5170. needleAddr
  5171. The Memory address of the string that is to be searched for in haystack
  5172. haystackSize
  5173. The size of the haystack in bytes
  5174. needleSize
  5175. The size of the needle in bytes
  5176. StartOffset
  5177. The zero based index offset value to begin the searh in haystack
  5178. Returns:
  5179. Returns zero based index of position of 'sought' inside 'haystack' or -1 if not found.
  5180. Remarks:
  5181. See https://autohotkey.com/board/topic/23627-machine-code-binary-buffer-searching-regardless-of-null/
  5182. Credit for this method goes to wOxxOm
  5183. See InBuffer for wraper function
  5184. Static Method
  5185. */
  5186. InBuf(haystackAddr, needleAddr, haystackSize, needleSize, StartOffset=0) {
  5187. Static fun
  5188. IfEqual,fun,
  5189. {
  5190. h=
  5191. ( LTrim join
  5192. 5589E583EC0C53515256579C8B5D1483FB000F8EC20000008B4D108B451829C129D9410F8E
  5193. B10000008B7D0801C78B750C31C0FCAC4B742A4B742D4B74364B74144B753F93AD93F2AE0F
  5194. 858B000000391F75F4EB754EADF2AE757F3947FF75F7EB68F2AE7574EB628A26F2AE756C38
  5195. 2775F8EB569366AD93F2AE755E66391F75F7EB474E43AD8975FC89DAC1EB02895DF483E203
  5196. 8955F887DF87D187FB87CAF2AE75373947FF75F789FB89CA83C7038B75FC8B4DF485C97404
  5197. F3A775DE8B4DF885C97404F3A675D389DF4F89F82B45089D5F5E5A595BC9C2140031C0F7D0EBF0
  5198. )
  5199. VarSetCapacity(fun,StrLen(h)//2)
  5200. Loop % StrLen(h)//2
  5201. NumPut("0x" . SubStr(h,2*A_Index-1,2), fun, A_Index-1, "Char")
  5202. }
  5203. Return DllCall(&fun
  5204. , "uint",haystackAddr, "uint",needleAddr
  5205. , "uint",haystackSize, "uint",needleSize
  5206. , "uint",StartOffset)
  5207. }
  5208. ; End:InBuf ;}
  5209. ;{ InBufRev
  5210. /*
  5211. Method: InBufRev()
  5212.  
  5213. InBufRev()
  5214. Blazing fast machine-code CASE-SENSITIVE searching in a (binary) buffer for a sequence of bytes,
  5215. that may include NULL characters. Reverse look for binary Needle in binary Buffer
  5216. Parameters:
  5217. haystackAddr
  5218. The memory address of the string to search
  5219. needleAddr
  5220. The Memory address of the string that is to be searched for in haystack
  5221. haystackSize
  5222. The size of the haystack in bytes
  5223. needleSize
  5224. The size of the needle in bytes
  5225. StartOffsetOfLastNeedleByte
  5226. maximum hayStack offset to contain Needle's bytes (-1=whole haystackSize)
  5227. Returns:
  5228. Returns zero based index of position of 'sought' inside 'haystack' or -1 if not found.
  5229. Remarks:
  5230. See https://autohotkey.com/board/topic/23627-machine-code-binary-buffer-searching-regardless-of-null/
  5231. Credit for this method goes to wOxxOm
  5232. See InBufferRev for wraper function
  5233. Static Method
  5234. */
  5235. InBufRev(haystackAddr, needleAddr, haystackSize, needleSize, StartOffsetOfLastNeedleByte=-1) {
  5236. Static fun
  5237. IfEqual,fun,
  5238. {
  5239. h=
  5240. ( LTrim join
  5241. 5589E583EC0C53515256579C8B5D1483FB000F8EDE0000008B4510488B4D1883F9FF0F44
  5242. C839C80F4CC829D989CF410F8EC1000000037D088B750C83E000FCAC4B74224B742A4B74
  5243. 354B74434B754E93AD93FDF2AE0F859B000000395F0275F3E981000000FDF2AE0F858800
  5244. 0000EB76FD8A26F2AE757F38670275F7EB689366AD93FDF2AE756F66395F0275F6EB574E
  5245. ADFDF2AE756039470175F7EB494E43AD8975FC89DAC1EB02895DF483E2038955F887DF87
  5246. D1FD87FB87CAF2AE753839470175F7FC89FB89CA83C7058B75FC8B4DF485C97404F3A775
  5247. DC8B4DF885C97404F3A675D189DF4789F82B45089D5F5E5A595BC9C2140031C0F7D0EBF0
  5248. )
  5249. VarSetCapacity(fun,StrLen(h)//2)
  5250. Loop % StrLen(h)//2
  5251. NumPut("0x" . SubStr(h,2*A_Index-1,2), fun, A_Index-1, "Char")
  5252. }
  5253. return DllCall(&fun
  5254. , "uint",haystackAddr, "uint",needleAddr
  5255. , "uint",haystackSize, "uint",needleSize
  5256. , "uint",StartOffsetOfLastNeedleByte)
  5257. }
  5258. ; End:InBufRev ;}
  5259. ;{ IndexOf
  5260. /*
  5261. Method: IndexOf()
  5262.  
  5263. IndexOf()
  5264. Gets the First index of NeedleObj in current instance
  5265. Parameters:
  5266. NeedleObj
  5267. Instance of MfMemStrView that represents the needle byte(s) to search for
  5268. StartIndex
  5269. The index to start the searh for needleObj. Search is preformed from
  5270. StartIndex to the start of the string bytes
  5271. Default value is -1 which search from end of current instance
  5272. Count
  5273. The number of chars to examine from StartIndex location
  5274. IgnoreCase
  5275. If True Case will not be considered; Otherwise case will be considered.
  5276. Default value is true
  5277. Returns:
  5278. Returns the zero based index of NeedleObj if found within current instance; Othwrwise -1
  5279. Throws:
  5280. Throws MfArgumentException
  5281. Remarks:
  5282. Return index is the index with the char count and may not be the same as the byte position
  5283. */
  5284. IndexOf(ByRef NeedleObj, StartIndex=0, Count=-1, IgnoreCase=false) {
  5285. if (NeedleObj.__Class != "MfMemStrView")
  5286. {
  5287. ex := new MfArgumentException(MfEnvironment.Instance.GetResourceString("Argument_NonMfObjectWithParamName", "obj", "MfMemStrView"), "obj")
  5288. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  5289. throw ex
  5290. }
  5291. if (Count = 0)
  5292. {
  5293. return -1
  5294. }
  5295. BytesPerChar := this.m_BytesPerChar
  5296.  
  5297. if ((StartIndex + 1) * BytesPerChar >= this.Pos - BytesPerChar) ; adjust for zero based index
  5298. {
  5299. Return -1
  5300. }
  5301. maxIndex := (this.Pos - (BytesPerChar * 2)) // BytesPerChar ; adjust for zero base index
  5302. if (Count > maxIndex + 1)
  5303. {
  5304. return -1
  5305. }
  5306. if (Count < 0)
  5307. {
  5308. count := maxIndex + 1
  5309. }
  5310. needleSize := (NeedleObj.Pos - BytesPerChar) // BytesPerChar
  5311. if (needleSize > maxIndex)
  5312. {
  5313. return -1
  5314. }
  5315.  
  5316. sType := this.m_sType
  5317. ptr := this[]
  5318. ptrNeedle := NeedleObj[]
  5319. NeedleFirstNum := NumGet(ptrNeedle + 0, 0, sType)
  5320. if (NeedleFirstNum = 0)
  5321. {
  5322. return -1
  5323. }
  5324. NeedleFirtChar := Chr(NeedleFirstNum)
  5325.  
  5326. i := StartIndex
  5327. MatchCount := 0
  5328. maxCount := MfMath.Min(StartIndex + Count, maxIndex + 1)
  5329. while ( i < maxCount)
  5330. {
  5331.  
  5332. Num1 := NumGet(ptr + 0, i * BytesPerChar, sType)
  5333. if (MatchCount = 0)
  5334. {
  5335. if (Num1 = NeedleFirstNum)
  5336. {
  5337. MatchCount++
  5338. if (MatchCount = needleSize)
  5339. {
  5340. break
  5341. }
  5342. i++
  5343. continue
  5344. }
  5345. if (!IgnoreCase)
  5346. {
  5347. If (MfMemStrView._IsLatin1(Num1) && MfMemStrView._IsLatin1(NeedleFirstNum))
  5348. {
  5349. if (MfMemStrView._IsEqualLatin1IgnoreCase(Num1, NeedleFirstNum))
  5350. {
  5351. MatchCount++
  5352. if (MatchCount = needleSize)
  5353. {
  5354. break
  5355. }
  5356. i++
  5357. Continue
  5358. }
  5359. }
  5360. Else
  5361. {
  5362. Char1 := Chr(Num1)
  5363. if (Char1 = NeedleFirtChar)
  5364. {
  5365. MatchCount++
  5366. if (MatchCount = needleSize)
  5367. {
  5368. break
  5369. }
  5370. i++
  5371. continue
  5372. }
  5373. }
  5374. }
  5375. MatchCount := 0
  5376. i++
  5377. continue
  5378. }
  5379. ; matchcount is greater then 0
  5380. Num2 := NumGet(ptrNeedle + 0, MatchCount * BytesPerChar, sType)
  5381. if (Num1 = Num2)
  5382. {
  5383. MatchCount++
  5384. if (MatchCount = needleSize)
  5385. {
  5386. break
  5387. }
  5388. i++
  5389. continue
  5390. }
  5391. if (!IgnoreCase)
  5392. {
  5393. If (MfMemStrView._IsLatin1(Num1) && MfMemStrView._IsLatin1(Num2))
  5394. {
  5395. if (MfMemStrView._IsEqualLatin1IgnoreCase(Num1, Num2))
  5396. {
  5397. MatchCount++
  5398. if (MatchCount = needleSize)
  5399. {
  5400. break
  5401. }
  5402. i++
  5403. Continue
  5404. }
  5405. }
  5406. else
  5407. {
  5408. Char1 := Chr(Num1)
  5409. Char2 := Chr(Num2)
  5410. if (Char1 = Char2)
  5411. {
  5412. MatchCount++
  5413. if (MatchCount = needleSize)
  5414. {
  5415. break
  5416. }
  5417. i++
  5418. Continue
  5419. }
  5420. }
  5421. }
  5422. MatchCount := 0
  5423. i++
  5424. }
  5425. if (MatchCount = needleSize)
  5426. {
  5427. return ++i - MatchCount
  5428. }
  5429. Return -1
  5430. }
  5431. ; End:IndexOf ;}
  5432.  
  5433. ;{ Insert
  5434. /*
  5435. Method: Insert()
  5436.  
  5437. Insert()
  5438. Inserts the contents of obj into current instance
  5439. Parameters:
  5440. startIndex
  5441. The zero based index to start the insertion
  5442. obj
  5443. The MfMemStrView instance to insert into this instance
  5444. Returns:
  5445. Returns the number of char of this instance after insert
  5446. Throws:
  5447. Throws MfArgumentException
  5448. Remarks:
  5449. see InsertStr to insert as string var
  5450. */
  5451. Insert(startIndex, ByRef obj) {
  5452. ; StartPos is the Position to start inserting text
  5453. if (obj.__Class != "MfMemStrView")
  5454. {
  5455. ex := new MfArgumentException(MfEnvironment.Instance.GetResourceString("Argument_NonMfObjectWithParamName", "obj", "MfMemStrView"), "obj")
  5456. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  5457. throw ex
  5458. }
  5459. BytesPerChar := this.m_BytesPerChar
  5460. If (obj.Pos <= BytesPerChar)
  5461. {
  5462. return this.GetCharCount()
  5463. }
  5464. If (!(this.m_Encoding = obj.m_Encoding))
  5465. {
  5466. return this.InsertStr(startIndex, obj.ToString())
  5467. }
  5468.  
  5469. PI := this.Pos ; this will be the end the current chars
  5470. startIndex := MfInteger.GetValue(startIndex)
  5471. if (startIndex < 0)
  5472. {
  5473. ex := new MfArgumentOutOfRangeException("startPos", MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_SmallCapacity"))
  5474. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  5475. throw ex
  5476. }
  5477. iLen := (obj.Pos - BytesPerChar) ; * BytesPerChar
  5478. if ((startIndex + iLen) >= (this.size - BytesPerChar))
  5479. {
  5480. ex := new MfArgumentOutOfRangeException("requiredLength", MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_SmallCapacity"))
  5481. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  5482. throw ex
  5483. }
  5484.  
  5485. ; Make Room for the new Insert
  5486. SourcePtr := this[] + startIndex
  5487. ; CopyFromAddress will copy the memory from startPos and slide then right
  5488. iCount := (PI - BytesPerChar) - StartIndex
  5489. ;MfMemStrView.CopyFromAddress(SourcePtr, this, startIndex + iLen, PI < this.Size ? PI : this.Size)
  5490. MfMemStrView.CopyFromAddress(SourcePtr, this, startIndex + iLen, iCount)
  5491. ; will be a new pos here will manually reset pos as we know the pos is + ilen
  5492. PI += iLen
  5493. this.Pos := PI
  5494.  
  5495. ; not that we have created the space for the insert the next step is to isert obj into that space
  5496. MfMemStrView.CopyFromAddress(obj[], this, startIndex, ilen)
  5497. return this.GetCharCount()
  5498. }
  5499. ; End:Insert ;}
  5500. ;{ InsertStr
  5501. /*
  5502. Method: InsertStr()
  5503.  
  5504. InsertStr()
  5505. Inserts the contents of str into current instance
  5506. Parameters:
  5507. startIndex
  5508. The zero based index to start the insertion
  5509. obj
  5510. The string var to insert into this instance
  5511. Returns:
  5512. Returns the number of char of this instance after insert
  5513. Remarks:
  5514. see Insert to insert as MfMemStrView instance
  5515. */
  5516. InsertStr(startIndex, str) {
  5517. ; StartPos is the Position to start inserting text
  5518.  
  5519. strLength := StrLen(str)
  5520. If (strLength = 0)
  5521. {
  5522. return this.GetCharCount()
  5523. }
  5524. BytesPerChar := this.m_BytesPerChar
  5525. Size := (strLength + BytesPerChar) * BytesPerChar
  5526. mv := new MfMemStrView(Size, this.m_FillBytes, this.m_Encoding)
  5527. mv.Append(str)
  5528. return this.Insert(startIndex, mv)
  5529. }
  5530. ; End:InsertStr ;}
  5531. ;{ IsWhiteSpace
  5532. /*
  5533. Method: IsWhiteSpace()
  5534.  
  5535. IsWhiteSpace()
  5536. Check to see if a char number is considered to be whitespace
  5537. Parameters:
  5538. cc
  5539. The char number to check
  5540. Returns:
  5541. Returns boolean true if cc is whitespace char; Otherwise false
  5542. Remarks:
  5543. Char numbers are base on unicode
  5544. */
  5545. IsWhiteSpace(cc) {
  5546. ; from unicode database
  5547. retval := ((cc >= 9 && cc <= 13) || (cc = 32) || (cc = 133) || (cc = 160) || (cc = 5760) || (cc >= 8192 && cc <= 8202)
  5548. || (cc = 8232) || (cc = 8233) || (cc = 8239) || (cc = 8287) || (cc = 12288))
  5549. return retval
  5550. }
  5551. ; End:IsWhiteSpace ;}
  5552. ;{ LastIndexOf
  5553. /*
  5554. Method: LastIndexOf()
  5555.  
  5556. LastIndexOf()
  5557. Gets the last index of NeedleObj in current instance
  5558. Parameters:
  5559. NeedleObj
  5560. Instance of MfMemStrView that represents the needle byte(s) to search for
  5561. EndIndex
  5562. The index to start the searh for needleObj. Search is preformed from
  5563. EndIndex to the start of the string bytes
  5564. Default value is -1 which search from end of current instance
  5565. Count
  5566. The number of chars to examine from EndIndex location
  5567. IgnoreCase
  5568. If True Case will not be considered; Otherwise case will be considered.
  5569. Default value is true
  5570. Returns:
  5571. Returns the zero based index of NeedleObj if found within current instance; Othwrwise -1
  5572. Throws:
  5573. Throws MfArgumentException
  5574. Remarks:
  5575. Return index is the index with the char count and may not be the same as the byte position
  5576. */
  5577. LastIndexOf(ByRef NeedleObj, EndIndex=-1, Count=-1, IgnoreCase=true) {
  5578. if (NeedleObj.__Class != "MfMemStrView")
  5579. {
  5580. ex := new MfArgumentException(MfEnvironment.Instance.GetResourceString("Argument_NonMfObjectWithParamName", "obj", "MfMemStrView"), "obj")
  5581. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  5582. throw ex
  5583. }
  5584. if (Count = 0)
  5585. {
  5586. return -1
  5587. }
  5588. BytesPerChar := this.m_BytesPerChar
  5589. if (EndIndex < 0)
  5590. {
  5591. EndIndex := this.Pos - (BytesPerChar * 2) ; adjust for zero base index
  5592. }
  5593. Else
  5594. {
  5595. EndIndex := EndIndex * BytesPerChar
  5596. }
  5597. if (EndIndex > (this.Pos - (BytesPerChar * 2))) ; adjust for zero base index
  5598. {
  5599. Return -1
  5600. }
  5601.  
  5602. maxIndex := EndIndex // BytesPerChar
  5603. if (Count > maxIndex + 1)
  5604. {
  5605. return -1
  5606. }
  5607. needleSize := (NeedleObj.Pos - BytesPerChar) // BytesPerChar
  5608. if (needleSize > maxIndex)
  5609. {
  5610. return -1
  5611. }
  5612. if (Count < 0)
  5613. {
  5614. count := maxIndex + 1
  5615. }
  5616.  
  5617. sType := this.m_sType
  5618. ptr := this[]
  5619. ptrNeedle := NeedleObj[]
  5620. NeedleLastPos := NeedleObj.Pos - BytesPerChar
  5621. NeedleLastNum := NumGet(ptrNeedle + 0, NeedleLastPos - BytesPerChar, sType)
  5622. if (NeedleLastNum = 0)
  5623. {
  5624. return -1
  5625. }
  5626. NeedleLastChar := Chr(NeedleLastNum)
  5627.  
  5628. i := maxIndex
  5629. minIndex := 0
  5630. MatchCount := 0
  5631. iCount = 0
  5632. while ( i > minIndex)
  5633. {
  5634. iCount++
  5635. if (iCount > Count)
  5636. {
  5637. return -1
  5638. }
  5639. Num1 := NumGet(ptr + 0, i * BytesPerChar, sType)
  5640. if (MatchCount = 0)
  5641. {
  5642. if (Num1 = NeedleLastNum)
  5643. {
  5644. MatchCount++
  5645. if (MatchCount = needleSize)
  5646. {
  5647. break
  5648. }
  5649. i--
  5650. continue
  5651. }
  5652. if (!IgnoreCase)
  5653. {
  5654. If (MfMemStrView._IsLatin1(Num1) && MfMemStrView._IsLatin1(NeedleLastNum))
  5655. {
  5656. if (MfMemStrView._IsEqualLatin1IgnoreCase(Num1, NeedleLastNum))
  5657. {
  5658. MatchCount++
  5659. if (MatchCount = needleSize)
  5660. {
  5661. break
  5662. }
  5663. i--
  5664. Continue
  5665. }
  5666. }
  5667. Else
  5668. {
  5669. Char1 := Chr(Num1)
  5670. if (Char1 = NeedleLastChar)
  5671. {
  5672. MatchCount++
  5673. if (MatchCount = needleSize)
  5674. {
  5675. break
  5676. }
  5677. i--
  5678. continue
  5679. }
  5680. }
  5681. }
  5682. MatchCount := 0
  5683. i--
  5684. continue
  5685. }
  5686. ; matchcount is greater then 0
  5687. Num2 := NumGet(ptrNeedle + 0, ((needleSize - 1) - MatchCount) * BytesPerChar, sType)
  5688. if (Num1 = Num2)
  5689. {
  5690. MatchCount++
  5691. if (MatchCount = needleSize)
  5692. {
  5693. break
  5694. }
  5695. i--
  5696. continue
  5697. }
  5698. if (!IgnoreCase)
  5699. {
  5700. If (MfMemStrView._IsLatin1(Num1) && MfMemStrView._IsLatin1(Num2))
  5701. {
  5702. if (MfMemStrView._IsEqualLatin1IgnoreCase(Num1, Num2))
  5703. {
  5704. MatchCount++
  5705. if (MatchCount = needleSize)
  5706. {
  5707. break
  5708. }
  5709. i--
  5710. Continue
  5711. }
  5712. }
  5713. else
  5714. {
  5715. Char1 := Chr(Num1)
  5716. Char2 := Chr(Num2)
  5717. if (Char1 = Char2)
  5718. {
  5719. MatchCount++
  5720. if (MatchCount = needleSize)
  5721. {
  5722. break
  5723. }
  5724. i--
  5725. Continue
  5726. }
  5727. }
  5728. }
  5729. MatchCount := 0
  5730. i--
  5731. }
  5732. if (MatchCount > 0)
  5733. {
  5734. return i
  5735. }
  5736. Return -1
  5737. }
  5738. ; End:LastIndexOf ;}
  5739. ;{ MoveBytesLeft
  5740. /*
  5741. Method: MoveBytesLeft()
  5742.  
  5743. MoveBytesLeft()
  5744. Move the characters in memory to the left overwriting any characters in position before move
  5745. Parameters:
  5746. StartIndex
  5747. The zero based char index to start overwriting
  5748. ShiftAmt
  5749. The number of bytes from StartIndex to start the shift
  5750. The First character at ShiftAmt will be written into the Position
  5751. of StartIndex, the second character from shiftAmount will be written
  5752. into the second position from StartIndex and so on.
  5753. Length
  5754. Length Limits how many bytes are shifted left from ShiftAmout
  5755. Default Value of Length is -1.
  5756. When omitted or less then 0 then all characters right of ShiftAmt are shift left.
  5757. If Length is greater then the last byte Position then all bytes right of shiftamt
  5758. will still be moved left
  5759. ZeroFillSpace
  5760. Optional Boolean value
  5761. Defautl Vaue is false
  5762. If True then the Space created when the bytes are moved are overwritten with 0
  5763. Throws:
  5764. Throws MfArgumentOutOfRangeException,
  5765. Remarks:
  5766. The Pos will be adjusted to reflect then new location
  5767. If Length is included and is less then the number of bytes past ShiftAmt to Pos
  5768. then all bytes from Length to Previous Pos are overwritten with current Fillbytes
  5769. */
  5770. MoveBytesLeft(StartIndex, ShiftAmt, Length=-1, ZeroFillSpace=false) {
  5771. if (Length = 0 || ShiftAmt = 0)
  5772. {
  5773. ; cannot move left already at the start or no shift amount to move
  5774. return
  5775. }
  5776. if (StartIndex < 0)
  5777. {
  5778. ex := new MfArgumentOutOfRangeException("StartIndex", MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_IndexString"))
  5779. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  5780. throw ex
  5781. }
  5782.  
  5783. if (ShiftAmt < 0)
  5784. {
  5785. ex := new MfArgumentOutOfRangeException("ShiftAmt", MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_IndexString"))
  5786. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  5787. throw ex
  5788. }
  5789. BytesPerChar := this.m_BytesPerChar
  5790. sType := this.m_sType
  5791. FillByte := this.m_FillBytes
  5792.  
  5793. PI := this.Pos ; this will be the end the current chars
  5794. if (Length < 0)
  5795. {
  5796. if (StartIndex + ShiftAmt > PI)
  5797. {
  5798. Length := ShiftAmt
  5799. }
  5800. else
  5801. {
  5802. Length := PI - StartIndex - ShiftAmt - BytesPerChar
  5803. }
  5804.  
  5805. }
  5806. if (StartIndex + ShiftAmt + BytesPerChar >= PI)
  5807. {
  5808. if (StartIndex + ShiftAmt > this.Size)
  5809. {
  5810. ex := new MfArgumentOutOfRangeException("Length", MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_IndexString"))
  5811. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  5812. throw ex
  5813. }
  5814. ; Shift Amount is beyond PI so delete all chars past index
  5815. length := PI - StartIndex
  5816. sourcePtr := this[] + StartIndex
  5817. this._FillByte(length, FillByte, BytesPerChar, sourcePtr)
  5818. this.Pos := StartIndex + BytesPerChar
  5819. return
  5820.  
  5821. }
  5822. Else
  5823. {
  5824. if (StartIndex + ShiftAmt + length > this.Size)
  5825. {
  5826. ex := new MfArgumentOutOfRangeException("Length", MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_IndexString"))
  5827. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  5828. throw ex
  5829. }
  5830. }
  5831.  
  5832. sourcePtr := this[] + StartIndex + ShiftAmt
  5833.  
  5834. MfMemStrView.CopyFromAddress(SourcePtr, this, StartIndex, Length )
  5835. lengthRemainder := (PI - BytesPerChar) - StartIndex - ShiftAmt - Length
  5836.  
  5837. if (lengthRemainder > 0 )
  5838. {
  5839. if (ZeroFillSpace)
  5840. {
  5841. sourcePtr := this[] + StartIndex + ShiftAmt + Length + BytesPerChar
  5842. this._FillByte(lengthRemainder, FillByte, BytesPerChar, sourcePtr)
  5843. }
  5844. this.Pos := StartIndex + Length + BytesPerChar
  5845. }
  5846. else
  5847. {
  5848. this.Pos -= ShiftAmt
  5849. }
  5850.  
  5851. }
  5852. ; End:MoveBytesLeft ;}
  5853. ;{ Copy
  5854. /*
  5855. Method: Copy()
  5856.  
  5857. Copy()
  5858. Copies the Source MfMemStrView bytes instance to destination MfMemStrView
  5859. Parameters:
  5860. sourceMemView
  5861. Source instance of MfMemStrView
  5862. destinationMemView
  5863. Destination instance of MfMemStrView
  5864. destinationIndex
  5865. The Destination index to start copying into
  5866. count
  5867. The Number of bytes to copy
  5868. Throws:
  5869. Throws MfArgumentException, MfArgumentOutOfRangeException, MfFormatException
  5870. Remarks:
  5871. If destinationMemView.Pos is less then destinationIndex + count it is adjusted to the position of destinationIndex + count
  5872. Static Method
  5873. */
  5874. Copy(sourceMemView, destinationMemView, destinationIndex, count) {
  5875. if (sourceMemView.__Class != "MfMemStrView")
  5876. {
  5877. ex := new MfArgumentException(MfEnvironment.Instance.GetResourceString("Argument_NonMfObjectWithParamName", "sourceMemView", "MfMemStrView"), "sourceMemView")
  5878. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  5879. throw ex
  5880. }
  5881. if (destinationMemView.__Class != "MfMemStrView")
  5882. {
  5883. ex := new MfArgumentException(MfEnvironment.Instance.GetResourceString("Argument_NonMfObjectWithParamName", "destinationMemView", "MfMemStrView"), "destinationMemView")
  5884. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  5885. throw ex
  5886. }
  5887. destinationIndex := MfInteger.GetValue(destinationIndex)
  5888. count := MfInteger.GetValue(count)
  5889. if (count <= 0)
  5890. {
  5891. return
  5892. }
  5893. if (destinationIndex < 0)
  5894. {
  5895. ex := new MfArgumentOutOfRangeException("destinationIndex", MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_MustBePositive", "destinationIndex"))
  5896. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  5897. throw ex
  5898. }
  5899. if (sourceMemView.Size = 0)
  5900. {
  5901. ex := new MfArgumentOutOfRangeException("sourceMemView", MfEnvironment.Instance.GetResourceString("Arg_ArrayTooSmall"))
  5902. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  5903. throw ex
  5904. }
  5905. if (!(sourceMemView.m_Encoding = destinationMemView.m_Encoding))
  5906. {
  5907. ex := new MfFormatException(MfEnvironment.Instance.GetResourceString("Format_Encoding_MisMatch"))
  5908. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  5909. throw ex
  5910. }
  5911. if (sourceMemView.Size < count)
  5912. {
  5913. ex := new MfArgumentOutOfRangeException("count", MfEnvironment.Instance.GetResourceString("Arg_ArrayTooSmall"))
  5914. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  5915. throw ex
  5916. }
  5917. if (destinationIndex <= destinationMemView.Size && destinationIndex + count <= destinationMemView.Size)
  5918. {
  5919. SourcePtr := sourceMemView[]
  5920. PI := destinationMemView.Pos
  5921. DestPtr := destinationMemView[] + destinationIndex
  5922. ; source and Dest may be in the same address space so use a tmp to go between
  5923. tmp := ""
  5924. VarSetCapacity(tmp, count)
  5925. DllCall("RtlMoveMemory", "PTR", &tmp, "PTR", SourcePtr + 0, "UCHAR", count)
  5926.  
  5927. DllCall("RtlMoveMemory", "PTR", DestPtr + 0, "PTR", &tmp, "UCHAR", count)
  5928.  
  5929. VarSetCapacity(tmp, 0)
  5930.  
  5931. ; DllCall("RtlMoveMemory", "Ptr", SourcePtr + 0, "Ptr", DestPtr + 0, "UChar", count)
  5932. if (destinationIndex + count > PI)
  5933. {
  5934. destinationMemView.Pos := (destinationIndex + count)
  5935. }
  5936. return
  5937. }
  5938. ex := new MfArgumentOutOfRangeException("destinationIndex", MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_Index"))
  5939. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  5940. throw ex
  5941. }
  5942. ; End:Copy ;}
  5943. ;{ CopyFromAddress
  5944. /*
  5945. Method: CopyFromAddress()
  5946.  
  5947. CopyFromAddress()
  5948. Copies the Source address bytes to destination MfMemStrView
  5949. Parameters:
  5950. SourceAddress
  5951. Source memory address of bytes to copy
  5952. destinationMemView
  5953. Destination instance of MfMemStrView
  5954. destinationIndex
  5955. The Destination index to start copying into
  5956. count
  5957. The Number of bytes to copy
  5958. Throws:
  5959. Throws MfArgumentException, MfArgumentOutOfRangeException, MfFormatException
  5960. Remarks:
  5961. If destinationMemView.Pos is less then destinationIndex + count it is adjusted to the position of destinationIndex + count
  5962. Static Method
  5963. */
  5964. CopyFromAddress(SourceAddress, ByRef destinationMemView, destinationIndex, count) {
  5965. if (MfNull.IsNull(SourceAddress) || Mfunc.IsInteger(SourceAddress) = false)
  5966. {
  5967. ex := new MfArgumentException(MfEnvironment.Instance.GetResourceString("Argument_Address", "SourceAddress"), "SourceAddress")
  5968. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  5969. throw ex
  5970. }
  5971. if (destinationMemView.__Class != "MfMemStrView")
  5972. {
  5973. ex := new MfArgumentException(MfEnvironment.Instance.GetResourceString("Argument_NonMfObjectWithParamName", "destinationMemView", "MfMemStrView"), "destinationMemView")
  5974. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  5975. throw ex
  5976. }
  5977. destinationIndex := MfInteger.GetValue(destinationIndex)
  5978. count := MfInteger.GetValue(count)
  5979. if (count <= 0)
  5980. {
  5981. return
  5982. }
  5983. ; if (destinationIndex < 0)
  5984. ; {
  5985. ; ex := new MfArgumentOutOfRangeException("destinationIndex", MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_MustBePositive", "destinationIndex"))
  5986. ; ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  5987. ; throw ex
  5988. ; }
  5989.  
  5990. if (destinationIndex <= destinationMemView.Size && destinationIndex + count <= destinationMemView.Size)
  5991. {
  5992. SourcePtr := SourceAddress
  5993. PI := destinationMemView.Pos
  5994. DestPtr := destinationMemView[] + destinationIndex
  5995.  
  5996. ; source and Dest may be in the same address space so use a tmp to go between
  5997. tmp := ""
  5998. VarSetCapacity(tmp, count)
  5999. DllCall("RtlMoveMemory", "Ptr", &tmp, "Ptr", SourcePtr + 0, "UChar", count)
  6000.  
  6001. DllCall("RtlMoveMemory", "Ptr", DestPtr + 0, "Ptr", &tmp, "UChar", count)
  6002.  
  6003. ;~ str := StrGet(&tmp, ,destinationMemView.m_Encoding)
  6004. ;~ str2 := StrGet(destinationMemView[], ,destinationMemView.m_Encoding)
  6005. ;~ str3 := StrGet(DestPtr + 0, ,destinationMemView.m_Encoding)
  6006.  
  6007. VarSetCapacity(tmp, 0)
  6008. if (destinationIndex + count > PI)
  6009. {
  6010. destinationMemView.Pos := (destinationIndex + count)
  6011. }
  6012. return
  6013. }
  6014. ex := new MfArgumentOutOfRangeException("destinationIndex", MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_Index"))
  6015. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  6016. throw ex
  6017. }
  6018. ; End:CopyFromAddress ;}
  6019. ;{ CopyFromAddressToCharList
  6020. /*
  6021. Method: CopyFromAddressToCharList()
  6022.  
  6023. CopyFromAddressToCharList()
  6024. Copies the Source address bytes to destination MfCharList
  6025. Parameters:
  6026. SourceAddress
  6027. Source memory address of bytes to copy
  6028. CharList
  6029. Destination instance of MfCharList
  6030. destinationIndex
  6031. The Destination index to start copying into
  6032. count
  6033. The Number of bytes to copy
  6034. Throws:
  6035. Throws MfArgumentException, MfArgumentOutOfRangeException, MfFormatException
  6036. Remarks:
  6037. If CharList.Count is less then destinationIndex + count it is zero filled before copying from memory to the position of destinationIndex + count
  6038. Static Method
  6039. */
  6040. CopyFromAddressToCharList(SourceAddress, CharList, destinationIndex, count) {
  6041. if (MfNull.IsNull(SourceAddress) || Mfunc.IsInteger(SourceAddress) = false)
  6042. {
  6043. ex := new MfArgumentException(MfEnvironment.Instance.GetResourceString("Argument_Address", "SourceAddress"), "SourceAddress")
  6044. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  6045. throw ex
  6046. }
  6047. if (!MfObject.IsObjInstance(CharList, MfCharList))
  6048. {
  6049. ex := new MfArgumentException(MfEnvironment.Instance.GetResourceString("NullReferenceException_Object_Param", "CharList"), "CharList")
  6050. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  6051. throw ex
  6052. }
  6053. destinationIndex := MfInteger.GetValue(destinationIndex)
  6054. count := MfInteger.GetValue(count)
  6055. if (count <= 0)
  6056. {
  6057. return
  6058. }
  6059. BytesPerChar := CharList.m_BytesPerChar
  6060. sType := CharList.m_sType
  6061. NewSize := destinationIndex + count
  6062.  
  6063. if (CharList.m_Count < NewSize)
  6064. {
  6065.  
  6066. while (CharList.m_Count < NewSize)
  6067. {
  6068. CharList._Add(0)
  6069. i++
  6070. }
  6071. }
  6072.  
  6073. if (destinationIndex <= CharList.m_Count && destinationIndex + count <= CharList.m_Count)
  6074. {
  6075. Ptr := SourceAddress
  6076. a := CharList.m_InnerList
  6077. i := 0
  6078. destinationIndex++ ; move to one base array
  6079. While (i < count)
  6080. {
  6081. num := NumGet(Ptr + 0, i * BytesPerChar, sType)
  6082. a[destinationIndex + i] := num
  6083. i++
  6084. }
  6085.  
  6086. return
  6087. }
  6088. ex := new MfArgumentOutOfRangeException("destinationIndex", MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_Index"))
  6089. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  6090. throw ex
  6091. }
  6092. ; End:CopyFromAddressToCharList ;}
  6093. ;{ MoveBytesRight
  6094. /*
  6095. Method: MoveBytesRight()
  6096.  
  6097. MoveBytesRight()
  6098. Move the Bytes in memory to the Right inserting null 0 from StartIndex to ShiftAmt
  6099. Parameters:
  6100. StartIndex
  6101. The zero based Starting index in bytes to inserting 0 values
  6102. ShiftAmt
  6103. The Number of 0 bytes to insert at the StartIndex
  6104. Length
  6105. Length Limits how many bytes are moved to the end.
  6106. Default Value is -1.
  6107. If Omitted or less then zero then all bytes from the StartIndex are moved to the right
  6108. ZeroFillSpace
  6109. Optional Boolean value
  6110. Defautl Vaue is false
  6111. If True then the Space created when the bytes are moved are overwritten with 0
  6112. Throws:
  6113. Throws MfArgumentOutOfRangeException
  6114. Remarks:
  6115. Pos is set to the new location after the chars have been moved.
  6116. This method does not increase the size of the current instance and there must be
  6117. room in the buffer to ensure the move is successfull. An error will be throw if there is not
  6118. enough room in the buffer.
  6119. When bytes are moved to the right the ToString() method will stop at the first null char found.
  6120. Use GetStringIgnoreNull().ToString() if current string value is needed.
  6121. The Primary usage for this method is to move characters to the right so new characters can be inserted.
  6122. See the OverWrite method as well.
  6123. */
  6124. MoveBytesRight(StartIndex, ShiftAmt, Length=-1, ZeroFillSpace=false) {
  6125. if (Length = 0 || ShiftAmt = 0)
  6126. {
  6127. ; cannot move left already at the start or no shift amount to move
  6128. return
  6129. }
  6130. if (StartIndex < 0)
  6131. {
  6132. ex := new MfArgumentOutOfRangeException("StartIndex", MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_IndexString"))
  6133. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  6134. throw ex
  6135. }
  6136. BytesPerChar := this.m_BytesPerChar
  6137. sType := this.m_sType
  6138. FillByte := this.m_FillBytes
  6139.  
  6140. PI := this.Pos ; this will be the end the current chars
  6141. If (PI = 0)
  6142. {
  6143. return this
  6144. }
  6145. if (Length < 0)
  6146. {
  6147. Length := PI - BytesPerChar - StartIndex - ShiftAmt
  6148. }
  6149.  
  6150. if (ShiftAmt < 0)
  6151. {
  6152. ex := new MfArgumentOutOfRangeException("ShiftAmt", MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_IndexString"))
  6153. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  6154. throw ex
  6155. }
  6156.  
  6157. InsertEnd := StartIndex + ShiftAmt + Length
  6158. lengthRemainder := (PI - BytesPerChar) - InsertEnd
  6159.  
  6160. if (InsertEnd > this.Size)
  6161. {
  6162. ex := new MfIndexOutOfRangeException(MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_SmallCapacity"))
  6163. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  6164. throw ex
  6165. }
  6166.  
  6167. sourcePtr := this[] + StartIndex ; get the start pos Address
  6168. destPtr := sourcePtr + ShiftAmt
  6169.  
  6170. ; Make Room for the new Insert
  6171. SourcePtr := this[] + startIndex
  6172. ; CopyFromAddress will copy the memory from startPos and slide then right
  6173. MfMemStrView.CopyFromAddress(SourcePtr, this, startIndex + ShiftAmt, Length)
  6174.  
  6175.  
  6176. if (ZeroFillSpace)
  6177. {
  6178. ; overwrite the section just copied with fill bytes
  6179. this._FillByte(ShiftAmt, FillByte, BytesPerChar, sourcePtr)
  6180. }
  6181.  
  6182. if (lengthRemainder > 0 )
  6183. {
  6184. sourcePtr := this[] + StartIndex + ShiftAmt + Length ; + BytesPerChar
  6185. if (ZeroFillSpace)
  6186. {
  6187. this._FillByte(lengthRemainder, FillByte, BytesPerChar, sourcePtr)
  6188. }
  6189. this.Pos := InsertEnd + BytesPerChar
  6190. }
  6191. else if (InsertEnd < this.Size)
  6192. {
  6193. this.Pos := InsertEnd + BytesPerChar
  6194. }
  6195. else
  6196. {
  6197. this.Pos := this.Size
  6198. }
  6199. }
  6200. ; End:MoveBytesRight ;}
  6201. ;{ OverWrite
  6202. /*
  6203. Method: OverWrite()
  6204.  
  6205. OverWrite()
  6206. Overwrites the Bytes in this instance with the bytes in obj instance
  6207. Parameters:
  6208. obj
  6209. The instance of MfMemStrView that contains the bytes to overwrite in this instance
  6210. StartIndex
  6211. The zero based index to start overwriting bytes in this instance
  6212. Default value is 0
  6213. Length
  6214. The number of chars to read from obj and to ovrwrite in this instance
  6215. Default value is -1.
  6216. When Length is -1 the entire chars of obj will be read and overwritten in this instance.
  6217. Returns:
  6218. Returns the current char count.
  6219. Throws:
  6220. Throws MfArgumentException, MfArgumentOutOfRangeException, MfException
  6221. Remarks:
  6222. The Current char count should remain the same as this method overwrites chars and does not add or remove chars
  6223. */
  6224. OverWrite(ByRef obj, StartIndex=0, Length=-1) {
  6225. ; StartPos is the Position to start inserting text
  6226. if (obj.__Class != "MfMemStrView")
  6227. {
  6228. ex := new MfArgumentException(MfEnvironment.Instance.GetResourceString("Argument_NonMfObjectWithParamName", "obj", "MfMemStrView"), "obj")
  6229. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  6230. throw ex
  6231. }
  6232.  
  6233. if (!(this.m_Encoding = obj.m_Encoding))
  6234. {
  6235. ex := new MfFormatException(MfEnvironment.Instance.GetResourceString("Format_Encoding_MisMatch"))
  6236. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  6237. throw ex
  6238. }
  6239. BytesPerChar := this.m_BytesPerChar
  6240. ;StartIndex := StartIndex * BytesPerChar
  6241. if ((StartIndex < 0) || (StartIndex * BytesPerChar >= this.size))
  6242. {
  6243. ex := new MfArgumentOutOfRangeException("StartIndex", MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_IndexString"))
  6244. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  6245. throw ex
  6246. }
  6247. if (Length < 0)
  6248. {
  6249. Length := (obj.Pos - BytesPerChar) * BytesPerChar
  6250. }
  6251. else
  6252. {
  6253. Length := Length * BytesPerChar
  6254. }
  6255. if (Length <= 0 || Length > obj.Pos)
  6256. {
  6257. ex := new MfArgumentOutOfRangeException("StartIndex", MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_IndexString"))
  6258. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  6259. throw ex
  6260. }
  6261. if ((Length + StartIndex) > this.Size)
  6262. {
  6263. ex := new MfArgumentOutOfRangeException("Length", MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_IndexString"))
  6264. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  6265. throw ex
  6266. }
  6267.  
  6268. If (obj.Pos <= BytesPerChar)
  6269. {
  6270. return this.GetCharCount()
  6271. }
  6272.  
  6273. PI := this.Pos ; this will be the end the current chars
  6274.  
  6275. StartIndex := StartIndex * BytesPerChar
  6276. sType := this.m_sType
  6277. ;this.Seek(StrPut(str, enc) * BytesPerChar, 1)
  6278.  
  6279. try
  6280. {
  6281. ; copy the remainder of the string to a new address and then append it back later
  6282. this.Seek(StartIndex) ; Move to the start Pos
  6283. ptr := this[] + this.Pos
  6284. sourcePtr := obj[]
  6285.  
  6286. ; i := 0
  6287. ; While (i < Length)
  6288. ; {
  6289. ; num := NumGet(sourcePtr + i, 0, sType)
  6290. ; NumPut(num, ptr + i, 0, sType)
  6291. ; i += BytesPerChar
  6292. ; }
  6293.  
  6294. DllCall("RtlMoveMemory", "Ptr", ptr + 0, "Ptr", sourcePtr + 0, "UChar", Length)
  6295. ;DllCall("RtlMoveMemory", sType, ptr + 0, sType, sourcePtr + 0, sType, Length)
  6296.  
  6297. if (Length > PI)
  6298. {
  6299. this.Pos := Length + BytesPerChar
  6300. }
  6301. else
  6302. {
  6303. this.Pos := PI
  6304. }
  6305. }
  6306. catch e
  6307. {
  6308. if (MfObject.IsObjInstance(e, MfException))
  6309. {
  6310. throw e
  6311. }
  6312. ex := new MfException(MfEnvironment.Instance.GetResourceString("Exception_Error", A_ThisFunc), e)
  6313. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  6314. throw ex
  6315. }
  6316. Finally
  6317. {
  6318. if (this.Pos < PI)
  6319. {
  6320. this.Pos := PI
  6321. }
  6322. }
  6323. return this.GetCharCount()
  6324. }
  6325. ; End:OverWrite ;}
  6326. ;{ Reverse
  6327. /*
  6328. Method: Reverse()
  6329.  
  6330. Reverse()
  6331. Reverses the contentes of the currrent instance and returne it as a new instance
  6332. Parameters:
  6333. LimitBytes
  6334. If True then the return instance will have its size limited to the number of chars in the current instaned;
  6335. Otherwise the size will be the same size as the current instance
  6336. Returns:
  6337. Returns a new instance with the chars reversed
  6338. Remarks:
  6339. New line char sequences set in the framework will not be reversed in the return output.
  6340. the default new line chars are 13, 10 when the string is reversed the order will still be 13, 10
  6341. the order and char for new line are read from MfEnviroment.Instance.NewLine
  6342. */
  6343. Reverse(LimitBytes=false) {
  6344. rev := new MfMemStrView(LimitBytes?this.Pos + this.m_BytesPerChar: this.Size, this.m_FillBytes, this.m_Encoding)
  6345. If (this.Pos < 1)
  6346. {
  6347. return rev
  6348. }
  6349.  
  6350. ;nlChars := MfEnvironment.Instance.GetResourceStringBySection("NewLine", "SYSTEM")
  6351. ; capture the new line char(s) so we can add them to the reverse string in the same order
  6352. nl := MfEnvironment.Instance.NewLine
  6353. i := 1
  6354. arrNl := []
  6355. NewLineCount := StrLen(nl)
  6356. i := 1
  6357. While (i <= NewLineCount)
  6358. {
  6359. ; fill array so we can enter value in reverse later
  6360. arrNl[i] := 0
  6361. i++
  6362. }
  6363. i := NewLineCount
  6364. Loop, Parse, nl
  6365. {
  6366. ; fill the arrry with the reverse of the new line chars
  6367. arrNl[i] := asc(A_LoopField)
  6368. i--
  6369. }
  6370. LastNewChar := arrNl[1]
  6371.  
  6372. BytesPerChar := this.m_BytesPerChar
  6373. i := this.Pos - BytesPerChar
  6374. j := 0
  6375.  
  6376. sType := this.m_sType
  6377. thisAddress := this[]
  6378. revAddress := rev[]
  6379. LastChar := NumGet(thisAddress + 0, i , sType)
  6380. i -= BytesPerChar
  6381. While (i >= 0)
  6382. {
  6383. num := NumGet(thisAddress + 0, i , sType)
  6384. if ((num = LastNewChar) && (NewLineCount > 1) && (i - (BytesPerChar * NewLineCount) > 0))
  6385. {
  6386. ; do not reverse new line chars which is 13,10 by default
  6387. k := 2 ; already have amatch on the first
  6388. FoundNewLine := true
  6389. While k <= NewLineCount
  6390. {
  6391. numNext := NumGet(thisAddress + 0, i - (BytesPerChar * (k - 1)), sType) ; get the next char number for k
  6392. ; check the next char number against the revers array to see if it matches the next char in new line
  6393. if (numNext != arrNl[k])
  6394. {
  6395. ; no match, this byte sequence is not in the same order as new line chars sequence so will
  6396. ; ignore here and add as regular byte
  6397. FoundNewLine := false
  6398. break
  6399. }
  6400. k++
  6401. }
  6402. if (FoundNewLine)
  6403. {
  6404. ; new line byte sequence has been found so add a new line sequence of bytes to the reverse
  6405. ; from the new line array captured above
  6406. ; the array value are in reverse so count down to add into reverse output
  6407. k := NewLineCount
  6408. while (k >= 1)
  6409. {
  6410. NumPut(arrNl[k], revAddress + 0, j, sType)
  6411. j += BytesPerChar
  6412. i -= BytesPerChar
  6413. k--
  6414. }
  6415. continue
  6416. }
  6417. }
  6418. NumPut(num, revAddress + 0, j, sType)
  6419. i -= BytesPerChar
  6420. j += BytesPerChar
  6421. }
  6422. NumPut(LastChar, revAddress + 0, j, sType)
  6423. rev.Pos := this.Pos
  6424. return rev
  6425. }
  6426. ; End:Reverse ;}
  6427.  
  6428. ;{ _CompareOrdinalHelper
  6429. ; compare two instances of MfMemStrView and returns ordinal value comparsion
  6430. _CompareOrdinalHelper(objA, objB) {
  6431. BytesPerChar := objA.m_BytesPerChar
  6432. sType := objA.m_sType
  6433. i := objA.Pos > objB.Pos ? objB.Pos : objA.Pos
  6434. i -= BytesPerChar
  6435. num := -1
  6436. AddressA := objA[]
  6437. AddressB := objB[]
  6438. ptrA := objA[] ; first char address
  6439. ptrB := objB[] ; frist char address
  6440. While (i >= 5 * BytesPerChar)
  6441. {
  6442. numA := NumGet(ptrA + 0, 0, sType)
  6443. numB := NumGet(ptrB + 0, 0, sType)
  6444. if (numA != numB)
  6445. {
  6446. num := 0
  6447. break
  6448. }
  6449. numA := NumGet(ptrA + BytesPerChar, 0, sType)
  6450. numB := NumGet(ptrB + BytesPerChar, 0, sType)
  6451. if (numA != numB)
  6452. {
  6453. num := BytesPerChar
  6454. break
  6455. }
  6456. numA := NumGet(ptrA + (BytesPerChar * 2), 0, sType)
  6457. numB := NumGet(ptrB + (BytesPerChar * 2), 0, sType)
  6458. if (numA != numB)
  6459. {
  6460. num := BytesPerChar * 2
  6461. break
  6462. }
  6463. numA := NumGet(ptrA + (BytesPerChar * 3), 0, sType)
  6464. numB := NumGet(ptrB + (BytesPerChar * 3), 0, sType)
  6465. if (numA != numB)
  6466. {
  6467. num := BytesPerChar * 3
  6468. break
  6469. }
  6470. numA := NumGet(ptrA + (BytesPerChar * 4), 0, sType)
  6471. numB := NumGet(ptrB + (BytesPerChar * 4), 0, sType)
  6472. if (numA != numB)
  6473. {
  6474. num := BytesPerChar * 4
  6475. break
  6476. }
  6477. ptrA += BytesPerChar * 5
  6478. ptrB += BytesPerChar * 5
  6479. i -= BytesPerChar * 5
  6480. }
  6481. if (num != -1)
  6482. {
  6483. ptrA += num
  6484. ptrB += num
  6485. numA := NumGet(ptrA + 0, 0, sType)
  6486. numB := NumGet(ptrB + 0, 0, sType)
  6487. result := numA - numB
  6488. if (result != 0)
  6489. {
  6490. return result
  6491. }
  6492. numA := NumGet(ptrA + BytesPerChar, 0, sType)
  6493. numB := NumGet(ptrB + BytesPerChar, 0, sType)
  6494. return numA - numB
  6495. }
  6496. else
  6497. {
  6498. while (i > 0)
  6499. {
  6500. numA := NumGet(ptrA + 0, 0, sType)
  6501. numB := NumGet(ptrB + 0, 0, sType)
  6502. if (numA != numB)
  6503. {
  6504. break
  6505. }
  6506. ptrA += BytesPerChar
  6507. ptrB += BytesPerChar
  6508. i -= BytesPerChar
  6509. }
  6510. if (i <= 0)
  6511. {
  6512. return objA.Pos - objB.Pos
  6513. }
  6514. result := NumGet(ptrA + 0, 0, sType) - NumGet(ptrB + 0, 0, sType)
  6515. if (result != 0)
  6516. {
  6517. return result
  6518. }
  6519. numA := NumGet(ptrA + BytesPerChar, 0, sType)
  6520. numB := NumGet(ptrB + BytesPerChar, 0, sType)
  6521. return numA - numB
  6522. }
  6523. }
  6524. ; End:_CompareOrdinalHelper ;}
  6525.  
  6526. ;{ ToBase64
  6527. /*
  6528. Method: ToBase64()
  6529.  
  6530. ToBase64()
  6531. Reads instanceof MfMemStrView and returns a new MfMemStrView as base64 equal UTF-8 Encoded
  6532. Parameters:
  6533. data
  6534. The MfMemStrView instance to create base64 from
  6535. offset
  6536. Offset in bytes to start the encoding
  6537. addLineBreaks
  6538. If true then line breaks will be inserted into output every 76 chars
  6539. Returns:
  6540. Returns new instance of MfMemStrView with base64 encoded byte values
  6541. Throws:
  6542. Throws MfArgumentException
  6543. Remarks:
  6544. Translated from http://stackoverflow.com/questions/12178495/an-efficient-way-to-base64-encode-a-byte-array
  6545. Static method
  6546. */
  6547. ToBase64(ByRef data, offset, size, addLineBreaks=false) {
  6548. if (data.__Class != "MfMemStrView")
  6549. {
  6550. ex := new MfArgumentException(MfEnvironment.Instance.GetResourceString("Argument_NonMfObjectWithParamName", "data", "MfMemStrView"), "data")
  6551. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  6552. throw ex
  6553. }
  6554.  
  6555. strEnc := "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
  6556. base64EncodingTable := new MfMemStrView(StrPut(strEnc,"UTF-8"),,"UTF-8")
  6557. base64EncodingTable.AppendString(strEnc)
  6558.  
  6559. dataBPC := data.m_BytesPerChar
  6560. requiredSize := (4 * ((size + 2) / 3))
  6561. if (addLineBreaks)
  6562. {
  6563. requiredSize += requiredSize + (requiredSize / 38)
  6564. }
  6565. requiredSize := requiredSize * dataBPC
  6566.  
  6567.  
  6568. buffer := new MfMemStrView(ceil(requiredSize),,"UTF-8") ; base64 out only makes sense to output as utf-8
  6569. offset := offset * dataBPC
  6570. size := size * dataBPC
  6571. octet_a := ""
  6572. octet_b = ""
  6573. octet_c = ""
  6574. triple = ""
  6575. lineCount := 0
  6576. sizeMod := size - mod(size , 3)
  6577. ptr := data[]
  6578. ptrBuff := buffer[]
  6579. ptr64 := base64EncodingTable[]
  6580. mBufferPos := 0
  6581. while (offset < sizeMod)
  6582. {
  6583. octet_a := NumGet(ptr + 0, Offset++, "UChar")
  6584. octet_b := NumGet(ptr + 0, Offset++, "UChar")
  6585. octet_c := NumGet(ptr + 0, Offset++, "UChar")
  6586.  
  6587. triple := (octet_a << 0x10) + (octet_b << 0x08) + octet_c
  6588.  
  6589. numb64 := NumGet(ptr64 + 0, (triple >> 3 * 6) & 0x3F, "UChar")
  6590. NumPut(numb64, ptrBuff + 0 , mBufferPos++, "UChar")
  6591.  
  6592. numb64 := NumGet(ptr64 + 0, (triple >> 2 * 6) & 0x3F, "UChar")
  6593. NumPut(numb64, ptrBuff + 0 , mBufferPos++, "UChar")
  6594.  
  6595. numb64 := NumGet(ptr64 + 0, (triple >> 1 * 6) & 0x3F, "UChar")
  6596. NumPut(numb64, ptrBuff + 0 , mBufferPos++, "UChar")
  6597.  
  6598. numb64 := NumGet(ptr64 + 0, (triple >> 0 * 6) & 0x3F, "UChar")
  6599. NumPut(numb64, ptrBuff + 0 , mBufferPos++, "UChar")
  6600.  
  6601. if (addLineBreaks)
  6602. {
  6603. if (++lineCount = 19)
  6604. {
  6605. NumPut(13, ptrBuff + 0 , mBufferPos++, "UChar")
  6606.  
  6607. NumPut(10, ptrBuff + 0 , mBufferPos++, "UChar")
  6608. lineCount := 0
  6609. }
  6610. }
  6611. }
  6612. ; last bytes
  6613. if (sizeMod < size)
  6614. {
  6615. octet_a := offset < size ? NumGet(ptr + 0, Offset++, "UChar") : 0
  6616. octet_b := offset < size ? NumGet(ptr + 0, Offset++, "UChar") : 0
  6617. octet_c := 0 ; last character is definitely padded
  6618.  
  6619. triple := (octet_a << 0x10) + (octet_b << 0x08) + octet_c
  6620.  
  6621. numb64 := NumGet(ptr64 + 0, (triple >> 3 * 6) & 0x3F,"UChar")
  6622. NumPut(numb64, ptrBuff + 0 , mBufferPos++, "UChar")
  6623.  
  6624. numb64 := NumGet(ptr64 + 0, (triple >> 2 * 6) & 0x3F,"UChar")
  6625. NumPut(numb64, ptrBuff + 0 , mBufferPos++, "UChar")
  6626.  
  6627. numb64 := NumGet(ptr64 + 0, (triple >> 1 * 6) & 0x3F,"UChar")
  6628. NumPut(numb64, ptrBuff + 0 , mBufferPos++, "UChar")
  6629.  
  6630. numb64 := NumGet(ptr64 + 0, (triple >> 0 * 6) & 0x3F,"UChar")
  6631. NumPut(numb64, ptrBuff + 0 , mBufferPos++, "UChar")
  6632.  
  6633. ; add padding '='
  6634. sizeMod := Mod(size , 3)
  6635. ; last character is definitely padded
  6636. ; for some unknow reason it is needed to set the byte postition at - 2 before -1
  6637. ; the last postiion set seems to somehow stop the output from reading anyafter the
  6638. ; last NumPut position
  6639. if (sizeMod = 1)
  6640. {
  6641. NumPut(61, ptrBuff + 0 , mBufferPos - 2, "UChar")
  6642.  
  6643. }
  6644. NumPut(61, ptrBuff + 0 , mBufferPos - 1, "UChar") ; put = sign byte
  6645. }
  6646. buffer.Pos := mBufferPos + buffer.m_BytesPerChar
  6647. return buffer
  6648. }
  6649. ; End:ToBase64 ;}
  6650. ;{ ToCharList
  6651. /*
  6652. Method: ToCharList()
  6653.  
  6654. ToCharList()
  6655. Gets a copy of the current instance as MfCharList
  6656. Parameters:
  6657. startIndex
  6658. Optional: The Char Index to start filling the return list with
  6659. length
  6660. Optional: The length of the retrun list
  6661. Returns:
  6662. Returns instance of MfCharList containing Numer Char valus
  6663. Throws:
  6664. Throws MfArgumentOutOfRangeException
  6665. */
  6666. ToCharList(startIndex=0, length=-1) {
  6667. BytesPerChar := this.m_BytesPerChar
  6668. startIndex := MfInteger.GetValue(startIndex, 0) * BytesPerChar
  6669. length := MfInteger.GetValue(length, -1)
  6670. littleEndian := mfbool.GetValue(littleEndian, false)
  6671. lst := new MfCharList(, this.m_Encoding)
  6672. if (this.Size = 0)
  6673. {
  6674. return lst
  6675. }
  6676.  
  6677. if ((StartIndex < 0) || (StartIndex >= this.Size))
  6678. {
  6679. ex := new MfArgumentOutOfRangeException("index", MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_Index"))
  6680. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  6681. throw ex
  6682. }
  6683. if (Length = 0)
  6684. {
  6685. return lst
  6686. }
  6687. if (Length < 0)
  6688. {
  6689. length := (this.Pos - BytesPerChar - startIndex) // BytesPerChar
  6690. }
  6691. length := length * BytesPerChar
  6692. if (((length) + startIndex) >= this.Size)
  6693. {
  6694. ex := new MfArgumentOutOfRangeException("length", MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_IndexCount"))
  6695. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  6696. throw ex
  6697. }
  6698. ptr := this[]
  6699. sType := lst.m_sType
  6700. i := startIndex
  6701. While (i < length)
  6702. {
  6703. lst._Add(NumGet(ptr + 0, i, sType))
  6704. i += BytesPerChar
  6705. }
  6706. return lst
  6707. }
  6708. ; End:ToCharList ;}
  6709. ;{ ToString
  6710. /*
  6711. Method: ToString()
  6712.  
  6713. ToString()
  6714. Gets the value of this instance as string var
  6715. Returns:
  6716. Returns string var
  6717. */
  6718. ToString() {
  6719. len := (this.Pos - this.m_BytesPerChar) // this.m_BytesPerChar
  6720. if (this.m_BytesPerChar <= 2)
  6721. {
  6722. ptr := this[]
  6723. return StrGet(ptr + 0, len, this.m_Encoding)
  6724. }
  6725. PI := this.Pos
  6726. methodName := "Read" . this.m_EncodingName
  6727. this.Seek(0, 0)
  6728. retval := this.__Call(methodName, len)
  6729. this.Pos := PI
  6730. return retval
  6731. }
  6732. ; End:ToString ;}
  6733.  
  6734. ;{ TrimBufferToPos
  6735. /*
  6736. Method: TrimBufferToPos()
  6737.  
  6738. TrimBufferToPos()
  6739. Trims the current size to the current Pos
  6740. Parameters:
  6741. Param1
  6742. Returns:
  6743. The current CharCount after trim
  6744. Remarks:
  6745. This[] address will be changed
  6746. */
  6747. TrimBufferToPos() {
  6748. if (this.Size = this.Pos)
  6749. {
  6750. return this.GetCharCount()
  6751. }
  6752.  
  6753. size := this.Pos
  6754. if (this.m_isAddr = false)
  6755. {
  6756. ; If ByteSize is less than the current size, excess data is truncated;
  6757. ; otherwise all existing data is preserved.
  6758. this.Size := ObjSetCapacity(this, "_Buffer", size)
  6759. this.__Ptr := ObjGetAddress(this, "_Buffer")
  6760. return this.GetCharCount()
  6761. }
  6762. this.m_isAddr := false
  6763. FB := this.m_FillBytes
  6764. nv := 0
  6765. sType := "UChar"
  6766. VarSetCapacity(nV, size , FB)
  6767. DllCall("RtlMoveMemory", "PTR", &nV, "PTR", this[], sType, size)
  6768.  
  6769. this.m_isAddr := false
  6770. ObjSetCapacity(this, "_Buffer", size)
  6771. this.__Ptr := ObjGetAddress(this, "_Buffer")
  6772. DllCall("RtlFillMemory", "PTR", this[], "PTR", size, "UCHAR", FB)
  6773. this.Size := this.GetCapacity("_Buffer")
  6774. DllCall("RtlMoveMemory", "PTR", this[], "PTR", &nV, sType, size)
  6775. VarSetCapacity(nV, 0)
  6776. return this.GetCharCount()
  6777. }
  6778. ; End:TrimBufferToPos ;}
  6779. ;{ TrimStart
  6780. /*
  6781. Method: TrimStart()
  6782.  
  6783. TrimStart()
  6784. Trims all whitespace char from start of current instance
  6785. Returns:
  6786. Returns the count of the number of chars trimed from the start
  6787. */
  6788. TrimStart() {
  6789.  
  6790. BytesPerChar := this.m_BytesPerChar
  6791. sType := this.m_sType
  6792. len := this.Pos
  6793. Address := this[]
  6794. i := 0
  6795. while (i < len)
  6796. {
  6797. num := NumGet(Address + 0, i, sType)
  6798. if (MfMemStrView.IsWhiteSpace(num) = false)
  6799. {
  6800. break
  6801. }
  6802. i += BytesPerChar
  6803. }
  6804. if (i = 0)
  6805. {
  6806. return 0
  6807. }
  6808.  
  6809. this.MoveBytesLeft(0,i)
  6810.  
  6811. result := i // BytesPerChar
  6812. return result
  6813. }
  6814. ; End:TrimStart ;}
  6815. ;{ TrimStartChars
  6816. /*
  6817. Method: TrimStartChars()
  6818.  
  6819. TrimStartChars()
  6820. Trims char(s) from the start of a string
  6821. Parameters:
  6822. strChars
  6823. A string var containing one or more chars to trim from the start of current instance
  6824. IgnoreCase
  6825. If true case is ignored for trim chars; Otherwise case is observed
  6826. Returns:
  6827. Returns the count of the number of chars trimed from the start
  6828. */
  6829. TrimStartChars(strChars, IgnoreCase=true) {
  6830. if (strChars == "")
  6831. {
  6832. return 0
  6833. }
  6834. chars := MfMemStrView._GetCharArray(strChars, IgnoreCase)
  6835.  
  6836. BytesPerChar := this.m_BytesPerChar
  6837. sType := this.m_sType
  6838. len := this.Pos
  6839. Address := this[]
  6840. i := 0
  6841. while (i < len)
  6842. {
  6843. num := NumGet(Address + 0, i, sType)
  6844. if (!MfMemStrView._indexOfArr(chars, num))
  6845. {
  6846. break
  6847. }
  6848. i += BytesPerChar
  6849. }
  6850. if (i = 0)
  6851. {
  6852. return 0
  6853. }
  6854. this.MoveBytesLeft(0, i)
  6855. result := i // BytesPerChar
  6856. return result
  6857. }
  6858. ; End:TrimStartChars ;}
  6859. ;{ TrimEnd
  6860. /*
  6861. Method: TrimEnd()
  6862.  
  6863. TrimEnd()
  6864. Trims all whitespace char from end of current instance
  6865. Returns:
  6866. Returns the count of the number of chars trimed from the end
  6867. */
  6868. TrimEnd() {
  6869. BytesPerChar := this.m_BytesPerChar
  6870. sType := this.m_sType
  6871. PI := this.Pos
  6872. Address := this[]
  6873. i := PI - (BytesPerChar * 2) ; minus 1 for zero based
  6874. if ( i < 0)
  6875. {
  6876. return 0
  6877. }
  6878. iCount := 0
  6879. while (i >= 0)
  6880. {
  6881. num := NumGet(Address + 0, i, sType)
  6882. if (MfMemStrView.IsWhiteSpace(num) = false)
  6883. {
  6884. break
  6885. }
  6886. i -= BytesPerChar
  6887. iCount ++
  6888. }
  6889. if (iCount = 0)
  6890. {
  6891. return 0
  6892. }
  6893.  
  6894. this.TrimMemoryRight(iCount)
  6895. result := iCount
  6896. return result
  6897. }
  6898. ; End:TrimEnd ;}
  6899. ;{ TrimEndChars
  6900. /*
  6901. Method: TrimStartChars()
  6902.  
  6903. TrimStartChars()
  6904. Trims char(s) from the end of a string
  6905. Parameters:
  6906. strChars
  6907. A string var containing one or more chars to trim from the end of current instance
  6908. IgnoreCase
  6909. If true case is ignored for trim chars; Otherwise case is observed
  6910. Returns:
  6911. Returns the count of the number of chars trimed from the end
  6912. */
  6913. TrimEndChars(strChars, IgnoreCase=true) {
  6914. if (strChars == "")
  6915. {
  6916. return 0
  6917. }
  6918. chars := MfMemStrView._GetCharArray(strChars, IgnoreCase)
  6919.  
  6920. BytesPerChar := this.m_BytesPerChar
  6921. sType := this.m_sType
  6922. PI := this.Pos
  6923. Address := this[]
  6924. i := PI - (BytesPerChar * 2) ; minus 1 for zero based
  6925. if ( i < 0)
  6926. {
  6927. return 0
  6928. }
  6929. iCount := 0
  6930. while (i >= 0)
  6931. {
  6932. num := NumGet(Address + 0, i, sType)
  6933. if (!MfMemStrView._indexOfArr(chars, num))
  6934. {
  6935. break
  6936. }
  6937. i -= BytesPerChar
  6938. iCount ++
  6939. }
  6940. if (iCount = 0)
  6941. {
  6942. return 0
  6943. }
  6944. this.TrimMemoryRight(iCount)
  6945. result := iCount
  6946. return result
  6947. }
  6948. ; End:TrimEndChars ;}
  6949. ;{ TrimMemoryRight
  6950. /*
  6951. Method: TrimMemoryRight()
  6952.  
  6953. TrimMemoryRight()
  6954. Overwrites memory bytes with fillbytes for the end of a string, Erases end of a string
  6955. Parameters:
  6956. Length
  6957. The number of chars to erase from the end this instance
  6958. */
  6959. TrimMemoryRight(Length) {
  6960. BytesPerChar := this.m_BytesPerChar
  6961. PI := this.Pos
  6962. NewPos := this.Pos - (Length * BytesPerChar)
  6963. this.Seek(NewPos - BytesPerChar)
  6964. strType := this.m_sType
  6965. methodPut := "Put" . strType
  6966. while (this.Pos < PI)
  6967. {
  6968. this.__Call(methodPut,this.m_FillBytes)
  6969. }
  6970. this.Seek(NewPos)
  6971.  
  6972. }
  6973. ; End:TrimMemoryRight ;}
  6974. ;{ StringsAreEqual
  6975. /*
  6976. Method: StringsAreEqual()
  6977.  
  6978. StringsAreEqual()
  6979. Binary comparsion of string in memory
  6980. Parameters:
  6981. FirstStrAddr
  6982. The memory address of the frist string to compare
  6983. FirstStrLen
  6984. The length of the frist string to compare
  6985. SecondStrAddr
  6986. The memory address of the secnod string to compare
  6987. SecondStrLen
  6988. The length of the frist string to compare
  6989. encoding
  6990. The encoding of the string in memory
  6991. IgnoreCase
  6992. Boolean value indicating if case should be ignored
  6993. Returns:
  6994. Boolean true if string are equal, Otherwise False
  6995. Remarks:
  6996. Because Memory addresses and length are being compared this method could alus be used to to compare
  6997. substring of memory strings. See EqualsSubString as an example
  6998. Static Method
  6999. */
  7000. StringsAreEqual(FirstStrAddr, FirstStrLen, SecondStrAddr,SecondStrLen, encoding, IgnoreCase=true) {
  7001. if (FirstStrAddr = SecondStrAddr)
  7002. {
  7003. return true
  7004. }
  7005. If (FirstStrLen <> SecondStrLen)
  7006. {
  7007. Return false
  7008. }
  7009. retval := true
  7010. BytesPerChar := MfMemStrView.GetBytesPerChar(encoding)
  7011. sType := "UChar"
  7012. if (BytesPerChar = 2)
  7013. {
  7014. sType := "UShort"
  7015. }
  7016. else if (BytesPerChar = 4)
  7017. {
  7018. sType := "UInt"
  7019. }
  7020. i := 0
  7021. len := FirstStrLen * BytesPerChar
  7022. if (IgnoreCase)
  7023. {
  7024. while (i < len)
  7025. {
  7026. num1 := NumGet(FirstStrAddr + 0, i, sType)
  7027. num2:= NumGet(SecondStrAddr + 0, i, sType)
  7028. if (num1 != num2)
  7029. {
  7030. retval := false
  7031. break
  7032. }
  7033. i += BytesPerChar
  7034. }
  7035. }
  7036. else
  7037. {
  7038. while (i < len)
  7039. {
  7040. num1 := NumGet(FirstStrAddr + 0, i, sType)
  7041. num2:= NumGet(SecondStrAddr + 0, i, sType)
  7042. if (num1 != num2)
  7043. {
  7044. If (MfMemStrView._IsLatin1(num1) && MfMemStrView._IsLatin1(num2))
  7045. {
  7046. if (MfMemStrView._IsEqualLatin1IgnoreCase(num1, num2))
  7047. {
  7048. i += BytesPerChar
  7049. continue
  7050. }
  7051. }
  7052. else
  7053. {
  7054. char1 := Chr(num1)
  7055. char2 := Chr(num2)
  7056. ; compare as case in-sensitive
  7057. if (char1 = Char2)
  7058. {
  7059. i += BytesPerChar
  7060. continue
  7061. }
  7062. }
  7063.  
  7064. retval := false
  7065. break
  7066. }
  7067. i += BytesPerChar
  7068. }
  7069.  
  7070. }
  7071. Return retval
  7072. }
  7073. ; End:StringsAreEqual ;}
  7074. ;{ SubSet
  7075. /*
  7076. Method: SubSet()
  7077.  
  7078. SubSet()
  7079. Gets a sub set (sub string) of the currrent instance chars
  7080. Parameters:
  7081. StartIndex
  7082. The start index in Byte Position
  7083. Length
  7084. The length of the subset in Bytes
  7085. Returns:
  7086. Returns new instance of MfMemStrView
  7087. Throws:
  7088. Throws MfArgumentOutOfRangeException if startIndex or Length is out or range
  7089. Throws MfArgumentException
  7090. */
  7091. SubSet(StartIndex, Length=-1) {
  7092. if (StartIndex < 0)
  7093. {
  7094. ex := new MfArgumentOutOfRangeException("StartIndex", MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_IndexString"))
  7095. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  7096. throw ex
  7097. }
  7098.  
  7099. if (Length < 0)
  7100. {
  7101. Length := ((this.Pos - this.m_BytesPerChar) - StartIndex)
  7102. }
  7103.  
  7104.  
  7105. if ((StartIndex + Length) > (this.Pos - this.m_BytesPerChar))
  7106. {
  7107. ex := new MfArgumentException(MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_IndexLength"))
  7108. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  7109. throw ex
  7110. }
  7111.  
  7112. PI := this.Pos
  7113. try
  7114. {
  7115. this.seek(StartIndex)
  7116. ;size := (Length - StartIndex) + (this.m_BytesPerChar * 2)
  7117.  
  7118. objMemBlk := new MfMemStrView(Length + this.m_BytesPerChar, this.m_FillBytes, this.m_Encoding)
  7119. newAddress := objMemBlk[]
  7120. Address := this[] + this.Pos
  7121. DllCall("RtlMoveMemory", "PTR", newAddress + 0, "PTR", Address + 0, "UCHAR", Length)
  7122. objMemBlk.Size := ObjGetCapacity(objMemBlk, "_Buffer")
  7123. objMemBlk.Pos := Length + this.m_BytesPerChar
  7124. return objMemBlk
  7125. }
  7126. catch e
  7127. {
  7128. ex := new MfException(MfEnvironment.Instance.GetResourceString("Exception_Error", A_ThisFunc), e)
  7129. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  7130. throw ex
  7131. }
  7132. finally
  7133. {
  7134. this.Pos := PI
  7135. }
  7136. }
  7137. ; End:SubSet ;}
  7138.  
  7139. ;{ _GetCharArray
  7140. /*
  7141. Method: _GetCharArray()
  7142.  
  7143. _GetCharArray()
  7144. Builds a one base array from strChars adding each character only once as a char number
  7145. Parameters:
  7146. strChars
  7147. The source string to build array from
  7148. IgnoreCase
  7149. Boolean value indicating if case should be ignored
  7150. Returns:
  7151. Returns one based array of chars numbers representing the chars in strChars
  7152. Remarks:
  7153. if IgnoreCase is false then each char in strChars will be added as upper case and lower case if the char
  7154. has a corresponding case
  7155. */
  7156. _GetCharArray(strChars, IgnoreCase=true) {
  7157.  
  7158. tc := []
  7159. i := 1
  7160. Loop, Parse, strChars
  7161. {
  7162. if (IgnoreCase = true)
  7163. {
  7164. char := Asc(A_LoopField)
  7165. if (MfMemStrView._indexOfArr(tc, char))
  7166. {
  7167. continue
  7168. }
  7169.  
  7170. tc[i] := char
  7171. i++
  7172. }
  7173. else
  7174. {
  7175. StringLower, LC, A_LoopField
  7176. char := Asc(LC)
  7177. if (MfMemStrView._indexOfArr(tc, char))
  7178. {
  7179. continue
  7180. }
  7181. tc[i] := char
  7182. i++
  7183. ; some chars are the same upper and lower case
  7184. StringUpper, UC, A_LoopField
  7185. charU := Asc(UC)
  7186. if (CharU != char)
  7187. {
  7188. tc[i] := CharU
  7189. i++
  7190. }
  7191. }
  7192. }
  7193. return tc
  7194. }
  7195. ; End:_GetCharArray ;}
  7196. ;{ _indexOfArr
  7197. /*
  7198. Method: _indexOfArr()
  7199.  
  7200. _indexOfArr()
  7201. Search a one based array to see if contains var value
  7202. Parameters:
  7203. Arr
  7204. Array to search
  7205. var
  7206. Value to search for
  7207. fromIndex
  7208. The one based index to start searching from. Defauult is 1
  7209. Returns:
  7210. Returns the index in the array if var is found otherwise false
  7211. */
  7212. _indexOfArr(ByRef Arr, var, fromIndex:=1) {
  7213. for index, value in Arr {
  7214. if (index < fromIndex)
  7215. Continue
  7216. else if (value = var)
  7217. return index
  7218. }
  7219. return false
  7220. }
  7221. ; End:_indexOfArr ;}
  7222.  
  7223. ;{ _IsEqualLatin1IgnoreCase
  7224. ; static method
  7225. ; Checkes if char1 and Char2 are equal when case is ignored
  7226. ; applies only to Lattin1 chars
  7227. _IsEqualLatin1IgnoreCase(char1, char2) {
  7228. If (Char1 = Char2)
  7229. {
  7230. return true
  7231. }
  7232. if (MfMemStrView._IsAsciiLetter(Char1) && MfMemStrView._IsAsciiLetter(Char2))
  7233. {
  7234. up1 := MfMemStrView._AsciiToUpper(Char1)
  7235. up2 := MfMemStrView._AsciiToUpper(Char2)
  7236. return up1 = up2
  7237. }
  7238. Return false
  7239. }
  7240. ; End:_IsEqualLatin1IgnoreCase ;}
  7241. ;{ _AsciiToUpper
  7242. ; statice method
  7243. ; Converts ascii lower case char to upper case char
  7244. _AsciiToUpper(cc) {
  7245. if (MfMemStrView._IsAsciiLower(cc))
  7246. {
  7247. return cc - 32
  7248. }
  7249. return cc
  7250. }
  7251. ; End:_AsciiToUpper ;}
  7252. ;{ _AsciiToLower
  7253. ; statice method
  7254. ; Converts ascii Upper case char to lower case char
  7255. _AsciiToLower(cc) {
  7256. if (MfMemStrView._IsAsciiUpper(cc))
  7257. {
  7258. return cc + 32
  7259. }
  7260. return cc
  7261. }
  7262. ; End:_AsciiToLower ;}
  7263. ;{ _IsAsciiLetter
  7264. ; static method
  7265. ; check if cc is a ascii letter
  7266. _IsAsciiLetter(cc) {
  7267. IsUpper := MfMemStrView._IsAsciiUpper(cc)
  7268. If (IsUpper)
  7269. {
  7270. return true
  7271. }
  7272. IsLower := MfMemStrView._IsAsciiLower(cc)
  7273. return IsLower
  7274. }
  7275. ; End:_IsAsciiLetter ;}
  7276. ;{ _IsAsciiLower
  7277. ; static metohd
  7278. ; check to see if cc is a valid ascii lowercase char
  7279. _IsAsciiLower(cc) {
  7280. return ((cc >= 97) && (cc <= 122))
  7281. }
  7282. ; End:_IsAsciiLower ;}
  7283. ;{ _IsAsciiUpper
  7284. ; static metohd
  7285. ; check to see if cc is a valid ascii uppercase char
  7286. _IsAsciiUpper(cc) {
  7287. return ((cc >= 65) && (cc <= 90))
  7288. }
  7289. ; End:_IsAsciiUpper ;}
  7290. ;{ _IsAscII
  7291. ; Static method
  7292. ; checks to see if cc is a valid ascii char
  7293. _IsAscII(cc) {
  7294. return cc >=0 && c <= 127
  7295. }
  7296. ; End:_IsAscII ;}
  7297. ;{ _IsLatin1
  7298. ; static method
  7299. ; checks to see if cc is a valid Latin1 char
  7300. _IsLatin1(cc) {
  7301. return cc >=0 && c <= 255
  7302. }
  7303. ; End:_IsLatin1 ;}
  7304. ;{ _IsSeparatorLatin1
  7305. ; static method
  7306. ; checks ot see if cc is a Latin1 separator char
  7307. _IsSeparatorLatin1(cc) {
  7308. return ((cc = 32 ) || (cc = 160))
  7309. }
  7310. ; End:_IsSeparatorLatin1 ;}
  7311. ;{ _IsDigitLatin1
  7312. ; static method
  7313. ; checks ot see if cc is a valid Latin1 digit
  7314. _IsDigitLatin1(cc) {
  7315. retur ((cc >= 48 ) && (cc <= 57))
  7316. }
  7317. ; End:_IsDigitLatin1 ;}
  7318.  
  7319. ;{ __Delete
  7320. ; clean up when instance is destroyed
  7321. __Delete() {
  7322. if (!this.m_isAddr)
  7323. ObjSetCapacity(this, "_Buffer", 0)
  7324. }
  7325. ; End:__Delete ;}
  7326.  
  7327. ;{ _NewEnum
  7328. /*
  7329. Method: _NewEnum()
  7330. Overrides MfEnumerableBase._NewEnum()
  7331. _NewEnum()
  7332. Returns a new enumerator to enumerate this object's key-value pairs.
  7333. This method is usually not called directly, but by the for-loop or by GetEnumerator()
  7334. */
  7335. _NewEnum() {
  7336. return new MfMemStrView.Enumerator(this)
  7337. }
  7338. ; End:_NewEnum ;}
  7339. ;{ internal class Enumerator
  7340. class Enumerator
  7341. {
  7342. m_Parent := ""
  7343. m_KeyEnum := ""
  7344. m_index := 0
  7345. m_count := 0
  7346. m_address := ""
  7347.  
  7348. __new(ByRef ParentClass) {
  7349. this.m_Parent := ParentClass
  7350. if (this.m_Parent.Pos > 0)
  7351. {
  7352. this.m_count := (this.m_Parent.Pos - this.m_Parent.m_BytesPerChar) // this.m_Parent.m_BytesPerChar
  7353. }
  7354. else
  7355. {
  7356. this.m_count := 0
  7357. }
  7358. this.m_address := this.m_Parent[]
  7359. }
  7360.  
  7361. Next(ByRef key, ByRef value)
  7362. {
  7363. if (this.m_index < this.m_count) {
  7364. key := this.m_index
  7365. i := key * this.m_Parent.m_BytesPerChar
  7366. value := NumGet(this.m_address + 0, i, this.m_Parent.m_sType)
  7367. }
  7368. this.m_index++
  7369. if (this.m_index > (this.m_count)) {
  7370. value := ""
  7371. return false
  7372. } else {
  7373. return true
  7374. }
  7375. }
  7376. }
  7377. ; End:class Enumerator ;}
  7378. }
  7379.  
  7380. /* Class: MfMemBlkView
  7381. * Provides an interface for reading data from and writing it to a buffer or
  7382. * memory address. API is similar to that of AutoHotkey's File object.
  7383. */
  7384. class MfMemBlkView
  7385. {
  7386. /* Constructor: __New
  7387. * Instantiates an object that respresents a view into a buffer.
  7388. * Syntax:
  7389. * oView := new MfMemBlkView( ByRef VarOrAddress [ , offset := 0, length ] )
  7390. * Parameter(s):
  7391. * oView [retval] - a MfMemBlkView object
  7392. * VarOrAddress [in, ByRef] - variable(initialized by VarSetCapacity)
  7393. * or a memory address
  7394. * offset [in, opt] - an offset, in bytes, which is added to
  7395. * 'VarOrAddress' for the new view object
  7396. * to reference. Defaults to 0 if omitted.
  7397. * length [in, opt] - length of the view, in bytes. This parameter
  7398. * is required when 'VarOrAddress' is a memory
  7399. * address, else, an exception is thrown.
  7400. * Remarks:
  7401. * An exception is thrown if the 'offset' and 'length' result in the
  7402. * specified view extending past the end of the buffer.
  7403. */
  7404. __New(ByRef VarOrAddr, offset:=0, length:="") {
  7405. this.__Ptr := (IsByRef(VarOrAddr) ? &VarOrAddr : VarOrAddr) + offset
  7406.  
  7407. if (length == "")
  7408. {
  7409. if (!IsByRef(VarOrAddr))
  7410. {
  7411. ex := new MfArgumentException(MfEnvironment.Instance.GetResourceString("Argument_Address", "length"),"length")
  7412. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  7413. throw ex
  7414. }
  7415. length := VarSetCapacity(VarOrAddr)
  7416. }
  7417. if (IsByRef(VarOrAddr) && ((offset + length) > VarSetCapacity(VarOrAddr)))
  7418. {
  7419. ex := new MfArgumentException(MfEnvironment.Instance.GetResourceString("Argument_Buffer_Overflow"),"length")
  7420. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  7421. throw ex
  7422. }
  7423.  
  7424. this.Size := (this[] + length) - this[]
  7425. this.Pos := 0
  7426.  
  7427. }
  7428. /* Property: Size
  7429. * Size of the view in bytes. This property is read-only
  7430. * Syntax:
  7431. * size := oView.Size
  7432. */
  7433.  
  7434. /* Property: Pos
  7435. * The current position of the view pointer, where 0 is the beginning of
  7436. * the view
  7437. * Syntax:
  7438. * pos := oView.Pos
  7439. */
  7440. __Get(key:="", args*) {
  7441. if !key || (key > 0 && key <= this.Size)
  7442. return this.__Ptr + Round(key)
  7443. }
  7444.  
  7445. __Call(name, args*) {
  7446. if (name = "Put" || name = "Get")
  7447. name .= "UPtr"
  7448. else if (name = "Read" || name = "Write")
  7449. name .= "CP0"
  7450.  
  7451. if (name ~= "i)^((Put|Get)(U?(Char|Short|Int|Ptr)|Double|Float|Int64)|(Read|Write)(UTF(8|16|32)|CP\d+))$")
  7452. {
  7453. static ObjPush := Func(A_AhkVersion<"2" ? "ObjInsert" : "ObjPush")
  7454.  
  7455. n := InStr("RW", SubStr(name, 1, 1)) ? InStr(name, "r") : 0
  7456. %ObjPush%(args, SubStr(name, 4 + n)) ; num type OR encoding
  7457. return this[n ? "_Str" : "_Num"](SubStr(name, 1, 3 + n), args*)
  7458. }
  7459. }
  7460. /* Method: Put[NumType]
  7461. * Store a number in binary format and advances the view pointer
  7462. * Syntax:
  7463. * oView.PutNumType( num [ , offset ] )
  7464. * Parameter(s):
  7465. * NumType - One of the following specified directly as part of
  7466. * the method name: UInt, Int, Int64, Short, UShort,
  7467. * Char, UChar, Double, Float, UPtr or Ptr. Defaults
  7468. * to 'UPtr' if omitted.
  7469. * num [in] - a number
  7470. * offset [in, opt] - the offset, in bytes, from the view's start point.
  7471. * If omitted, 'num' is written at the current position
  7472. * of the view pointer.
  7473. */
  7474.  
  7475. /* Method: Get[NumType]
  7476. * Reads a number from the view and advances the view pointer
  7477. * Syntax:
  7478. * num := oView.GetNumType()
  7479. * Parameter(s):
  7480. * num [retval] - a number
  7481. * NumType - same as that of .PutNumType()
  7482. * offset [in, opt] - the offset, in bytes, from the view's start point.
  7483. * If omitted, 'num' is read from the current position
  7484. * of the view pointer.
  7485. */
  7486. _Num(action, args*) {
  7487. static sizeof := { "Char":1, "Short":2, "Int":4, "Float":4, "Double":8, "Int64":8, "Ptr":A_PtrSize }
  7488. static ObjRemoveAt := Func(A_AhkVersion<"2" ? "ObjRemove" : "ObjRemoveAt")
  7489.  
  7490. ; Process args
  7491. if (action = "Put")
  7492. {
  7493. num := %ObjRemoveAt%(args, 1)
  7494. if (sizeof[ LTrim(num, "Uu") ])
  7495. {
  7496. mName := "Put" . num . "()"
  7497. ex := new MfArgumentException(MfEnvironment.Instance.GetResourceString("NotSupportedException_MethodOverload", mName), mName)
  7498. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  7499. throw ex
  7500. }
  7501. }
  7502. ptr := this[]
  7503. at := ObjHasKey(args, 1) && ((args[1]+0) != "") ? %ObjRemoveAt%(args, 1) : ptr + this.Pos
  7504. type := ObjHasKey(args, 1) && sizeof[LTrim(args[1], "Uu")] ? args[1] : "UPtr"
  7505.  
  7506. if (at != (ptr + this.Pos)) && (at >= 0 && at < this.Size) ; offset
  7507. at += ptr
  7508.  
  7509. if (action = "Put")
  7510. return (n := NumPut(num, at + 0, type), this.Pos := n-ptr, n) ; rightmost for v2.0-a
  7511.  
  7512. this.Seek(sizeof[ LTrim(type, "Uu") ], 1)
  7513. return NumGet(at + 0, type)
  7514. }
  7515. /* Method: Write[Encoding]
  7516. * Copies a string into the view and advances the view pointer
  7517. * Syntax:
  7518. * chars := oView.WriteEncoding( str [ , length ] )
  7519. * Parameter(s):
  7520. * Encoding - source/target encoding in the following format:
  7521. * 'CPnnn' or 'UTFn' specified directly as part of
  7522. * the method name. Defaults to 'CP0' if omitted.
  7523. * chars [retval] - the number of characters written
  7524. * str [in] - a string
  7525. * length [in, opt] - Similar to StrPut()'s 'Length' parameter.
  7526. */
  7527.  
  7528. /* Method: Read[Encoding]
  7529. * Copies a string from the view and advances the view pointer
  7530. * Syntax:
  7531. * str := oView.ReadEncoding( [ length ] )
  7532. * Parameter(s):
  7533. * Encoding - same as that of .Write[Encoding]()
  7534. * str [retval] - the requested string after performing any necessary
  7535. * conversion
  7536. * length [in, opt] - Similar to StrGet()'s 'Length' parameter.
  7537. */
  7538. _Str(action, args*) {
  7539. enc := "CP0" ; default encoding
  7540. for i, arg in args
  7541. {
  7542. if (arg ~= "i)^UTF-?(8|16|32)|CP\d+$")
  7543. {
  7544. if InStr(enc := arg, "UTF")
  7545. args[i] := enc := "UTF-" . Abs(SubStr(enc, 4)) ; normalizes if it contains a dash
  7546. break
  7547. }
  7548. }
  7549. static ObjRemoveAt := Func(A_AhkVersion<"2" ? "ObjRemove" : "ObjRemoveAt")
  7550. addr := this[] + this.Pos
  7551.  
  7552. BytesPerChar := 1
  7553. if (enc = "UTF-32")
  7554. {
  7555. BytesPerChar := 4
  7556. if (action = "Read")
  7557. {
  7558. str := ""
  7559. len := args[1]
  7560. i := 0
  7561.  
  7562. while (i < len)
  7563. {
  7564. num := NumGet(addr + 0, i * BytesPerChar, "UInt")
  7565. str .= chr(num)
  7566. i++
  7567. }
  7568. return str
  7569. }
  7570. else
  7571. {
  7572. str := %ObjRemoveAt%(args, 1)
  7573. i := this.Pos
  7574. loop, Parse, str
  7575. {
  7576. NumPut(asc(A_LoopField), addr + 0, i, "UInt")
  7577. i += BytesPerChar
  7578.  
  7579. }
  7580. this.Pos := i
  7581. return (this.Pos + BytesPerChar) // BytesPerChar
  7582. }
  7583.  
  7584. }
  7585. str := action="Read" ? StrGet(addr, args*) : %ObjRemoveAt%(args, 1)
  7586. if (enc = "UTF-16" || Encoding = "CP1200")
  7587. {
  7588. BytesPerChar := 2
  7589. }
  7590.  
  7591. this.Seek(StrPut(str, enc) * BytesPerChar, 1)
  7592.  
  7593. return action="Read" ? str : StrPut(str, addr, args*)
  7594. }
  7595. /* Method: RawRead
  7596. * Copies raw binary data from the the view into the specified buffer
  7597. * or memory address. Data is read from the current position of the view
  7598. * pointer.
  7599. * Syntax:
  7600. * BytesRead := oView.RawRead( ByRef VarOrAddress, bytes )
  7601. * Parameter(s):
  7602. * BytesRead [retval] - number of bytes that were read
  7603. * VarOrAddress [in, ByRef] - variable or memory address to which the
  7604. * data will be copied
  7605. * bytes [in] - maximum number of bytes to read
  7606. */
  7607. RawRead(ByRef dest, bytes) {
  7608. if ((this.Pos + bytes) > this.Size) ; exceeds view's capacity
  7609. bytes := this.Size - this.Pos
  7610. if IsByRef(dest) && (!VarSetCapacity(dest) || (VarSetCapacity(dest) < bytes))
  7611. {
  7612. if (bytes < (A_IsUnicode ? 6 : 3)) ; minimum allowed is 3 TCHARS
  7613. VarSetCapacity(dest, 128), VarSetCapacity(dest, 0) ; force ALLOC_MALLOC method
  7614. VarSetCapacity(dest, bytes, 0) ; initialize or adjust if capacity is 0 or < bytes
  7615. }
  7616. DllCall("RtlMoveMemory", "PTR", IsByRef(dest) ? &dest : dest, "PTR", this[] + this.Pos, "UPtr", bytes)
  7617. return bytes
  7618. }
  7619. /* Method: RawWrite
  7620. * Write raw binary data into the view. Data is written at the current
  7621. * position of the view pointer.
  7622. * Syntax:
  7623. * BytesWritten := oView.RawWrite( ByRef VarOrAddress, bytes )
  7624. * Parameter(s):
  7625. * BytesWritten [retval] - number of bytes that were written
  7626. * VarOrAddress [in, ByRef] - variable containing the data or the
  7627. * address of the data in memory
  7628. * bytes [in] - maximum number of bytes to write
  7629. */
  7630. RawWrite(ByRef src, bytes) {
  7631. if ((this.Pos + bytes) > this.Size)
  7632. bytes := this.Size - this.Pos
  7633. DllCall("RtlMoveMemory", "PTR", this[] + this.Pos, "PTR", IsByRef(src) ? &src : src, "UPtr", bytes)
  7634. return bytes
  7635. }
  7636. /* Method: Seek
  7637. * Moves the view pointer
  7638. * Syntax:
  7639. * oView.Seek( distance [ , origin := 0 ] )
  7640. * Parameter(s):
  7641. * distance [in] - distance to move, in bytes.
  7642. * origin [in, opt] - starting point for the view pointer move. Must
  7643. * be one of the following:
  7644. * 0 - beginning of the view
  7645. * 1 - current position of the pointer
  7646. * 2 - end of the view, 'distance' should usually
  7647. * be negative
  7648. * If ommitted, 'origin' defaults to 2 if 'distance'
  7649. * is negative and 0 otherwise.
  7650. */
  7651. Seek(distance, origin:=0) {
  7652. if (distance < 0 && origin != 2)
  7653. origin := 2
  7654. start := origin == 0 ? this[] ; start
  7655. : origin == 1 ? this[] + this.Pos ; current
  7656. : origin == 2 ? this[] + this.Size ; end
  7657. : 0
  7658. return start ? this.Pos := start + distance - this[] : 0
  7659. }
  7660. ;{ FromArray
  7661. /*
  7662. Method: FromArray()
  7663.  
  7664. FromArray()
  7665. Creates new isntance of MfMemBlkView from AutoHotkey one based byte array
  7666. Parameters:
  7667. objArray
  7668. The array containing the bytes
  7669. startIndex
  7670. The zero based index to start read bytes from with the array.
  7671. Default value is zero
  7672. length
  7673. The lengt of byte to read from startIndex forward in the array.
  7674. The default value is -1
  7675. Values less then 0 will read all array bytes from startIndex forward
  7676. Returns:
  7677. Returns MfMemBlkView instance
  7678. Throws:
  7679. Throws MfArgumentNullException, MfArgumentOutOfRangeException
  7680. Remarks:
  7681. If FromArray
  7682. */
  7683. FromArray(byref objArray, startIndex=0, length=-1, sType="UChar") {
  7684. if (MfNull.IsNull(objArray))
  7685. {
  7686. ex := new MfArgumentNullException("ojbArray")
  7687. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  7688. throw ex
  7689. }
  7690. if (startIndex < 0)
  7691. {
  7692. ex := new MfArgumentOutOfRangeException("startIndex", MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_IndexString"))
  7693. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  7694. throw ex
  7695. }
  7696. if (length = 0)
  7697. {
  7698. ex := new MfArgumentException(MfEnvironment.Instance.GetResourceString("Arg_ArrayZeroError", "objArray"))
  7699. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  7700. throw ex
  7701. }
  7702. aLength := objArray.Length()
  7703. if (!aLength)
  7704. {
  7705. ex := new MfException(MfEnvironment.Instance.GetResourceString("Arg_ArrayTooSmall"))
  7706. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  7707. throw ex
  7708. }
  7709. if (length < 0)
  7710. {
  7711. length := (aLength - startIndex) + 1
  7712. }
  7713. if ((startIndex + length) - 1 > aLength)
  7714. {
  7715. ex := new MfArgumentException(MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_IndexLength"))
  7716. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  7717. throw ex
  7718. }
  7719. ; UInt, Int, Int64, Short, UShort, Char, UChar, Double, Float, Ptr or UPtr
  7720. step := 0
  7721. if (sType = "char" || stype = "uchar")
  7722. {
  7723. step := 1
  7724. }
  7725. else if (sType = "short" || stype = "ushort")
  7726. {
  7727. step := 2
  7728. }
  7729. else if (sType = "float" || stype = "int" || stype = "uint")
  7730. {
  7731. step := 4
  7732. }
  7733. else if (sType = "int64" || stype = "uint64" || stype = "Double")
  7734. {
  7735. step := 8
  7736. if (sType = "UInt64")
  7737. {
  7738. sType := "Int64"
  7739. }
  7740. }
  7741. else if (sType = "ptr" || stype = "uptr")
  7742. {
  7743. step := A_PtrSize
  7744. }
  7745. else
  7746. {
  7747. sType := "UChar"
  7748. step := 1
  7749. }
  7750.  
  7751. buff := 0
  7752. mv := new MfMemBlkView(&buff, 0, length)
  7753. addr := mv[]
  7754. i := 1
  7755. j := 0
  7756. while (i <= length)
  7757. {
  7758. NumPut(objArray[i], addr + 0, j , sType)
  7759. mv.Pos += step
  7760. j += step
  7761. i++
  7762. }
  7763. if (i > 1)
  7764. {
  7765. mv.Pos -= step
  7766. }
  7767. return mv
  7768. }
  7769. ; End:FromArray ;}
  7770. ;{ FromByteList
  7771. /*
  7772. Method: FromByteList()
  7773.  
  7774. FromByteList()
  7775. Converts MfByteList into MfMemStrView instance
  7776. Parameters:
  7777. bytes
  7778. instance of MfByteList containing byte values to convert
  7779. startIndex
  7780. The starting index in the MfByteList to start the conversion
  7781. Default value is 0
  7782. length
  7783. the length in bytes to convert.
  7784. Default value is -1
  7785. When length is less then 0 then all bytes past startIndex are included
  7786. littleEndian
  7787. Default value is true.
  7788. If true then byte order is considered to be reversed and the bytes are written into
  7789. memory from last byte to first after considering startIndex and length; Oterwise bytes
  7790. are written from start to end.
  7791. Returns:
  7792. Returns instance of MfMemBlkView
  7793. Throws:
  7794. Throws MfArgumentException, MfArgumentOutOfRangeException
  7795. Remarks:
  7796. Both startIndex and length operate the same no mater the state of littleEndian.
  7797. Static Method
  7798. */
  7799. FromByteList(bytes, startIndex=0, length=-1, littleEndian=true) {
  7800. if(MfObject.IsObjInstance(bytes, MfByteList) = false)
  7801. {
  7802. ex := new MfArgumentException(MfEnvironment.Instance.GetResourceString("Argument_Incorrect_List", "bytes"))
  7803. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  7804. throw ex
  7805. }
  7806. if(bytes.Count = 0)
  7807. {
  7808. ex := new MfArgumentException(MfEnvironment.Instance.GetResourceString("Arg_ArrayZeroError", "bytes"))
  7809. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  7810. throw ex
  7811. }
  7812. if(!littleEndian)
  7813. {
  7814. return MfMemBlkView.FromArray(bytes.m_InnerList, startIndex, length, "UChar")
  7815. }
  7816. if (startIndex < 0)
  7817. {
  7818. ex := new MfArgumentOutOfRangeException("startIndex", MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_IndexString"))
  7819. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  7820. throw ex
  7821. }
  7822. if (length = 0)
  7823. {
  7824. ex := new MfArgumentOutOfRangeException("length", MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_IndexString"))
  7825. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  7826. throw ex
  7827. }
  7828. aLength := bytes.Count
  7829.  
  7830. if (length < 0)
  7831. {
  7832. length := (aLength - startIndex) + 1
  7833. }
  7834. if ((startIndex + length) -1 > aLength)
  7835. {
  7836. ex := new MfArgumentException(MfEnvironment.Instance.GetResourceString("ArgumentOutOfRange_IndexLength"))
  7837. ex.SetProp(A_LineFile, A_LineNumber, A_ThisFunc)
  7838. throw ex
  7839. }
  7840. buff := 0
  7841. mv := new MfMemBlkView(&buff, 0, length)
  7842. addr := mv[]
  7843.  
  7844. objArray := bytes.m_InnerList
  7845. i := 1
  7846. j := bytes.Count
  7847. sType := "UChar"
  7848. while (i <= length)
  7849. {
  7850. NumPut(objArray[j], addr + 0, i -1 , sType)
  7851. mv.Pos++
  7852. i++
  7853. j--
  7854. }
  7855. if (i > 1 )
  7856. {
  7857. mv.Pos--
  7858. }
  7859. return mv
  7860. }
  7861. ; End:FromByteList ;}
  7862. ;{ ToArray
  7863. /*
  7864. Method: ToArray()
  7865.  
  7866. ToArray()
  7867. Creates an array of bytes from current instance of MfMemStrView
  7868. Parameters:
  7869. startIndex
  7870. The zero based index to start reading current instance bytes
  7871. length
  7872. The length in bytes to read from memory
  7873. Default value is -1
  7874. When value is -1 bytes are read from startIndex to current instanec pos
  7875. Returns:
  7876. Returns a one based AutoHotkey array
  7877. */
  7878. ToArray(startIndex=0, length=-1, sType="UChar") {
  7879. if ((StartIndex < 0) || (StartIndex >= this.pos))
  7880. {
  7881. return []
  7882. }
  7883. if (Length = 0)
  7884. {
  7885. return []
  7886. }
  7887. if (Length < 0)
  7888. {
  7889. length := this.Pos - startIndex
  7890. }
  7891. if (Length + startIndex > this.Pos)
  7892. {
  7893. return []
  7894. }
  7895. ; UInt, Int, Int64, Short, UShort, Char, UChar, Double, Float, Ptr or UPtr
  7896. step := 0
  7897. if (sType = "char" || stype = "uchar")
  7898. {
  7899. step := 1
  7900. }
  7901. else if (sType = "short" || stype = "ushort")
  7902. {
  7903. step := 2
  7904. }
  7905. else if (sType = "float" || stype = "int" || stype = "uint")
  7906. {
  7907. step := 4
  7908. }
  7909. else if (sType = "int64" || stype = "uint64" || stype = "double")
  7910. {
  7911. step := 8
  7912. if (sType = "UInt64")
  7913. {
  7914. sType := "Int64"
  7915. }
  7916. }
  7917. else if (sType = "ptr" || stype = "uptr")
  7918. {
  7919. step := A_PtrSize
  7920. }
  7921. else
  7922. {
  7923. sType := "UChar"
  7924. step := 1
  7925. }
  7926.  
  7927. ptr := this[]
  7928. a := []
  7929. maxIndex := length - 1
  7930. i := startIndex
  7931. j := 1
  7932.  
  7933. While (i <= maxIndex)
  7934. {
  7935. a[j] := NumGet(ptr + 0, i, sType)
  7936. i += step
  7937. j++
  7938. }
  7939. return a
  7940. }
  7941. ; End:ToArray ;}
  7942. ;{ ToByteList
  7943. /*
  7944. Method: ToByteList()
  7945.  
  7946. ToByteList()
  7947. Creates an MfByteList of bytes from current instance of MfMemStrView
  7948. Parameters:
  7949. startIndex
  7950. The zero based index to start reading current instance bytes
  7951. length
  7952. The length in bytes to read from memory
  7953. Default value is -1
  7954. When value is -1 bytes are read from startIndex to current instance pos
  7955. littleEndian
  7956. Default is true, If True byte order is in Little Endian;
  7957. Otherwise byte order is in Big Endian ( same as ToArray )
  7958. Returns:
  7959. Returns a zero based MfByteList
  7960. */
  7961. ToByteList(startIndex=0, length=-1, littleEndian=true) {
  7962. lst := new MfByteList()
  7963. if (!littleEndian)
  7964. {
  7965. a := this.ToArray(startIndex,length)
  7966. lst._SetInnerList(a, true)
  7967. return lst
  7968. }
  7969. if ((StartIndex < 0) || (StartIndex >= this.pos))
  7970. {
  7971. return lst
  7972. }
  7973. if (Length = 0)
  7974. {
  7975. return lst
  7976. }
  7977. if (Length < 0)
  7978. {
  7979. length := this.Pos - startIndex
  7980. }
  7981. if (Length + startIndex > this.Pos)
  7982. {
  7983. return lst
  7984. }
  7985. ptr := this[]
  7986. a := []
  7987. sType := "UChar"
  7988.  
  7989. i := startIndex + length -1
  7990. j := 1
  7991. While (j <= length)
  7992. {
  7993. a[j] := NumGet(ptr + 0, i, sType)
  7994. i--
  7995. j++
  7996. }
  7997. lst._SetInnerList(a, true)
  7998. return lst
  7999. }
  8000. ; End:ToByteList ;}
  8001.  
  8002. }
Add Comment
Please, Sign In to add comment