func (params *headerParams) Length() int {
	params.mu.RLock()
	defer params.mu.RUnlock()
	return len(params.params)
}
Returns number of params.
package sip
import (
	"bytes"
	"fmt"
	"strings"
	"sync"
	"github.com/ghettovoice/gosip/util"
)
const abnfWs = " \t"
type Header interface {
	Name() string
	Value() string
	Clone() Header
	String() string
	Equals(other interface{}) bool
}
type Uri interface {
	Equals(other interface{}) bool
	String() string
	Clone() Uri
	IsEncrypted() bool
	SetEncrypted(flag bool)
	User() MaybeString
	SetUser(user MaybeString)
	Password() MaybeString
	SetPassword(pass MaybeString)
	Host() string
	SetHost(host string)
	Port() *Port
	SetPort(port *Port)
	UriParams() Params
	SetUriParams(params Params)
	Headers() Params
	SetHeaders(params Params)
	IsWildcard() bool
}
type ContactUri interface {
	Uri
}
type Params interface {
	Get(key string) (MaybeString, bool)
	Add(key string, val MaybeString) Params
	Remove(key string) Params
	Clone() Params
	Equals(params interface{}) bool
	ToString(sep uint8) string
	String() string
	Length() int
	Items() map[string]MaybeString
	Keys() []string
	Has(key string) bool
}
type headerParams struct {
	mu         sync.RWMutex
	params     map[string]MaybeString
	paramOrder []string
}
func NewParams() Params {
	return &headerParams{
		params:     make(map[string]MaybeString),
		paramOrder: []string{},
	}
}
func (params *headerParams) Items() map[string]MaybeString {
	params.mu.RLock()
	defer params.mu.RUnlock()
	return params.params
}
func (params *headerParams) Keys() []string {
	params.mu.RLock()
	defer params.mu.RUnlock()
	return params.paramOrder
}
func (params *headerParams) Get(key string) (MaybeString, bool) {
	params.mu.RLock()
	v, ok := params.params[key]
	params.mu.RUnlock()
	return v, ok
}
func (params *headerParams) Add(key string, val MaybeString) Params {
	params.mu.Lock()
	if _, ok := params.params[key]; !ok {
		params.paramOrder = append(params.paramOrder, key)
	}
	params.params[key] = val
	params.mu.Unlock()
	return params
}
func (params *headerParams) Remove(key string) Params {
	params.mu.Lock()
	if _, ok := params.params[key]; ok {
		for k, v := range params.paramOrder {
			if v == key {
				params.paramOrder = append(params.paramOrder[:k], params.paramOrder[k+1:]...)
				break
			}
		}
		delete(params.params, key)
	}
	params.mu.Unlock()
	return params
}
func (params *headerParams) Has(key string) bool {
	params.mu.RLock()
	_, ok := params.params[key]
	params.mu.RUnlock()
	return ok
}
func (params *headerParams) Clone() Params {
	if params == nil {
		var dup *headerParams
		return dup
	}
	dup := NewParams()
	for _, key := range params.Keys() {
		if val, ok := params.Get(key); ok {
			dup.Add(key, val)
		}
	}
	return dup
}
func (params *headerParams) ToString(sep uint8) string {
	if params == nil {
		return ""
	}
	var buffer bytes.Buffer
	first := true
	for _, key := range params.Keys() {
		val, ok := params.Get(key)
		if !ok {
			continue
		}
		if !first {
			buffer.WriteString(fmt.Sprintf("%c", sep))
		}
		first = false
		buffer.WriteString(fmt.Sprintf("%s", key))
		if val, ok := val.(String); ok {
			if strings.ContainsAny(val.String(), abnfWs) {
				buffer.WriteString(fmt.Sprintf("=\"%s\"", val.String()))
			} else {
				buffer.WriteString(fmt.Sprintf("=%s", val.String()))
			}
		}
	}
	return buffer.String()
}
func (params *headerParams) String() string {
	if params == nil {
		return ""
	}
	return params.ToString('&')
}