/
name.go
145 lines (126 loc) · 3.01 KB
/
name.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
package ros
import (
"fmt"
"regexp"
"strings"
)
const (
Sep = "/"
GlobalNS = "/"
PrivateNS = "~"
)
type NameMap map[string]string
func getNamespace(name string) string {
if len(name) == 0 {
return GlobalNS
} else if name[len(name)-1] == '/' {
name = name[:len(name)-1]
}
result := name[:strings.LastIndex(name, Sep)+1]
if len(result) == 0 {
return Sep
} else {
return result
}
}
func qualifyNodeName(nodeName string) (string, string, error) {
if nodeName == "" {
return "", "", fmt.Errorf("Empty node name")
}
if nodeName[:1] == PrivateNS {
return "", "", fmt.Errorf("Node name should not contain '~'")
}
canonName := canonicalizeName(nodeName)
var components []string
for _, c := range strings.Split(canonName, Sep) {
if len(c) > 0 {
components = append(components, c)
}
}
if len(components) == 1 {
return GlobalNS, components[0], nil
} else {
namespace := GlobalNS + strings.Join(components[:len(components)-1], Sep)
return namespace, components[len(components)-1], nil
}
}
func isValidName(name string) bool {
if len(name) == 0 {
return true
}
if name == "/" || name == "~" {
return true
}
if matched, _ := regexp.MatchString("^[~/]?([a-zA-Z]\\w*/)*[a-zA-Z]\\w*/?$", name); !matched {
return false
}
return true
}
func isGlobalName(name string) bool {
return len(name) > 0 && name[0:1] == GlobalNS
}
func isPrivateName(name string) bool {
return len(name) > 0 && name[0:1] == PrivateNS
}
// Remove sequential seperater
func canonicalizeName(name string) string {
if name == GlobalNS {
return name
} else {
components := []string{}
for _, word := range strings.Split(name, Sep) {
if len(word) > 0 {
components = append(components, word)
}
}
if name[0:1] == GlobalNS {
return GlobalNS + strings.Join(components, Sep)
} else {
return strings.Join(components, Sep)
}
}
}
type NameResolver struct {
nodeName string
namespace string
mapping NameMap
resolvedMapping NameMap
}
func newNameResolver(namespace string, nodeName string, remapping NameMap) *NameResolver {
n := new(NameResolver)
n.nodeName = nodeName
n.namespace = canonicalizeName(namespace)
n.mapping = remapping
n.resolvedMapping = make(NameMap)
for k, v := range n.mapping {
newKey := n.resolve(k)
newValue := n.resolve(v)
n.resolvedMapping[newKey] = newValue
}
return n
}
// Resolve a ROS name to global name
func (n *NameResolver) resolve(name string) string {
if len(name) == 0 {
return n.namespace
}
var resolvedName string
canonName := canonicalizeName(name)
if isGlobalName(canonName) {
resolvedName = canonName
} else if isPrivateName(canonName) {
resolvedName = canonicalizeName(n.namespace + Sep + n.nodeName + Sep + canonName[1:])
} else {
resolvedName = canonicalizeName(n.namespace + Sep + canonName)
}
return resolvedName
}
// Resolve a ROS name with remapping
func (n *NameResolver) remap(name string) string {
key := n.resolve(name)
if value, ok := n.resolvedMapping[key]; ok {
return value
} else {
return key
}
}