This commit is contained in:
Miek Gieben 2013-06-20 20:36:13 +00:00
parent 9e544160e4
commit a16b289765
3 changed files with 90 additions and 93 deletions

View File

@ -1,27 +0,0 @@
// Copyright 2011 Miek Gieben. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package dns
import (
"testing"
)
func TestLenLabels(t *testing.T) {
labels := map[string]int{
"miek.nl": 2,
".": 0,
"www.miek.nl.": 3,
"www.miek.nl": 3,
"www..miek.nl": 4,
`www\.miek.nl`: 2,
`www\\.miek.nl`: 3,
}
for owner, lab := range labels {
if l := LenLabels(owner); l != lab {
t.Logf("%s should have %d labels, got %d\n", owner, lab, l)
t.Fail()
}
}
}

View File

@ -10,6 +10,7 @@ package dns
// www.miek.nl. returns []string{"www", "miek", "nl"}
// The root label (.) returns nil.
func SplitLabels(s string) []string {
// TODO(miek): make this use Split
if s == "." {
return nil
}
@ -36,7 +37,7 @@ func SplitLabels(s string) []string {
return labels
}
// CompareLabels compares the strings s1 and s2 and
// CompareLabels compares the names s1 and s2 and
// returns how many labels they have in common starting from the right.
// The comparison stops at the first inequality. The labels are not downcased
// before the comparison.
@ -44,46 +45,39 @@ func SplitLabels(s string) []string {
// www.miek.nl. and miek.nl. have two labels in common: miek and nl
// www.miek.nl. and www.bla.nl. have one label in common: nl
func CompareLabels(s1, s2 string) (n int) {
l1 := SplitLabels(s1)
l2 := SplitLabels(s2)
s1 = Fqdn(s1)
s2 = Fqdn(s2)
l1 := Split(s1)
l2 := Split(s2)
x1 := len(l1) - 1
x2 := len(l2) - 1
// the first check
if l1 == nil || l2 == nil {
return
}
j1 := len(l1) - 1 // end
i1 := len(l1) - 2 // start
j2 := len(l2) - 1
i2 := len(l2) - 2
// the second check can be done here, before we fall through into the for-loop below
if s1[l1[j1]:] == s2[l2[j2]:] {
n++
} else {
return
}
for {
if x1 < 0 || x2 < 0 {
if i1 < 0 || i2 < 0 {
break
}
if l1[x1] == l2[x2] {
if s1[l1[i1]:l1[j1]] == s2[l2[i2]:l2[j2]] {
n++
} else {
break
}
x1--
x2--
}
return
}
// lenLabels returns the number of labels in a domain name.
func lenLabels(s string) (labels int) {
if s == "." {
return
}
last := byte('.')
lastlast := byte('.')
s = Fqdn(s)
for i := 0; i < len(s); i++ {
if s[i] == '.' {
if last == '\\' {
if lastlast != '\\' {
// do nothing
continue
}
}
labels++
}
lastlast = last
last = s[i]
j1--
i1--
j2--
i2--
}
return
}
@ -93,27 +87,47 @@ func LenLabels(s string) (labels int) {
if s == "." {
return
}
s = Fqdn(s)
s = Fqdn(s) // TODO(miek): annoyed I need this
off := 0
end := false
for {
off, end = nextLabel(s, off+1)
off, end = nextLabel(s, off)
labels++
if end {
return
}
labels++
}
}
// NextLabel returns the index of the start of the next label in the
// string s. The bool end is true when the end of the string has been
// Split splits a name s into its label indexes.
// www.miek.nl. returns []int{0, 4, 9}. The root name (.) returns nil.
func Split(s string) []int {
if s == "." {
return nil
}
s = Fqdn(s) // Grrr!
idx := []int{0} // TODO(miek): could allocate more (10) and then extend when needed
off := 0
end := false
for {
off, end = nextLabel(s, off)
if end {
return idx
}
idx = append(idx, off)
}
}
// nextLabel returns the index of the start of the next label in the
// string s. The bool end is true when the end of the string has been
// reached.
func nextLabel(s string, offset int) (i int, end bool) {
// The other label function are quite generous with memory,
// The other label function are quite generous with memory,
// this one does not allocate.
quote := false
for i = offset; i < len(s); i++ {
for i = offset; i < len(s)-1; i++ {
switch s[i] {
case '\\':
quote = !quote
@ -124,8 +138,8 @@ func nextLabel(s string, offset int) (i int, end bool) {
quote = !quote
continue
}
return i, false
return i + 1, false
}
}
return i, true
return i + 1, true
}

View File

@ -31,36 +31,46 @@ func TestCompareLabels(t *testing.T) {
t.Logf("%s with %s should be %d", s1, s5, 1)
t.Fail()
}
if CompareLabels(s1, ".") != 0 {
t.Logf("%s with %s should be %d", s1, s5, 0)
t.Fail()
}
if CompareLabels(".", ".") != 0 {
t.Logf("%s with %s should be %d", ".", ".", 0)
t.Fail()
}
}
func TestSplitLabels(t *testing.T) {
s1 := "www.miek.nl."
s2 := "www.miek.nl"
s3 := `www\.miek.nl.`
s4 := `www\\.miek.nl.`
if len(SplitLabels(s1)) != 3 {
t.Logf("Labels should be 3, %s\n", s1)
t.Fail()
func TestSplit(t *testing.T) {
splitter := map[string]int{
"www.miek.nl.": 3,
"www.miek.nl": 3,
`www\.miek.nl.`: 2,
`www\\.miek.nl.`: 3,
".": 0,
}
if len(SplitLabels(s2)) != 3 {
t.Logf("Labels should be 3, %s\n", s2)
t.Fail()
}
if len(SplitLabels(s3)) != 2 {
t.Logf("Labels should be 2, %s\n", s3)
t.Fail()
}
if len(SplitLabels(s4)) != 3 {
t.Logf("Labels should be 3, %s\n", s4)
t.Fail()
}
if len(SplitLabels(".")) != 0 {
t.Logf("Labels should be 0, %s\n", ".")
t.Fail()
for s, i := range splitter {
if x := len(Split(s)); x != i {
t.Logf("Labels should be %d, got %d: %s\n", i, x, s)
t.Fail()
}
}
}
func TestLenLabels(t *testing.T) {
labels := map[string]int{
"miek.nl": 2,
".": 0,
"www.miek.nl.": 3,
"www.miek.nl": 3,
"www..miek.nl": 4,
`www\.miek.nl`: 2,
`www\\.miek.nl`: 3,
}
for owner, lab := range labels {
if l := LenLabels(owner); l != lab {
t.Logf("%s should have %d labels, got %d\n", owner, lab, l)
t.Fail()
}
}
}