// New creates a RangeTable from the given runes, which may contain duplicates. func New(r ...rune) *unicode.RangeTable { if len(r) == 0 { return &unicode.RangeTable{} } sort.Sort(byRune(r)) // Remove duplicates. k := 1 for i := 1; i < len(r); i++ { if r[k-1] != r[i] { r[k] = r[i] k++ } } var rt unicode.RangeTable for _, r := range r[:k] { if r <= 0xFFFF { rt.R16 = append(rt.R16, unicode.Range16{Lo: uint16(r), Hi: uint16(r), Stride: 1}) } else { rt.R32 = append(rt.R32, unicode.Range32{Lo: uint32(r), Hi: uint32(r), Stride: 1}) } } // Optimize RangeTable. return Merge(&rt) }
func addR16ToTable(r *unicode.RangeTable, r16 unicode.Range16) { if r.R16 == nil { r.R16 = make([]unicode.Range16, 0, 1) } r.R16 = append(r.R16, r16) if r16.Hi <= unicode.MaxLatin1 { r.LatinOffset++ } }
func Range(lo, hi rune) Matcher { if lo > hi { return Fail() } var t unicode.RangeTable if lo >= 0x10000 { t.R32 = append(t.R32, unicode.Range32{Lo: uint32(lo), Hi: uint32(hi), Stride: 1}) } else if hi < 0x10000 { t.R16 = append(t.R16, unicode.Range16{Lo: uint16(lo), Hi: uint16(hi), Stride: 1}) if hi < 0x100 { t.LatinOffset = 1 } } else { t.R16 = append(t.R16, unicode.Range16{Lo: uint16(lo), Hi: 0xffff, Stride: 1}) t.R32 = append(t.R32, unicode.Range32{Lo: 0x10000, Hi: uint32(hi), Stride: 1}) } return charClassMatcher{false, t} }
func CharClass(negated bool, table *unicode.RangeTable) Matcher { var t unicode.RangeTable t.R16 = make([]unicode.Range16, len(table.R16)) copy(t.R16, table.R16) t.R32 = make([]unicode.Range32, len(table.R32)) copy(t.R32, table.R32) t.LatinOffset = table.LatinOffset return charClassMatcher{negated, t} }
func OneOf(chars ...rune) Matcher { if len(chars) == 0 { return Fail() } var t unicode.RangeTable sort.Sort(utf8betical(chars)) for _, ch := range chars { if ch >= 0x10000 { t.R32 = append(t.R32, unicode.Range32{Lo: uint32(ch), Hi: uint32(ch), Stride: 1}) } else { t.R16 = append(t.R16, unicode.Range16{Lo: uint16(ch), Hi: uint16(ch), Stride: 1}) if ch < 0x100 { t.LatinOffset += 1 } } } return charClassMatcher{false, t} }
func appendRange16(t *unicode.RangeTable, lo, hi uint16) error { if t.R16 == nil || len(t.R16) == 0 { t.R16 = append(t.R16, unicode.Range16{lo, hi, 1}) if hi <= unicode.MaxLatin1 { t.LatinOffset++ } return nil } range_ := &t.R16[len(t.R16)-1] if lo <= range_.Hi { return fmt.Errorf("AppendRange: lo must be greater than Hi of the last range: lo=%d", lo) } if lo == hi { if range_.Hi+range_.Stride == lo { range_.Hi = lo if len(t.R16) >= 2 { prevR := &t.R16[len(t.R16)-2] if prevR.Stride > 1 && prevR.Hi+1 == range_.Lo { prevCount := (prevR.Hi-prevR.Lo)/prevR.Stride + 1 count := (range_.Hi-range_.Lo)/range_.Stride + 1 if prevCount <= count { range_.Lo-- prevR.Hi -= prevR.Stride if prevR.Lo == prevR.Hi { prevR.Stride = 1 } } } } } else if range_.Lo == range_.Hi { range_.Hi = lo range_.Stride = lo - range_.Lo } else { t.R16 = append(t.R16, unicode.Range16{lo, hi, 1}) if hi <= unicode.MaxLatin1 { t.LatinOffset++ } } } else { if range_.Stride == 1 { if lo-1 <= range_.Hi { range_.Hi = hi } else { if range_.Lo == range_.Hi { range_.Hi = hi range_.Stride = range_.Hi - range_.Lo } else { t.R16 = append(t.R16, unicode.Range16{lo, hi, 1}) if hi <= unicode.MaxLatin1 { t.LatinOffset++ } } } } else { if lo-1 <= range_.Hi { range_.Hi -= range_.Stride if range_.Lo == range_.Hi { range_.Stride = 1 } t.R16 = append(t.R16, unicode.Range16{lo - 1, hi, 1}) if hi <= unicode.MaxLatin1 { t.LatinOffset++ } } else { t.R16 = append(t.R16, unicode.Range16{lo, hi, 1}) if hi <= unicode.MaxLatin1 { t.LatinOffset++ } } } } return nil }