/src/lib/string/rope.e

http://github.com/tybor/Liberty · Specman e · 263 lines · 196 code · 29 blank · 38 comment · 13 complexity · 49ede04d68d23305d82b1330dcb932e6 MD5 · raw file

  1. -- This file is part of a Liberty Eiffel library.
  2. -- See the full copyright at the end.
  3. --
  4. class ROPE
  5. --
  6. -- A string of characters allowing for efficient concatenation.
  7. --
  8. -- See also LAZY_STRING, FIXED_STRING, and STRING
  9. --
  10. -- https://en.wikipedia.org/wiki/Rope_(data_structure)
  11. --|NOTE: this class works on the assumption that lower = 1 (see ABSTRACT_STRING invariant)
  12. inherit
  13. ABSTRACT_STRING
  14. redefine
  15. new_iterator, infix "<", out_in_tagged_out_memory
  16. end
  17. create {ANY}
  18. from_strings
  19. feature {ANY} -- Creation
  20. from_strings (left_string, right_string: ABSTRACT_STRING)
  21. require
  22. left_string /= Void
  23. right_string /= Void
  24. do
  25. left := left_string
  26. right := right_string
  27. end
  28. copy (another: like Current)
  29. do
  30. from_strings(another.left, another.right)
  31. end
  32. feature {ANY}
  33. count: INTEGER
  34. do
  35. Result := left.count + right.count
  36. end
  37. item (an_index: INTEGER): CHARACTER
  38. -- Random access is an O(count) operation for a ROPE.
  39. do
  40. if an_index <= split_index then
  41. Result := left.item(an_index)
  42. else
  43. Result := right.item(an_index - split_index)
  44. end
  45. end
  46. substring (start_index, end_index: INTEGER): like Current
  47. local
  48. left_substring, right_substring: ABSTRACT_STRING
  49. do
  50. if end_index <= split_index then
  51. left_substring := left.substring(start_index, end_index)
  52. right_substring := once ""
  53. elseif start_index > split_index then
  54. left_substring := once ""
  55. right_substring := right.substring(start_index - split_index, end_index - split_index)
  56. else
  57. left_substring := left.substring(start_index, split_index)
  58. right_substring := right.substring(1, end_index - split_index)
  59. end
  60. create Result.from_strings(left_substring, right_substring)
  61. end
  62. occurrences (c: CHARACTER): INTEGER
  63. do
  64. Result := left.occurrences(c) + right.occurrences(c)
  65. end
  66. feature {ANY}
  67. infix "<" (other: ABSTRACT_STRING): BOOLEAN
  68. local
  69. i: INTEGER; done: BOOLEAN
  70. do
  71. from
  72. i := lower
  73. check
  74. i = other.lower
  75. end
  76. until
  77. done or else i > upper or else i > other.upper
  78. loop
  79. if item(i) /= other.item(i) then
  80. Result := item(i) < other.item(i)
  81. done := True
  82. end
  83. i := i + 1
  84. end
  85. end
  86. is_equal (other: ABSTRACT_STRING): BOOLEAN
  87. -- O(min(count,other.count))
  88. do
  89. Result := same_as(other)
  90. end
  91. hash_code: INTEGER
  92. do
  93. Result := computed_hash_code
  94. end
  95. same_as (other: ABSTRACT_STRING): BOOLEAN
  96. -- O(min(count,other.count))
  97. local
  98. i: INTEGER
  99. do
  100. from
  101. i := lower
  102. check
  103. i = other.lower
  104. end
  105. Result := True
  106. until
  107. not Result or else i > upper or else i > other.upper
  108. loop
  109. Result := item(i) = other.item(i)
  110. i := i + 1
  111. end
  112. end
  113. first: CHARACTER
  114. do
  115. Result := left.first
  116. end
  117. last: CHARACTER
  118. do
  119. Result := right.last
  120. end
  121. has, fast_has (c: CHARACTER): BOOLEAN
  122. do
  123. Result := left.has(c) or else right.has(c)
  124. end
  125. index_of, fast_index_of (c: CHARACTER; start_index: INTEGER): INTEGER
  126. do
  127. if start_index > split_index then
  128. Result := right.index_of(c, start_index - split_index) + split_index
  129. else
  130. Result := left.index_of(c, start_index)
  131. if not left.valid_index(Result) then
  132. Result := right.index_of(c, right.lower) + split_index
  133. end
  134. end
  135. end
  136. reverse_index_of, fast_reverse_index_of (c: CHARACTER; start_index: INTEGER): INTEGER
  137. do
  138. if start_index <= split_index then
  139. Result := left.reverse_index_of(c, start_index)
  140. else
  141. Result := right.reverse_index_of(c, start_index - split_index)
  142. if right.valid_index(Result) then
  143. Result := Result + split_index
  144. else
  145. Result := left.reverse_index_of(c, left.upper)
  146. end
  147. end
  148. end
  149. out_in_tagged_out_memory
  150. do
  151. tagged_out_memory.append(left)
  152. tagged_out_memory.append(right)
  153. end
  154. fill_tagged_out_memory
  155. do
  156. tagged_out_memory.append(once "[left: ")
  157. left.fill_tagged_out_memory
  158. tagged_out_memory.append(once " | right: ")
  159. right.fill_tagged_out_memory
  160. tagged_out_memory.append(once "]")
  161. end
  162. feature {ANY} -- Concatenation
  163. infix "&" (another: ABSTRACT_STRING): ABSTRACT_STRING
  164. -- A newly allocated string containing Current and `another'
  165. -- concatenated. Implementation may choose any effective heir of
  166. -- ABSTRACT_STRING.
  167. do
  168. if another.is_empty then
  169. Result := Current
  170. elseif is_empty then
  171. Result := another
  172. elseif left.is_empty then
  173. Result := right | another
  174. elseif right.is_empty then
  175. Result := left | another
  176. else
  177. Result := Current | another
  178. end
  179. end
  180. feature {ANY} -- Iterating and other features
  181. new_iterator: ITERATOR[CHARACTER]
  182. do
  183. create {ITERATOR_ON_ROPE} Result.make(Current)
  184. end
  185. intern: FIXED_STRING
  186. do
  187. Result := out.intern
  188. end
  189. feature {ANY} -- Interfacing with C string:
  190. to_external: POINTER
  191. do
  192. Result := out.to_external
  193. end
  194. feature {ANY}
  195. recycle
  196. do
  197. left := once ""
  198. right := left
  199. end
  200. feature {ABSTRACT_STRING, ITERATOR_ON_ROPE} -- Implementation
  201. left, right: ABSTRACT_STRING
  202. -- The left and right parts of the ROPE
  203. feature {} -- Split index
  204. split_index: INTEGER
  205. -- The index where the rope is split. It corresponds to the length of the left part of the ROPE.
  206. do
  207. Result := left.upper
  208. ensure
  209. definition: Result = left.upper
  210. end
  211. invariant
  212. left /= Void
  213. right /= Void
  214. end -- class ROPE
  215. --
  216. -- Copyright (C) 2009-2017: by all the people cited in the AUTHORS file.
  217. --
  218. -- Permission is hereby granted, free of charge, to any person obtaining a copy
  219. -- of this software and associated documentation files (the "Software"), to deal
  220. -- in the Software without restriction, including without limitation the rights
  221. -- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  222. -- copies of the Software, and to permit persons to whom the Software is
  223. -- furnished to do so, subject to the following conditions:
  224. --
  225. -- The above copyright notice and this permission notice shall be included in
  226. -- all copies or substantial portions of the Software.
  227. --
  228. -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  229. -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  230. -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  231. -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  232. -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  233. -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  234. -- THE SOFTWARE.