iter.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457
  1. // Copyright 2011 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package norm
  5. import (
  6. "fmt"
  7. "unicode/utf8"
  8. )
  9. // MaxSegmentSize is the maximum size of a byte buffer needed to consider any
  10. // sequence of starter and non-starter runes for the purpose of normalization.
  11. const MaxSegmentSize = maxByteBufferSize
  12. // An Iter iterates over a string or byte slice, while normalizing it
  13. // to a given Form.
  14. type Iter struct {
  15. rb reorderBuffer
  16. buf [maxByteBufferSize]byte
  17. info Properties // first character saved from previous iteration
  18. next iterFunc // implementation of next depends on form
  19. asciiF iterFunc
  20. p int // current position in input source
  21. multiSeg []byte // remainder of multi-segment decomposition
  22. }
  23. type iterFunc func(*Iter) []byte
  24. // Init initializes i to iterate over src after normalizing it to Form f.
  25. func (i *Iter) Init(f Form, src []byte) {
  26. i.p = 0
  27. if len(src) == 0 {
  28. i.setDone()
  29. i.rb.nsrc = 0
  30. return
  31. }
  32. i.multiSeg = nil
  33. i.rb.init(f, src)
  34. i.next = i.rb.f.nextMain
  35. i.asciiF = nextASCIIBytes
  36. i.info = i.rb.f.info(i.rb.src, i.p)
  37. i.rb.ss.first(i.info)
  38. }
  39. // InitString initializes i to iterate over src after normalizing it to Form f.
  40. func (i *Iter) InitString(f Form, src string) {
  41. i.p = 0
  42. if len(src) == 0 {
  43. i.setDone()
  44. i.rb.nsrc = 0
  45. return
  46. }
  47. i.multiSeg = nil
  48. i.rb.initString(f, src)
  49. i.next = i.rb.f.nextMain
  50. i.asciiF = nextASCIIString
  51. i.info = i.rb.f.info(i.rb.src, i.p)
  52. i.rb.ss.first(i.info)
  53. }
  54. // Seek sets the segment to be returned by the next call to Next to start
  55. // at position p. It is the responsibility of the caller to set p to the
  56. // start of a segment.
  57. func (i *Iter) Seek(offset int64, whence int) (int64, error) {
  58. var abs int64
  59. switch whence {
  60. case 0:
  61. abs = offset
  62. case 1:
  63. abs = int64(i.p) + offset
  64. case 2:
  65. abs = int64(i.rb.nsrc) + offset
  66. default:
  67. return 0, fmt.Errorf("norm: invalid whence")
  68. }
  69. if abs < 0 {
  70. return 0, fmt.Errorf("norm: negative position")
  71. }
  72. if int(abs) >= i.rb.nsrc {
  73. i.setDone()
  74. return int64(i.p), nil
  75. }
  76. i.p = int(abs)
  77. i.multiSeg = nil
  78. i.next = i.rb.f.nextMain
  79. i.info = i.rb.f.info(i.rb.src, i.p)
  80. i.rb.ss.first(i.info)
  81. return abs, nil
  82. }
  83. // returnSlice returns a slice of the underlying input type as a byte slice.
  84. // If the underlying is of type []byte, it will simply return a slice.
  85. // If the underlying is of type string, it will copy the slice to the buffer
  86. // and return that.
  87. func (i *Iter) returnSlice(a, b int) []byte {
  88. if i.rb.src.bytes == nil {
  89. return i.buf[:copy(i.buf[:], i.rb.src.str[a:b])]
  90. }
  91. return i.rb.src.bytes[a:b]
  92. }
  93. // Pos returns the byte position at which the next call to Next will commence processing.
  94. func (i *Iter) Pos() int {
  95. return i.p
  96. }
  97. func (i *Iter) setDone() {
  98. i.next = nextDone
  99. i.p = i.rb.nsrc
  100. }
  101. // Done returns true if there is no more input to process.
  102. func (i *Iter) Done() bool {
  103. return i.p >= i.rb.nsrc
  104. }
  105. // Next returns f(i.input[i.Pos():n]), where n is a boundary of i.input.
  106. // For any input a and b for which f(a) == f(b), subsequent calls
  107. // to Next will return the same segments.
  108. // Modifying runes are grouped together with the preceding starter, if such a starter exists.
  109. // Although not guaranteed, n will typically be the smallest possible n.
  110. func (i *Iter) Next() []byte {
  111. return i.next(i)
  112. }
  113. func nextASCIIBytes(i *Iter) []byte {
  114. p := i.p + 1
  115. if p >= i.rb.nsrc {
  116. i.setDone()
  117. return i.rb.src.bytes[i.p:p]
  118. }
  119. if i.rb.src.bytes[p] < utf8.RuneSelf {
  120. p0 := i.p
  121. i.p = p
  122. return i.rb.src.bytes[p0:p]
  123. }
  124. i.info = i.rb.f.info(i.rb.src, i.p)
  125. i.next = i.rb.f.nextMain
  126. return i.next(i)
  127. }
  128. func nextASCIIString(i *Iter) []byte {
  129. p := i.p + 1
  130. if p >= i.rb.nsrc {
  131. i.buf[0] = i.rb.src.str[i.p]
  132. i.setDone()
  133. return i.buf[:1]
  134. }
  135. if i.rb.src.str[p] < utf8.RuneSelf {
  136. i.buf[0] = i.rb.src.str[i.p]
  137. i.p = p
  138. return i.buf[:1]
  139. }
  140. i.info = i.rb.f.info(i.rb.src, i.p)
  141. i.next = i.rb.f.nextMain
  142. return i.next(i)
  143. }
  144. func nextHangul(i *Iter) []byte {
  145. p := i.p
  146. next := p + hangulUTF8Size
  147. if next >= i.rb.nsrc {
  148. i.setDone()
  149. } else if i.rb.src.hangul(next) == 0 {
  150. i.rb.ss.next(i.info)
  151. i.info = i.rb.f.info(i.rb.src, i.p)
  152. i.next = i.rb.f.nextMain
  153. return i.next(i)
  154. }
  155. i.p = next
  156. return i.buf[:decomposeHangul(i.buf[:], i.rb.src.hangul(p))]
  157. }
  158. func nextDone(i *Iter) []byte {
  159. return nil
  160. }
  161. // nextMulti is used for iterating over multi-segment decompositions
  162. // for decomposing normal forms.
  163. func nextMulti(i *Iter) []byte {
  164. j := 0
  165. d := i.multiSeg
  166. // skip first rune
  167. for j = 1; j < len(d) && !utf8.RuneStart(d[j]); j++ {
  168. }
  169. for j < len(d) {
  170. info := i.rb.f.info(input{bytes: d}, j)
  171. if info.BoundaryBefore() {
  172. i.multiSeg = d[j:]
  173. return d[:j]
  174. }
  175. j += int(info.size)
  176. }
  177. // treat last segment as normal decomposition
  178. i.next = i.rb.f.nextMain
  179. return i.next(i)
  180. }
  181. // nextMultiNorm is used for iterating over multi-segment decompositions
  182. // for composing normal forms.
  183. func nextMultiNorm(i *Iter) []byte {
  184. j := 0
  185. d := i.multiSeg
  186. for j < len(d) {
  187. info := i.rb.f.info(input{bytes: d}, j)
  188. if info.BoundaryBefore() {
  189. i.rb.compose()
  190. seg := i.buf[:i.rb.flushCopy(i.buf[:])]
  191. i.rb.insertUnsafe(input{bytes: d}, j, info)
  192. i.multiSeg = d[j+int(info.size):]
  193. return seg
  194. }
  195. i.rb.insertUnsafe(input{bytes: d}, j, info)
  196. j += int(info.size)
  197. }
  198. i.multiSeg = nil
  199. i.next = nextComposed
  200. return doNormComposed(i)
  201. }
  202. // nextDecomposed is the implementation of Next for forms NFD and NFKD.
  203. func nextDecomposed(i *Iter) (next []byte) {
  204. outp := 0
  205. inCopyStart, outCopyStart := i.p, 0
  206. for {
  207. if sz := int(i.info.size); sz <= 1 {
  208. i.rb.ss = 0
  209. p := i.p
  210. i.p++ // ASCII or illegal byte. Either way, advance by 1.
  211. if i.p >= i.rb.nsrc {
  212. i.setDone()
  213. return i.returnSlice(p, i.p)
  214. } else if i.rb.src._byte(i.p) < utf8.RuneSelf {
  215. i.next = i.asciiF
  216. return i.returnSlice(p, i.p)
  217. }
  218. outp++
  219. } else if d := i.info.Decomposition(); d != nil {
  220. // Note: If leading CCC != 0, then len(d) == 2 and last is also non-zero.
  221. // Case 1: there is a leftover to copy. In this case the decomposition
  222. // must begin with a modifier and should always be appended.
  223. // Case 2: no leftover. Simply return d if followed by a ccc == 0 value.
  224. p := outp + len(d)
  225. if outp > 0 {
  226. i.rb.src.copySlice(i.buf[outCopyStart:], inCopyStart, i.p)
  227. // TODO: this condition should not be possible, but we leave it
  228. // in for defensive purposes.
  229. if p > len(i.buf) {
  230. return i.buf[:outp]
  231. }
  232. } else if i.info.multiSegment() {
  233. // outp must be 0 as multi-segment decompositions always
  234. // start a new segment.
  235. if i.multiSeg == nil {
  236. i.multiSeg = d
  237. i.next = nextMulti
  238. return nextMulti(i)
  239. }
  240. // We are in the last segment. Treat as normal decomposition.
  241. d = i.multiSeg
  242. i.multiSeg = nil
  243. p = len(d)
  244. }
  245. prevCC := i.info.tccc
  246. if i.p += sz; i.p >= i.rb.nsrc {
  247. i.setDone()
  248. i.info = Properties{} // Force BoundaryBefore to succeed.
  249. } else {
  250. i.info = i.rb.f.info(i.rb.src, i.p)
  251. }
  252. switch i.rb.ss.next(i.info) {
  253. case ssOverflow:
  254. i.next = nextCGJDecompose
  255. fallthrough
  256. case ssStarter:
  257. if outp > 0 {
  258. copy(i.buf[outp:], d)
  259. return i.buf[:p]
  260. }
  261. return d
  262. }
  263. copy(i.buf[outp:], d)
  264. outp = p
  265. inCopyStart, outCopyStart = i.p, outp
  266. if i.info.ccc < prevCC {
  267. goto doNorm
  268. }
  269. continue
  270. } else if r := i.rb.src.hangul(i.p); r != 0 {
  271. outp = decomposeHangul(i.buf[:], r)
  272. i.p += hangulUTF8Size
  273. inCopyStart, outCopyStart = i.p, outp
  274. if i.p >= i.rb.nsrc {
  275. i.setDone()
  276. break
  277. } else if i.rb.src.hangul(i.p) != 0 {
  278. i.next = nextHangul
  279. return i.buf[:outp]
  280. }
  281. } else {
  282. p := outp + sz
  283. if p > len(i.buf) {
  284. break
  285. }
  286. outp = p
  287. i.p += sz
  288. }
  289. if i.p >= i.rb.nsrc {
  290. i.setDone()
  291. break
  292. }
  293. prevCC := i.info.tccc
  294. i.info = i.rb.f.info(i.rb.src, i.p)
  295. if v := i.rb.ss.next(i.info); v == ssStarter {
  296. break
  297. } else if v == ssOverflow {
  298. i.next = nextCGJDecompose
  299. break
  300. }
  301. if i.info.ccc < prevCC {
  302. goto doNorm
  303. }
  304. }
  305. if outCopyStart == 0 {
  306. return i.returnSlice(inCopyStart, i.p)
  307. } else if inCopyStart < i.p {
  308. i.rb.src.copySlice(i.buf[outCopyStart:], inCopyStart, i.p)
  309. }
  310. return i.buf[:outp]
  311. doNorm:
  312. // Insert what we have decomposed so far in the reorderBuffer.
  313. // As we will only reorder, there will always be enough room.
  314. i.rb.src.copySlice(i.buf[outCopyStart:], inCopyStart, i.p)
  315. i.rb.insertDecomposed(i.buf[0:outp])
  316. return doNormDecomposed(i)
  317. }
  318. func doNormDecomposed(i *Iter) []byte {
  319. for {
  320. i.rb.insertUnsafe(i.rb.src, i.p, i.info)
  321. if i.p += int(i.info.size); i.p >= i.rb.nsrc {
  322. i.setDone()
  323. break
  324. }
  325. i.info = i.rb.f.info(i.rb.src, i.p)
  326. if i.info.ccc == 0 {
  327. break
  328. }
  329. if s := i.rb.ss.next(i.info); s == ssOverflow {
  330. i.next = nextCGJDecompose
  331. break
  332. }
  333. }
  334. // new segment or too many combining characters: exit normalization
  335. return i.buf[:i.rb.flushCopy(i.buf[:])]
  336. }
  337. func nextCGJDecompose(i *Iter) []byte {
  338. i.rb.ss = 0
  339. i.rb.insertCGJ()
  340. i.next = nextDecomposed
  341. i.rb.ss.first(i.info)
  342. buf := doNormDecomposed(i)
  343. return buf
  344. }
  345. // nextComposed is the implementation of Next for forms NFC and NFKC.
  346. func nextComposed(i *Iter) []byte {
  347. outp, startp := 0, i.p
  348. var prevCC uint8
  349. for {
  350. if !i.info.isYesC() {
  351. goto doNorm
  352. }
  353. prevCC = i.info.tccc
  354. sz := int(i.info.size)
  355. if sz == 0 {
  356. sz = 1 // illegal rune: copy byte-by-byte
  357. }
  358. p := outp + sz
  359. if p > len(i.buf) {
  360. break
  361. }
  362. outp = p
  363. i.p += sz
  364. if i.p >= i.rb.nsrc {
  365. i.setDone()
  366. break
  367. } else if i.rb.src._byte(i.p) < utf8.RuneSelf {
  368. i.rb.ss = 0
  369. i.next = i.asciiF
  370. break
  371. }
  372. i.info = i.rb.f.info(i.rb.src, i.p)
  373. if v := i.rb.ss.next(i.info); v == ssStarter {
  374. break
  375. } else if v == ssOverflow {
  376. i.next = nextCGJCompose
  377. break
  378. }
  379. if i.info.ccc < prevCC {
  380. goto doNorm
  381. }
  382. }
  383. return i.returnSlice(startp, i.p)
  384. doNorm:
  385. // reset to start position
  386. i.p = startp
  387. i.info = i.rb.f.info(i.rb.src, i.p)
  388. i.rb.ss.first(i.info)
  389. if i.info.multiSegment() {
  390. d := i.info.Decomposition()
  391. info := i.rb.f.info(input{bytes: d}, 0)
  392. i.rb.insertUnsafe(input{bytes: d}, 0, info)
  393. i.multiSeg = d[int(info.size):]
  394. i.next = nextMultiNorm
  395. return nextMultiNorm(i)
  396. }
  397. i.rb.ss.first(i.info)
  398. i.rb.insertUnsafe(i.rb.src, i.p, i.info)
  399. return doNormComposed(i)
  400. }
  401. func doNormComposed(i *Iter) []byte {
  402. // First rune should already be inserted.
  403. for {
  404. if i.p += int(i.info.size); i.p >= i.rb.nsrc {
  405. i.setDone()
  406. break
  407. }
  408. i.info = i.rb.f.info(i.rb.src, i.p)
  409. if s := i.rb.ss.next(i.info); s == ssStarter {
  410. break
  411. } else if s == ssOverflow {
  412. i.next = nextCGJCompose
  413. break
  414. }
  415. i.rb.insertUnsafe(i.rb.src, i.p, i.info)
  416. }
  417. i.rb.compose()
  418. seg := i.buf[:i.rb.flushCopy(i.buf[:])]
  419. return seg
  420. }
  421. func nextCGJCompose(i *Iter) []byte {
  422. i.rb.ss = 0 // instead of first
  423. i.rb.insertCGJ()
  424. i.next = nextComposed
  425. // Note that we treat any rune with nLeadingNonStarters > 0 as a non-starter,
  426. // even if they are not. This is particularly dubious for U+FF9E and UFF9A.
  427. // If we ever change that, insert a check here.
  428. i.rb.ss.first(i.info)
  429. i.rb.insertUnsafe(i.rb.src, i.p, i.info)
  430. return doNormComposed(i)
  431. }