| // Copyright 2015 The Go Authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style | 
 | // license that can be found in the LICENSE file. | 
 |  | 
 | package rangetable | 
 |  | 
 | import ( | 
 | 	"unicode" | 
 | ) | 
 |  | 
 | // atEnd is used to mark a completed iteration. | 
 | const atEnd = unicode.MaxRune + 1 | 
 |  | 
 | // Merge returns a new RangeTable that is the union of the given tables. | 
 | // It can also be used to compact user-created RangeTables. The entries in | 
 | // R16 and R32 for any given RangeTable should be sorted and non-overlapping. | 
 | // | 
 | // A lookup in the resulting table can be several times faster than using In | 
 | // directly on the ranges. Merge is an expensive operation, however, and only | 
 | // makes sense if one intends to use the result for more than a couple of | 
 | // hundred lookups. | 
 | func Merge(ranges ...*unicode.RangeTable) *unicode.RangeTable { | 
 | 	rt := &unicode.RangeTable{} | 
 | 	if len(ranges) == 0 { | 
 | 		return rt | 
 | 	} | 
 |  | 
 | 	iter := tablesIter(make([]tableIndex, len(ranges))) | 
 |  | 
 | 	for i, t := range ranges { | 
 | 		iter[i] = tableIndex{t, 0, atEnd} | 
 | 		if len(t.R16) > 0 { | 
 | 			iter[i].next = rune(t.R16[0].Lo) | 
 | 		} | 
 | 	} | 
 |  | 
 | 	if r0 := iter.next16(); r0.Stride != 0 { | 
 | 		for { | 
 | 			r1 := iter.next16() | 
 | 			if r1.Stride == 0 { | 
 | 				rt.R16 = append(rt.R16, r0) | 
 | 				break | 
 | 			} | 
 | 			stride := r1.Lo - r0.Hi | 
 | 			if (r1.Lo == r1.Hi || stride == r1.Stride) && (r0.Lo == r0.Hi || stride == r0.Stride) { | 
 | 				// Fully merge the next range into the previous one. | 
 | 				r0.Hi, r0.Stride = r1.Hi, stride | 
 | 				continue | 
 | 			} else if stride == r0.Stride { | 
 | 				// Move the first element of r1 to r0. This may eliminate an | 
 | 				// entry. | 
 | 				r0.Hi = r1.Lo | 
 | 				r0.Stride = stride | 
 | 				r1.Lo = r1.Lo + r1.Stride | 
 | 				if r1.Lo > r1.Hi { | 
 | 					continue | 
 | 				} | 
 | 			} | 
 | 			rt.R16 = append(rt.R16, r0) | 
 | 			r0 = r1 | 
 | 		} | 
 | 	} | 
 |  | 
 | 	for i, t := range ranges { | 
 | 		iter[i] = tableIndex{t, 0, atEnd} | 
 | 		if len(t.R32) > 0 { | 
 | 			iter[i].next = rune(t.R32[0].Lo) | 
 | 		} | 
 | 	} | 
 |  | 
 | 	if r0 := iter.next32(); r0.Stride != 0 { | 
 | 		for { | 
 | 			r1 := iter.next32() | 
 | 			if r1.Stride == 0 { | 
 | 				rt.R32 = append(rt.R32, r0) | 
 | 				break | 
 | 			} | 
 | 			stride := r1.Lo - r0.Hi | 
 | 			if (r1.Lo == r1.Hi || stride == r1.Stride) && (r0.Lo == r0.Hi || stride == r0.Stride) { | 
 | 				// Fully merge the next range into the previous one. | 
 | 				r0.Hi, r0.Stride = r1.Hi, stride | 
 | 				continue | 
 | 			} else if stride == r0.Stride { | 
 | 				// Move the first element of r1 to r0. This may eliminate an | 
 | 				// entry. | 
 | 				r0.Hi = r1.Lo | 
 | 				r1.Lo = r1.Lo + r1.Stride | 
 | 				if r1.Lo > r1.Hi { | 
 | 					continue | 
 | 				} | 
 | 			} | 
 | 			rt.R32 = append(rt.R32, r0) | 
 | 			r0 = r1 | 
 | 		} | 
 | 	} | 
 |  | 
 | 	for i := 0; i < len(rt.R16) && rt.R16[i].Hi <= unicode.MaxLatin1; i++ { | 
 | 		rt.LatinOffset = i + 1 | 
 | 	} | 
 |  | 
 | 	return rt | 
 | } | 
 |  | 
 | type tableIndex struct { | 
 | 	t    *unicode.RangeTable | 
 | 	p    uint32 | 
 | 	next rune | 
 | } | 
 |  | 
 | type tablesIter []tableIndex | 
 |  | 
 | // sortIter does an insertion sort using the next field of tableIndex. Insertion | 
 | // sort is a good sorting algorithm for this case. | 
 | func sortIter(t []tableIndex) { | 
 | 	for i := range t { | 
 | 		for j := i; j > 0 && t[j-1].next > t[j].next; j-- { | 
 | 			t[j], t[j-1] = t[j-1], t[j] | 
 | 		} | 
 | 	} | 
 | } | 
 |  | 
 | // next16 finds the ranged to be added to the table. If ranges overlap between | 
 | // multiple tables it clips the result to a non-overlapping range if the | 
 | // elements are not fully subsumed. It returns a zero range if there are no more | 
 | // ranges. | 
 | func (ti tablesIter) next16() unicode.Range16 { | 
 | 	sortIter(ti) | 
 |  | 
 | 	t0 := ti[0] | 
 | 	if t0.next == atEnd { | 
 | 		return unicode.Range16{} | 
 | 	} | 
 | 	r0 := t0.t.R16[t0.p] | 
 | 	r0.Lo = uint16(t0.next) | 
 |  | 
 | 	// We restrict the Hi of the current range if it overlaps with another range. | 
 | 	for i := range ti { | 
 | 		tn := ti[i] | 
 | 		// Since our tableIndices are sorted by next, we can break if the there | 
 | 		// is no overlap. The first value of a next range can always be merged | 
 | 		// into the current one, so we can break in case of equality as well. | 
 | 		if rune(r0.Hi) <= tn.next { | 
 | 			break | 
 | 		} | 
 | 		rn := tn.t.R16[tn.p] | 
 | 		rn.Lo = uint16(tn.next) | 
 |  | 
 | 		// Limit r0.Hi based on next ranges in list, but allow it to overlap | 
 | 		// with ranges as long as it subsumes it. | 
 | 		m := (rn.Lo - r0.Lo) % r0.Stride | 
 | 		if m == 0 && (rn.Stride == r0.Stride || rn.Lo == rn.Hi) { | 
 | 			// Overlap, take the min of the two Hi values: for simplicity's sake | 
 | 			// we only process one range at a time. | 
 | 			if r0.Hi > rn.Hi { | 
 | 				r0.Hi = rn.Hi | 
 | 			} | 
 | 		} else { | 
 | 			// Not a compatible stride. Set to the last possible value before | 
 | 			// rn.Lo, but ensure there is at least one value. | 
 | 			if x := rn.Lo - m; r0.Lo <= x { | 
 | 				r0.Hi = x | 
 | 			} | 
 | 			break | 
 | 		} | 
 | 	} | 
 |  | 
 | 	// Update the next values for each table. | 
 | 	for i := range ti { | 
 | 		tn := &ti[i] | 
 | 		if rune(r0.Hi) < tn.next { | 
 | 			break | 
 | 		} | 
 | 		rn := tn.t.R16[tn.p] | 
 | 		stride := rune(rn.Stride) | 
 | 		tn.next += stride * (1 + ((rune(r0.Hi) - tn.next) / stride)) | 
 | 		if rune(rn.Hi) < tn.next { | 
 | 			if tn.p++; int(tn.p) == len(tn.t.R16) { | 
 | 				tn.next = atEnd | 
 | 			} else { | 
 | 				tn.next = rune(tn.t.R16[tn.p].Lo) | 
 | 			} | 
 | 		} | 
 | 	} | 
 |  | 
 | 	if r0.Lo == r0.Hi { | 
 | 		r0.Stride = 1 | 
 | 	} | 
 |  | 
 | 	return r0 | 
 | } | 
 |  | 
 | // next32 finds the ranged to be added to the table. If ranges overlap between | 
 | // multiple tables it clips the result to a non-overlapping range if the | 
 | // elements are not fully subsumed. It returns a zero range if there are no more | 
 | // ranges. | 
 | func (ti tablesIter) next32() unicode.Range32 { | 
 | 	sortIter(ti) | 
 |  | 
 | 	t0 := ti[0] | 
 | 	if t0.next == atEnd { | 
 | 		return unicode.Range32{} | 
 | 	} | 
 | 	r0 := t0.t.R32[t0.p] | 
 | 	r0.Lo = uint32(t0.next) | 
 |  | 
 | 	// We restrict the Hi of the current range if it overlaps with another range. | 
 | 	for i := range ti { | 
 | 		tn := ti[i] | 
 | 		// Since our tableIndices are sorted by next, we can break if the there | 
 | 		// is no overlap. The first value of a next range can always be merged | 
 | 		// into the current one, so we can break in case of equality as well. | 
 | 		if rune(r0.Hi) <= tn.next { | 
 | 			break | 
 | 		} | 
 | 		rn := tn.t.R32[tn.p] | 
 | 		rn.Lo = uint32(tn.next) | 
 |  | 
 | 		// Limit r0.Hi based on next ranges in list, but allow it to overlap | 
 | 		// with ranges as long as it subsumes it. | 
 | 		m := (rn.Lo - r0.Lo) % r0.Stride | 
 | 		if m == 0 && (rn.Stride == r0.Stride || rn.Lo == rn.Hi) { | 
 | 			// Overlap, take the min of the two Hi values: for simplicity's sake | 
 | 			// we only process one range at a time. | 
 | 			if r0.Hi > rn.Hi { | 
 | 				r0.Hi = rn.Hi | 
 | 			} | 
 | 		} else { | 
 | 			// Not a compatible stride. Set to the last possible value before | 
 | 			// rn.Lo, but ensure there is at least one value. | 
 | 			if x := rn.Lo - m; r0.Lo <= x { | 
 | 				r0.Hi = x | 
 | 			} | 
 | 			break | 
 | 		} | 
 | 	} | 
 |  | 
 | 	// Update the next values for each table. | 
 | 	for i := range ti { | 
 | 		tn := &ti[i] | 
 | 		if rune(r0.Hi) < tn.next { | 
 | 			break | 
 | 		} | 
 | 		rn := tn.t.R32[tn.p] | 
 | 		stride := rune(rn.Stride) | 
 | 		tn.next += stride * (1 + ((rune(r0.Hi) - tn.next) / stride)) | 
 | 		if rune(rn.Hi) < tn.next { | 
 | 			if tn.p++; int(tn.p) == len(tn.t.R32) { | 
 | 				tn.next = atEnd | 
 | 			} else { | 
 | 				tn.next = rune(tn.t.R32[tn.p].Lo) | 
 | 			} | 
 | 		} | 
 | 	} | 
 |  | 
 | 	if r0.Lo == r0.Hi { | 
 | 		r0.Stride = 1 | 
 | 	} | 
 |  | 
 | 	return r0 | 
 | } |