package dns

// Holds a bunch of helper functions for dealing with labels.

// SplitDomainName splits a name string into it's labels.
// www.miek.nl. returns []string{"www", "miek", "nl"}
// .www.miek.nl. returns []string{"", "www", "miek", "nl"},
// The root label (.) returns nil. Note that using
// strings.Split(s) will work in most cases, but does not handle
// escaped dots (\.) for instance.
// s must be a syntactically valid domain name, see IsDomainName.
func ( string) ( []string) {
	if  == "" {
		return nil
	}
	 := 0 // offset of the final '.' or the length of the name
	 := Split()
	 := 0
	if IsFqdn() {
		 = len() - 1
	} else {
		 = len()
	}

	switch len() {
	case 0:
		return nil
	case 1:
		// no-op
	default:
		for ,  := range [1:] {
			 = append(, [:-1])
			 = 
		}
	}

	return append(, [:])
}

// CompareDomainName 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 names are downcased
// before the comparison.
//
// 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
//
// s1 and s2 must be syntactically valid domain names.
func (,  string) ( int) {
	// the first check: root label
	if  == "." ||  == "." {
		return 0
	}

	 := Split()
	 := Split()

	 := len() - 1 // end
	 := len() - 2 // start
	 := len() - 1
	 := len() - 2
	// the second check can be done here: last/only label
	// before we fall through into the for-loop below
	if equal([[]:], [[]:]) {
		++
	} else {
		return
	}
	for {
		if  < 0 ||  < 0 {
			break
		}
		if equal([[]:[]], [[]:[]]) {
			++
		} else {
			break
		}
		--
		--
		--
		--
	}
	return
}

// CountLabel counts the number of labels in the string s.
// s must be a syntactically valid domain name.
func ( string) ( int) {
	if  == "." {
		return
	}
	 := 0
	 := false
	for {
		,  = NextLabel(, )
		++
		if  {
			return
		}
	}
}

// Split splits a name s into its label indexes.
// www.miek.nl. returns []int{0, 4, 9}, www.miek.nl also returns []int{0, 4, 9}.
// The root name (.) returns nil. Also see SplitDomainName.
// s must be a syntactically valid domain name.
func ( string) []int {
	if  == "." {
		return nil
	}
	 := make([]int, 1, 3)
	 := 0
	 := false

	for {
		,  = NextLabel(, )
		if  {
			return 
		}
		 = append(, )
	}
}

// NextLabel returns the index of the start of the next label in the
// string s starting at offset. A negative offset will cause a panic.
// The bool end is true when the end of the string has been reached.
// Also see PrevLabel.
func ( string,  int) ( int,  bool) {
	if  == "" {
		return 0, true
	}
	for  = ;  < len()-1; ++ {
		if [] != '.' {
			continue
		}
		 :=  - 1
		for  >= 0 && [] == '\\' {
			--
		}

		if (-)%2 == 0 {
			continue
		}

		return  + 1, false
	}
	return  + 1, true
}

// PrevLabel returns the index of the label when starting from the right and
// jumping n labels to the left.
// The bool start is true when the start of the string has been overshot.
// Also see NextLabel.
func ( string,  int) ( int,  bool) {
	if  == "" {
		return 0, true
	}
	if  == 0 {
		return len(), false
	}

	 := len() - 1
	if [] == '.' {
		--
	}

	for ;  >= 0 &&  > 0; -- {
		if [] != '.' {
			continue
		}
		 :=  - 1
		for  >= 0 && [] == '\\' {
			--
		}

		if (-)%2 == 0 {
			continue
		}

		--
		if  == 0 {
			return  + 1, false
		}
	}

	return 0,  > 1
}

// equal compares a and b while ignoring case. It returns true when equal otherwise false.
func equal(,  string) bool {
	// might be lifted into API function.
	 := len()
	 := len()
	if  !=  {
		return false
	}

	for  :=  - 1;  >= 0; -- {
		 := []
		 := []
		if  >= 'A' &&  <= 'Z' {
			 |= 'a' - 'A'
		}
		if  >= 'A' &&  <= 'Z' {
			 |= 'a' - 'A'
		}
		if  !=  {
			return false
		}
	}
	return true
}