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"} // www.miek.nl. returns []string{"www", "miek", "nl"}
// The root label (.) returns nil. // The root label (.) returns nil.
func SplitLabels(s string) []string { func SplitLabels(s string) []string {
// TODO(miek): make this use Split
if s == "." { if s == "." {
return nil return nil
} }
@ -36,7 +37,7 @@ func SplitLabels(s string) []string {
return labels 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. // returns how many labels they have in common starting from the right.
// The comparison stops at the first inequality. The labels are not downcased // The comparison stops at the first inequality. The labels are not downcased
// before the comparison. // 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 miek.nl. have two labels in common: miek and nl
// www.miek.nl. and www.bla.nl. have one label in common: nl // www.miek.nl. and www.bla.nl. have one label in common: nl
func CompareLabels(s1, s2 string) (n int) { func CompareLabels(s1, s2 string) (n int) {
l1 := SplitLabels(s1) s1 = Fqdn(s1)
l2 := SplitLabels(s2) s2 = Fqdn(s2)
l1 := Split(s1)
l2 := Split(s2)
x1 := len(l1) - 1 // the first check
x2 := len(l2) - 1 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 { for {
if x1 < 0 || x2 < 0 { if i1 < 0 || i2 < 0 {
break break
} }
if l1[x1] == l2[x2] { if s1[l1[i1]:l1[j1]] == s2[l2[i2]:l2[j2]] {
n++ n++
} else { } else {
break break
} }
x1-- j1--
x2-- i1--
} j2--
return i2--
}
// 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]
} }
return return
} }
@ -93,27 +87,47 @@ func LenLabels(s string) (labels int) {
if s == "." { if s == "." {
return return
} }
s = Fqdn(s) s = Fqdn(s) // TODO(miek): annoyed I need this
off := 0 off := 0
end := false end := false
for { for {
off, end = nextLabel(s, off+1) off, end = nextLabel(s, off)
labels++
if end { if end {
return return
} }
labels++
} }
} }
// NextLabel returns the index of the start of the next label in the // Split splits a name s into its label indexes.
// string s. The bool end is true when the end of the string has been // 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. // reached.
func nextLabel(s string, offset int) (i int, end bool) { 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. // this one does not allocate.
quote := false quote := false
for i = offset; i < len(s); i++ { for i = offset; i < len(s)-1; i++ {
switch s[i] { switch s[i] {
case '\\': case '\\':
quote = !quote quote = !quote
@ -124,8 +138,8 @@ func nextLabel(s string, offset int) (i int, end bool) {
quote = !quote quote = !quote
continue 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.Logf("%s with %s should be %d", s1, s5, 1)
t.Fail() t.Fail()
} }
if CompareLabels(s1, ".") != 0 {
t.Logf("%s with %s should be %d", s1, s5, 0)
t.Fail()
}
if CompareLabels(".", ".") != 0 { if CompareLabels(".", ".") != 0 {
t.Logf("%s with %s should be %d", ".", ".", 0) t.Logf("%s with %s should be %d", ".", ".", 0)
t.Fail() t.Fail()
} }
} }
func TestSplitLabels(t *testing.T) { func TestSplit(t *testing.T) {
s1 := "www.miek.nl." splitter := map[string]int{
s2 := "www.miek.nl" "www.miek.nl.": 3,
s3 := `www\.miek.nl.` "www.miek.nl": 3,
s4 := `www\\.miek.nl.` `www\.miek.nl.`: 2,
`www\\.miek.nl.`: 3,
if len(SplitLabels(s1)) != 3 { ".": 0,
t.Logf("Labels should be 3, %s\n", s1)
t.Fail()
} }
if len(SplitLabels(s2)) != 3 { for s, i := range splitter {
t.Logf("Labels should be 3, %s\n", s2) if x := len(Split(s)); x != i {
t.Fail() t.Logf("Labels should be %d, got %d: %s\n", i, x, s)
} t.Fail()
if len(SplitLabels(s3)) != 2 { }
t.Logf("Labels should be 2, %s\n", s3) }
t.Fail() }
}
if len(SplitLabels(s4)) != 3 { func TestLenLabels(t *testing.T) {
t.Logf("Labels should be 3, %s\n", s4) labels := map[string]int{
t.Fail() "miek.nl": 2,
} ".": 0,
if len(SplitLabels(".")) != 0 { "www.miek.nl.": 3,
t.Logf("Labels should be 0, %s\n", ".") "www.miek.nl": 3,
t.Fail() "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()
}
} }
} }