1// Copyright 2015 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 rangetable provides utilities for creating and inspecting
6// unicode.RangeTables.
7package rangetable
8
9import (
10	"sort"
11	"unicode"
12)
13
14// New creates a RangeTable from the given runes, which may contain duplicates.
15func New(r ...rune) *unicode.RangeTable {
16	if len(r) == 0 {
17		return &unicode.RangeTable{}
18	}
19
20	sort.Sort(byRune(r))
21
22	// Remove duplicates.
23	k := 1
24	for i := 1; i < len(r); i++ {
25		if r[k-1] != r[i] {
26			r[k] = r[i]
27			k++
28		}
29	}
30
31	var rt unicode.RangeTable
32	for _, r := range r[:k] {
33		if r <= 0xFFFF {
34			rt.R16 = append(rt.R16, unicode.Range16{Lo: uint16(r), Hi: uint16(r), Stride: 1})
35		} else {
36			rt.R32 = append(rt.R32, unicode.Range32{Lo: uint32(r), Hi: uint32(r), Stride: 1})
37		}
38	}
39
40	// Optimize RangeTable.
41	return Merge(&rt)
42}
43
44type byRune []rune
45
46func (r byRune) Len() int           { return len(r) }
47func (r byRune) Swap(i, j int)      { r[i], r[j] = r[j], r[i] }
48func (r byRune) Less(i, j int) bool { return r[i] < r[j] }
49
50// Visit visits all runes in the given RangeTable in order, calling fn for each.
51func Visit(rt *unicode.RangeTable, fn func(rune)) {
52	for _, r16 := range rt.R16 {
53		for r := rune(r16.Lo); r <= rune(r16.Hi); r += rune(r16.Stride) {
54			fn(r)
55		}
56	}
57	for _, r32 := range rt.R32 {
58		for r := rune(r32.Lo); r <= rune(r32.Hi); r += rune(r32.Stride) {
59			fn(r)
60		}
61	}
62}
63
64// Assigned returns a RangeTable with all assigned code points for a given
65// Unicode version. This includes graphic, format, control, and private-use
66// characters. It returns nil if the data for the given version is not
67// available.
68func Assigned(version string) *unicode.RangeTable {
69	return assigned[version]
70}
71