OSDN Git Service

new repo
[bytom/vapor.git] / vendor / golang.org / x / text / cases / map.go
1 // Copyright 2014 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
5 package cases
6
7 // This file contains the definitions of case mappings for all supported
8 // languages. The rules for the language-specific tailorings were taken and
9 // modified from the CLDR transform definitions in common/transforms.
10
11 import (
12         "strings"
13         "unicode"
14         "unicode/utf8"
15
16         "golang.org/x/text/internal"
17         "golang.org/x/text/language"
18         "golang.org/x/text/transform"
19         "golang.org/x/text/unicode/norm"
20 )
21
22 // A mapFunc takes a context set to the current rune and writes the mapped
23 // version to the same context. It may advance the context to the next rune. It
24 // returns whether a checkpoint is possible: whether the pDst bytes written to
25 // dst so far won't need changing as we see more source bytes.
26 type mapFunc func(*context) bool
27
28 // A spanFunc takes a context set to the current rune and returns whether this
29 // rune would be altered when written to the output. It may advance the context
30 // to the next rune. It returns whether a checkpoint is possible.
31 type spanFunc func(*context) bool
32
33 // maxIgnorable defines the maximum number of ignorables to consider for
34 // lookahead operations.
35 const maxIgnorable = 30
36
37 // supported lists the language tags for which we have tailorings.
38 const supported = "und af az el lt nl tr"
39
40 func init() {
41         tags := []language.Tag{}
42         for _, s := range strings.Split(supported, " ") {
43                 tags = append(tags, language.MustParse(s))
44         }
45         matcher = internal.NewInheritanceMatcher(tags)
46         Supported = language.NewCoverage(tags)
47 }
48
49 var (
50         matcher *internal.InheritanceMatcher
51
52         Supported language.Coverage
53
54         // We keep the following lists separate, instead of having a single per-
55         // language struct, to give the compiler a chance to remove unused code.
56
57         // Some uppercase mappers are stateless, so we can precompute the
58         // Transformers and save a bit on runtime allocations.
59         upperFunc = []struct {
60                 upper mapFunc
61                 span  spanFunc
62         }{
63                 {nil, nil},                  // und
64                 {nil, nil},                  // af
65                 {aztrUpper(upper), isUpper}, // az
66                 {elUpper, noSpan},           // el
67                 {ltUpper(upper), noSpan},    // lt
68                 {nil, nil},                  // nl
69                 {aztrUpper(upper), isUpper}, // tr
70         }
71
72         undUpper            transform.SpanningTransformer = &undUpperCaser{}
73         undLower            transform.SpanningTransformer = &undLowerCaser{}
74         undLowerIgnoreSigma transform.SpanningTransformer = &undLowerIgnoreSigmaCaser{}
75
76         lowerFunc = []mapFunc{
77                 nil,       // und
78                 nil,       // af
79                 aztrLower, // az
80                 nil,       // el
81                 ltLower,   // lt
82                 nil,       // nl
83                 aztrLower, // tr
84         }
85
86         titleInfos = []struct {
87                 title     mapFunc
88                 lower     mapFunc
89                 titleSpan spanFunc
90                 rewrite   func(*context)
91         }{
92                 {title, lower, isTitle, nil},                // und
93                 {title, lower, isTitle, afnlRewrite},        // af
94                 {aztrUpper(title), aztrLower, isTitle, nil}, // az
95                 {title, lower, isTitle, nil},                // el
96                 {ltUpper(title), ltLower, noSpan, nil},      // lt
97                 {nlTitle, lower, nlTitleSpan, afnlRewrite},  // nl
98                 {aztrUpper(title), aztrLower, isTitle, nil}, // tr
99         }
100 )
101
102 func makeUpper(t language.Tag, o options) transform.SpanningTransformer {
103         _, i, _ := matcher.Match(t)
104         f := upperFunc[i].upper
105         if f == nil {
106                 return undUpper
107         }
108         return &simpleCaser{f: f, span: upperFunc[i].span}
109 }
110
111 func makeLower(t language.Tag, o options) transform.SpanningTransformer {
112         _, i, _ := matcher.Match(t)
113         f := lowerFunc[i]
114         if f == nil {
115                 if o.ignoreFinalSigma {
116                         return undLowerIgnoreSigma
117                 }
118                 return undLower
119         }
120         if o.ignoreFinalSigma {
121                 return &simpleCaser{f: f, span: isLower}
122         }
123         return &lowerCaser{
124                 first:   f,
125                 midWord: finalSigma(f),
126         }
127 }
128
129 func makeTitle(t language.Tag, o options) transform.SpanningTransformer {
130         _, i, _ := matcher.Match(t)
131         x := &titleInfos[i]
132         lower := x.lower
133         if o.noLower {
134                 lower = (*context).copy
135         } else if !o.ignoreFinalSigma {
136                 lower = finalSigma(lower)
137         }
138         return &titleCaser{
139                 title:     x.title,
140                 lower:     lower,
141                 titleSpan: x.titleSpan,
142                 rewrite:   x.rewrite,
143         }
144 }
145
146 func noSpan(c *context) bool {
147         c.err = transform.ErrEndOfSpan
148         return false
149 }
150
151 // TODO: consider a similar special case for the fast majority lower case. This
152 // is a bit more involved so will require some more precise benchmarking to
153 // justify it.
154
155 type undUpperCaser struct{ transform.NopResetter }
156
157 // undUpperCaser implements the Transformer interface for doing an upper case
158 // mapping for the root locale (und). It eliminates the need for an allocation
159 // as it prevents escaping by not using function pointers.
160 func (t undUpperCaser) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
161         c := context{dst: dst, src: src, atEOF: atEOF}
162         for c.next() {
163                 upper(&c)
164                 c.checkpoint()
165         }
166         return c.ret()
167 }
168
169 func (t undUpperCaser) Span(src []byte, atEOF bool) (n int, err error) {
170         c := context{src: src, atEOF: atEOF}
171         for c.next() && isUpper(&c) {
172                 c.checkpoint()
173         }
174         return c.retSpan()
175 }
176
177 // undLowerIgnoreSigmaCaser implements the Transformer interface for doing
178 // a lower case mapping for the root locale (und) ignoring final sigma
179 // handling. This casing algorithm is used in some performance-critical packages
180 // like secure/precis and x/net/http/idna, which warrants its special-casing.
181 type undLowerIgnoreSigmaCaser struct{ transform.NopResetter }
182
183 func (t undLowerIgnoreSigmaCaser) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
184         c := context{dst: dst, src: src, atEOF: atEOF}
185         for c.next() && lower(&c) {
186                 c.checkpoint()
187         }
188         return c.ret()
189
190 }
191
192 // Span implements a generic lower-casing. This is possible as isLower works
193 // for all lowercasing variants. All lowercase variants only vary in how they
194 // transform a non-lowercase letter. They will never change an already lowercase
195 // letter. In addition, there is no state.
196 func (t undLowerIgnoreSigmaCaser) Span(src []byte, atEOF bool) (n int, err error) {
197         c := context{src: src, atEOF: atEOF}
198         for c.next() && isLower(&c) {
199                 c.checkpoint()
200         }
201         return c.retSpan()
202 }
203
204 type simpleCaser struct {
205         context
206         f    mapFunc
207         span spanFunc
208 }
209
210 // simpleCaser implements the Transformer interface for doing a case operation
211 // on a rune-by-rune basis.
212 func (t *simpleCaser) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
213         c := context{dst: dst, src: src, atEOF: atEOF}
214         for c.next() && t.f(&c) {
215                 c.checkpoint()
216         }
217         return c.ret()
218 }
219
220 func (t *simpleCaser) Span(src []byte, atEOF bool) (n int, err error) {
221         c := context{src: src, atEOF: atEOF}
222         for c.next() && t.span(&c) {
223                 c.checkpoint()
224         }
225         return c.retSpan()
226 }
227
228 // undLowerCaser implements the Transformer interface for doing a lower case
229 // mapping for the root locale (und) ignoring final sigma handling. This casing
230 // algorithm is used in some performance-critical packages like secure/precis
231 // and x/net/http/idna, which warrants its special-casing.
232 type undLowerCaser struct{ transform.NopResetter }
233
234 func (t undLowerCaser) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
235         c := context{dst: dst, src: src, atEOF: atEOF}
236
237         for isInterWord := true; c.next(); {
238                 if isInterWord {
239                         if c.info.isCased() {
240                                 if !lower(&c) {
241                                         break
242                                 }
243                                 isInterWord = false
244                         } else if !c.copy() {
245                                 break
246                         }
247                 } else {
248                         if c.info.isNotCasedAndNotCaseIgnorable() {
249                                 if !c.copy() {
250                                         break
251                                 }
252                                 isInterWord = true
253                         } else if !c.hasPrefix("Σ") {
254                                 if !lower(&c) {
255                                         break
256                                 }
257                         } else if !finalSigmaBody(&c) {
258                                 break
259                         }
260                 }
261                 c.checkpoint()
262         }
263         return c.ret()
264 }
265
266 func (t undLowerCaser) Span(src []byte, atEOF bool) (n int, err error) {
267         c := context{src: src, atEOF: atEOF}
268         for c.next() && isLower(&c) {
269                 c.checkpoint()
270         }
271         return c.retSpan()
272 }
273
274 // lowerCaser implements the Transformer interface. The default Unicode lower
275 // casing requires different treatment for the first and subsequent characters
276 // of a word, most notably to handle the Greek final Sigma.
277 type lowerCaser struct {
278         undLowerIgnoreSigmaCaser
279
280         context
281
282         first, midWord mapFunc
283 }
284
285 func (t *lowerCaser) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
286         t.context = context{dst: dst, src: src, atEOF: atEOF}
287         c := &t.context
288
289         for isInterWord := true; c.next(); {
290                 if isInterWord {
291                         if c.info.isCased() {
292                                 if !t.first(c) {
293                                         break
294                                 }
295                                 isInterWord = false
296                         } else if !c.copy() {
297                                 break
298                         }
299                 } else {
300                         if c.info.isNotCasedAndNotCaseIgnorable() {
301                                 if !c.copy() {
302                                         break
303                                 }
304                                 isInterWord = true
305                         } else if !t.midWord(c) {
306                                 break
307                         }
308                 }
309                 c.checkpoint()
310         }
311         return c.ret()
312 }
313
314 // titleCaser implements the Transformer interface. Title casing algorithms
315 // distinguish between the first letter of a word and subsequent letters of the
316 // same word. It uses state to avoid requiring a potentially infinite lookahead.
317 type titleCaser struct {
318         context
319
320         // rune mappings used by the actual casing algorithms.
321         title     mapFunc
322         lower     mapFunc
323         titleSpan spanFunc
324
325         rewrite func(*context)
326 }
327
328 // Transform implements the standard Unicode title case algorithm as defined in
329 // Chapter 3 of The Unicode Standard:
330 // toTitlecase(X): Find the word boundaries in X according to Unicode Standard
331 // Annex #29, "Unicode Text Segmentation." For each word boundary, find the
332 // first cased character F following the word boundary. If F exists, map F to
333 // Titlecase_Mapping(F); then map all characters C between F and the following
334 // word boundary to Lowercase_Mapping(C).
335 func (t *titleCaser) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
336         t.context = context{dst: dst, src: src, atEOF: atEOF, isMidWord: t.isMidWord}
337         c := &t.context
338
339         if !c.next() {
340                 return c.ret()
341         }
342
343         for {
344                 p := c.info
345                 if t.rewrite != nil {
346                         t.rewrite(c)
347                 }
348
349                 wasMid := p.isMid()
350                 // Break out of this loop on failure to ensure we do not modify the
351                 // state incorrectly.
352                 if p.isCased() {
353                         if !c.isMidWord {
354                                 if !t.title(c) {
355                                         break
356                                 }
357                                 c.isMidWord = true
358                         } else if !t.lower(c) {
359                                 break
360                         }
361                 } else if !c.copy() {
362                         break
363                 } else if p.isBreak() {
364                         c.isMidWord = false
365                 }
366
367                 // As we save the state of the transformer, it is safe to call
368                 // checkpoint after any successful write.
369                 if !(c.isMidWord && wasMid) {
370                         c.checkpoint()
371                 }
372
373                 if !c.next() {
374                         break
375                 }
376                 if wasMid && c.info.isMid() {
377                         c.isMidWord = false
378                 }
379         }
380         return c.ret()
381 }
382
383 func (t *titleCaser) Span(src []byte, atEOF bool) (n int, err error) {
384         t.context = context{src: src, atEOF: atEOF, isMidWord: t.isMidWord}
385         c := &t.context
386
387         if !c.next() {
388                 return c.retSpan()
389         }
390
391         for {
392                 p := c.info
393                 if t.rewrite != nil {
394                         t.rewrite(c)
395                 }
396
397                 wasMid := p.isMid()
398                 // Break out of this loop on failure to ensure we do not modify the
399                 // state incorrectly.
400                 if p.isCased() {
401                         if !c.isMidWord {
402                                 if !t.titleSpan(c) {
403                                         break
404                                 }
405                                 c.isMidWord = true
406                         } else if !isLower(c) {
407                                 break
408                         }
409                 } else if p.isBreak() {
410                         c.isMidWord = false
411                 }
412                 // As we save the state of the transformer, it is safe to call
413                 // checkpoint after any successful write.
414                 if !(c.isMidWord && wasMid) {
415                         c.checkpoint()
416                 }
417
418                 if !c.next() {
419                         break
420                 }
421                 if wasMid && c.info.isMid() {
422                         c.isMidWord = false
423                 }
424         }
425         return c.retSpan()
426 }
427
428 // finalSigma adds Greek final Sigma handing to another casing function. It
429 // determines whether a lowercased sigma should be σ or ς, by looking ahead for
430 // case-ignorables and a cased letters.
431 func finalSigma(f mapFunc) mapFunc {
432         return func(c *context) bool {
433                 if !c.hasPrefix("Σ") {
434                         return f(c)
435                 }
436                 return finalSigmaBody(c)
437         }
438 }
439
440 func finalSigmaBody(c *context) bool {
441         // Current rune must be ∑.
442
443         // ::NFD();
444         // # 03A3; 03C2; 03A3; 03A3; Final_Sigma; # GREEK CAPITAL LETTER SIGMA
445         // Σ } [:case-ignorable:]* [:cased:] → σ;
446         // [:cased:] [:case-ignorable:]* { Σ → ς;
447         // ::Any-Lower;
448         // ::NFC();
449
450         p := c.pDst
451         c.writeString("ς")
452
453         // TODO: we should do this here, but right now this will never have an
454         // effect as this is called when the prefix is Sigma, whereas Dutch and
455         // Afrikaans only test for an apostrophe.
456         //
457         // if t.rewrite != nil {
458         //      t.rewrite(c)
459         // }
460
461         // We need to do one more iteration after maxIgnorable, as a cased
462         // letter is not an ignorable and may modify the result.
463         wasMid := false
464         for i := 0; i < maxIgnorable+1; i++ {
465                 if !c.next() {
466                         return false
467                 }
468                 if !c.info.isCaseIgnorable() {
469                         // All Midword runes are also case ignorable, so we are
470                         // guaranteed to have a letter or word break here. As we are
471                         // unreading the run, there is no need to unset c.isMidWord;
472                         // the title caser will handle this.
473                         if c.info.isCased() {
474                                 // p+1 is guaranteed to be in bounds: if writing ς was
475                                 // successful, p+1 will contain the second byte of ς. If not,
476                                 // this function will have returned after c.next returned false.
477                                 c.dst[p+1]++ // ς → σ
478                         }
479                         c.unreadRune()
480                         return true
481                 }
482                 // A case ignorable may also introduce a word break, so we may need
483                 // to continue searching even after detecting a break.
484                 isMid := c.info.isMid()
485                 if (wasMid && isMid) || c.info.isBreak() {
486                         c.isMidWord = false
487                 }
488                 wasMid = isMid
489                 c.copy()
490         }
491         return true
492 }
493
494 // finalSigmaSpan would be the same as isLower.
495
496 // elUpper implements Greek upper casing, which entails removing a predefined
497 // set of non-blocked modifiers. Note that these accents should not be removed
498 // for title casing!
499 // Example: "Οδός" -> "ΟΔΟΣ".
500 func elUpper(c *context) bool {
501         // From CLDR:
502         // [:Greek:] [^[:ccc=Not_Reordered:][:ccc=Above:]]*? { [\u0313\u0314\u0301\u0300\u0306\u0342\u0308\u0304] → ;
503         // [:Greek:] [^[:ccc=Not_Reordered:][:ccc=Iota_Subscript:]]*? { \u0345 → ;
504
505         r, _ := utf8.DecodeRune(c.src[c.pSrc:])
506         oldPDst := c.pDst
507         if !upper(c) {
508                 return false
509         }
510         if !unicode.Is(unicode.Greek, r) {
511                 return true
512         }
513         i := 0
514         // Take the properties of the uppercased rune that is already written to the
515         // destination. This saves us the trouble of having to uppercase the
516         // decomposed rune again.
517         if b := norm.NFD.Properties(c.dst[oldPDst:]).Decomposition(); b != nil {
518                 // Restore the destination position and process the decomposed rune.
519                 r, sz := utf8.DecodeRune(b)
520                 if r <= 0xFF { // See A.6.1
521                         return true
522                 }
523                 c.pDst = oldPDst
524                 // Insert the first rune and ignore the modifiers. See A.6.2.
525                 c.writeBytes(b[:sz])
526                 i = len(b[sz:]) / 2 // Greek modifiers are always of length 2.
527         }
528
529         for ; i < maxIgnorable && c.next(); i++ {
530                 switch r, _ := utf8.DecodeRune(c.src[c.pSrc:]); r {
531                 // Above and Iota Subscript
532                 case 0x0300, // U+0300 COMBINING GRAVE ACCENT
533                         0x0301, // U+0301 COMBINING ACUTE ACCENT
534                         0x0304, // U+0304 COMBINING MACRON
535                         0x0306, // U+0306 COMBINING BREVE
536                         0x0308, // U+0308 COMBINING DIAERESIS
537                         0x0313, // U+0313 COMBINING COMMA ABOVE
538                         0x0314, // U+0314 COMBINING REVERSED COMMA ABOVE
539                         0x0342, // U+0342 COMBINING GREEK PERISPOMENI
540                         0x0345: // U+0345 COMBINING GREEK YPOGEGRAMMENI
541                         // No-op. Gobble the modifier.
542
543                 default:
544                         switch v, _ := trie.lookup(c.src[c.pSrc:]); info(v).cccType() {
545                         case cccZero:
546                                 c.unreadRune()
547                                 return true
548
549                         // We don't need to test for IotaSubscript as the only rune that
550                         // qualifies (U+0345) was already excluded in the switch statement
551                         // above. See A.4.
552
553                         case cccAbove:
554                                 return c.copy()
555                         default:
556                                 // Some other modifier. We're still allowed to gobble Greek
557                                 // modifiers after this.
558                                 c.copy()
559                         }
560                 }
561         }
562         return i == maxIgnorable
563 }
564
565 // TODO: implement elUpperSpan (low-priority: complex and infrequent).
566
567 func ltLower(c *context) bool {
568         // From CLDR:
569         // # Introduce an explicit dot above when lowercasing capital I's and J's
570         // # whenever there are more accents above.
571         // # (of the accents used in Lithuanian: grave, acute, tilde above, and ogonek)
572         // # 0049; 0069 0307; 0049; 0049; lt More_Above; # LATIN CAPITAL LETTER I
573         // # 004A; 006A 0307; 004A; 004A; lt More_Above; # LATIN CAPITAL LETTER J
574         // # 012E; 012F 0307; 012E; 012E; lt More_Above; # LATIN CAPITAL LETTER I WITH OGONEK
575         // # 00CC; 0069 0307 0300; 00CC; 00CC; lt; # LATIN CAPITAL LETTER I WITH GRAVE
576         // # 00CD; 0069 0307 0301; 00CD; 00CD; lt; # LATIN CAPITAL LETTER I WITH ACUTE
577         // # 0128; 0069 0307 0303; 0128; 0128; lt; # LATIN CAPITAL LETTER I WITH TILDE
578         // ::NFD();
579         // I } [^[:ccc=Not_Reordered:][:ccc=Above:]]* [:ccc=Above:] → i \u0307;
580         // J } [^[:ccc=Not_Reordered:][:ccc=Above:]]* [:ccc=Above:] → j \u0307;
581         // I \u0328 (Į) } [^[:ccc=Not_Reordered:][:ccc=Above:]]* [:ccc=Above:] → i \u0328 \u0307;
582         // I \u0300 (Ì) → i \u0307 \u0300;
583         // I \u0301 (Í) → i \u0307 \u0301;
584         // I \u0303 (Ĩ) → i \u0307 \u0303;
585         // ::Any-Lower();
586         // ::NFC();
587
588         i := 0
589         if r := c.src[c.pSrc]; r < utf8.RuneSelf {
590                 lower(c)
591                 if r != 'I' && r != 'J' {
592                         return true
593                 }
594         } else {
595                 p := norm.NFD.Properties(c.src[c.pSrc:])
596                 if d := p.Decomposition(); len(d) >= 3 && (d[0] == 'I' || d[0] == 'J') {
597                         // UTF-8 optimization: the decomposition will only have an above
598                         // modifier if the last rune of the decomposition is in [U+300-U+311].
599                         // In all other cases, a decomposition starting with I is always
600                         // an I followed by modifiers that are not cased themselves. See A.2.
601                         if d[1] == 0xCC && d[2] <= 0x91 { // A.2.4.
602                                 if !c.writeBytes(d[:1]) {
603                                         return false
604                                 }
605                                 c.dst[c.pDst-1] += 'a' - 'A' // lower
606
607                                 // Assumption: modifier never changes on lowercase. See A.1.
608                                 // Assumption: all modifiers added have CCC = Above. See A.2.3.
609                                 return c.writeString("\u0307") && c.writeBytes(d[1:])
610                         }
611                         // In all other cases the additional modifiers will have a CCC
612                         // that is less than 230 (Above). We will insert the U+0307, if
613                         // needed, after these modifiers so that a string in FCD form
614                         // will remain so. See A.2.2.
615                         lower(c)
616                         i = 1
617                 } else {
618                         return lower(c)
619                 }
620         }
621
622         for ; i < maxIgnorable && c.next(); i++ {
623                 switch c.info.cccType() {
624                 case cccZero:
625                         c.unreadRune()
626                         return true
627                 case cccAbove:
628                         return c.writeString("\u0307") && c.copy() // See A.1.
629                 default:
630                         c.copy() // See A.1.
631                 }
632         }
633         return i == maxIgnorable
634 }
635
636 // ltLowerSpan would be the same as isLower.
637
638 func ltUpper(f mapFunc) mapFunc {
639         return func(c *context) bool {
640                 // Unicode:
641                 // 0307; 0307; ; ; lt After_Soft_Dotted; # COMBINING DOT ABOVE
642                 //
643                 // From CLDR:
644                 // # Remove \u0307 following soft-dotteds (i, j, and the like), with possible
645                 // # intervening non-230 marks.
646                 // ::NFD();
647                 // [:Soft_Dotted:] [^[:ccc=Not_Reordered:][:ccc=Above:]]* { \u0307 → ;
648                 // ::Any-Upper();
649                 // ::NFC();
650
651                 // TODO: See A.5. A soft-dotted rune never has an exception. This would
652                 // allow us to overload the exception bit and encode this property in
653                 // info. Need to measure performance impact of this.
654                 r, _ := utf8.DecodeRune(c.src[c.pSrc:])
655                 oldPDst := c.pDst
656                 if !f(c) {
657                         return false
658                 }
659                 if !unicode.Is(unicode.Soft_Dotted, r) {
660                         return true
661                 }
662
663                 // We don't need to do an NFD normalization, as a soft-dotted rune never
664                 // contains U+0307. See A.3.
665
666                 i := 0
667                 for ; i < maxIgnorable && c.next(); i++ {
668                         switch c.info.cccType() {
669                         case cccZero:
670                                 c.unreadRune()
671                                 return true
672                         case cccAbove:
673                                 if c.hasPrefix("\u0307") {
674                                         // We don't do a full NFC, but rather combine runes for
675                                         // some of the common cases. (Returning NFC or
676                                         // preserving normal form is neither a requirement nor
677                                         // a possibility anyway).
678                                         if !c.next() {
679                                                 return false
680                                         }
681                                         if c.dst[oldPDst] == 'I' && c.pDst == oldPDst+1 && c.src[c.pSrc] == 0xcc {
682                                                 s := ""
683                                                 switch c.src[c.pSrc+1] {
684                                                 case 0x80: // U+0300 COMBINING GRAVE ACCENT
685                                                         s = "\u00cc" // U+00CC LATIN CAPITAL LETTER I WITH GRAVE
686                                                 case 0x81: // U+0301 COMBINING ACUTE ACCENT
687                                                         s = "\u00cd" // U+00CD LATIN CAPITAL LETTER I WITH ACUTE
688                                                 case 0x83: // U+0303 COMBINING TILDE
689                                                         s = "\u0128" // U+0128 LATIN CAPITAL LETTER I WITH TILDE
690                                                 case 0x88: // U+0308 COMBINING DIAERESIS
691                                                         s = "\u00cf" // U+00CF LATIN CAPITAL LETTER I WITH DIAERESIS
692                                                 default:
693                                                 }
694                                                 if s != "" {
695                                                         c.pDst = oldPDst
696                                                         return c.writeString(s)
697                                                 }
698                                         }
699                                 }
700                                 return c.copy()
701                         default:
702                                 c.copy()
703                         }
704                 }
705                 return i == maxIgnorable
706         }
707 }
708
709 // TODO: implement ltUpperSpan (low priority: complex and infrequent).
710
711 func aztrUpper(f mapFunc) mapFunc {
712         return func(c *context) bool {
713                 // i→İ;
714                 if c.src[c.pSrc] == 'i' {
715                         return c.writeString("İ")
716                 }
717                 return f(c)
718         }
719 }
720
721 func aztrLower(c *context) (done bool) {
722         // From CLDR:
723         // # I and i-dotless; I-dot and i are case pairs in Turkish and Azeri
724         // # 0130; 0069; 0130; 0130; tr; # LATIN CAPITAL LETTER I WITH DOT ABOVE
725         // İ→i;
726         // # When lowercasing, remove dot_above in the sequence I + dot_above, which will turn into i.
727         // # This matches the behavior of the canonically equivalent I-dot_above
728         // # 0307; ; 0307; 0307; tr After_I; # COMBINING DOT ABOVE
729         // # When lowercasing, unless an I is before a dot_above, it turns into a dotless i.
730         // # 0049; 0131; 0049; 0049; tr Not_Before_Dot; # LATIN CAPITAL LETTER I
731         // I([^[:ccc=Not_Reordered:][:ccc=Above:]]*)\u0307 → i$1 ;
732         // I→ı ;
733         // ::Any-Lower();
734         if c.hasPrefix("\u0130") { // İ
735                 return c.writeString("i")
736         }
737         if c.src[c.pSrc] != 'I' {
738                 return lower(c)
739         }
740
741         // We ignore the lower-case I for now, but insert it later when we know
742         // which form we need.
743         start := c.pSrc + c.sz
744
745         i := 0
746 Loop:
747         // We check for up to n ignorables before \u0307. As \u0307 is an
748         // ignorable as well, n is maxIgnorable-1.
749         for ; i < maxIgnorable && c.next(); i++ {
750                 switch c.info.cccType() {
751                 case cccAbove:
752                         if c.hasPrefix("\u0307") {
753                                 return c.writeString("i") && c.writeBytes(c.src[start:c.pSrc]) // ignore U+0307
754                         }
755                         done = true
756                         break Loop
757                 case cccZero:
758                         c.unreadRune()
759                         done = true
760                         break Loop
761                 default:
762                         // We'll write this rune after we know which starter to use.
763                 }
764         }
765         if i == maxIgnorable {
766                 done = true
767         }
768         return c.writeString("ı") && c.writeBytes(c.src[start:c.pSrc+c.sz]) && done
769 }
770
771 // aztrLowerSpan would be the same as isLower.
772
773 func nlTitle(c *context) bool {
774         // From CLDR:
775         // # Special titlecasing for Dutch initial "ij".
776         // ::Any-Title();
777         // # Fix up Ij at the beginning of a "word" (per Any-Title, notUAX #29)
778         // [:^WB=ALetter:] [:WB=Extend:]* [[:WB=MidLetter:][:WB=MidNumLet:]]? { Ij } → IJ ;
779         if c.src[c.pSrc] != 'I' && c.src[c.pSrc] != 'i' {
780                 return title(c)
781         }
782
783         if !c.writeString("I") || !c.next() {
784                 return false
785         }
786         if c.src[c.pSrc] == 'j' || c.src[c.pSrc] == 'J' {
787                 return c.writeString("J")
788         }
789         c.unreadRune()
790         return true
791 }
792
793 func nlTitleSpan(c *context) bool {
794         // From CLDR:
795         // # Special titlecasing for Dutch initial "ij".
796         // ::Any-Title();
797         // # Fix up Ij at the beginning of a "word" (per Any-Title, notUAX #29)
798         // [:^WB=ALetter:] [:WB=Extend:]* [[:WB=MidLetter:][:WB=MidNumLet:]]? { Ij } → IJ ;
799         if c.src[c.pSrc] != 'I' {
800                 return isTitle(c)
801         }
802         if !c.next() || c.src[c.pSrc] == 'j' {
803                 return false
804         }
805         if c.src[c.pSrc] != 'J' {
806                 c.unreadRune()
807         }
808         return true
809 }
810
811 // Not part of CLDR, but see http://unicode.org/cldr/trac/ticket/7078.
812 func afnlRewrite(c *context) {
813         if c.hasPrefix("'") || c.hasPrefix("’") {
814                 c.isMidWord = true
815         }
816 }