/
validate_full_topic_name.c
152 lines (146 loc) · 4.97 KB
/
validate_full_topic_name.c
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
146
147
148
149
150
151
152
// Copyright 2017 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <rmw/validate_full_topic_name.h>
#include <ctype.h>
#include <string.h>
#include "rcutils/isalnum_no_locale.h"
rmw_ret_t
rmw_validate_full_topic_name(
const char * topic_name,
int * validation_result,
size_t * invalid_index)
{
if (!topic_name) {
return RMW_RET_INVALID_ARGUMENT;
}
return rmw_validate_full_topic_name_with_size(
topic_name, strlen(topic_name), validation_result, invalid_index);
}
rmw_ret_t
rmw_validate_full_topic_name_with_size(
const char * topic_name,
size_t topic_name_length,
int * validation_result,
size_t * invalid_index)
{
if (!topic_name) {
return RMW_RET_INVALID_ARGUMENT;
}
if (!validation_result) {
return RMW_RET_INVALID_ARGUMENT;
}
if (topic_name_length == 0) {
*validation_result = RMW_TOPIC_INVALID_IS_EMPTY_STRING;
if (invalid_index) {
*invalid_index = 0;
}
return RMW_RET_OK;
}
if (topic_name[0] != '/') {
*validation_result = RMW_TOPIC_INVALID_NOT_ABSOLUTE;
if (invalid_index) {
*invalid_index = 0;
}
return RMW_RET_OK;
}
// note topic_name_length is >= 1 at this point
if (topic_name[topic_name_length - 1] == '/') {
// catches both "/foo/" and "/"
*validation_result = RMW_TOPIC_INVALID_ENDS_WITH_FORWARD_SLASH;
if (invalid_index) {
*invalid_index = topic_name_length - 1;
}
return RMW_RET_OK;
}
// check for unallowed characters
for (size_t i = 0; i < topic_name_length; ++i) {
if (rcutils_isalnum_no_locale(topic_name[i])) {
// if it is an alpha numeric character, i.e. [0-9|A-Z|a-z], continue
continue;
} else if (topic_name[i] == '_') {
// if it is an underscore, continue
continue;
} else if (topic_name[i] == '/') {
// if it is a forward slash, continue
continue;
} else {
// if it is none of these, then it is an unallowed character in a FQN topic name
*validation_result = RMW_TOPIC_INVALID_CONTAINS_UNALLOWED_CHARACTERS;
if (invalid_index) {
*invalid_index = i;
}
return RMW_RET_OK;
}
}
// check for double '/' and tokens that start with a number
for (size_t i = 0; i < topic_name_length; ++i) {
if (i == topic_name_length - 1) {
// if this is the last character, then nothing to check
continue;
}
// past this point, assuming i+1 is a valid index
if (topic_name[i] == '/') {
if (topic_name[i + 1] == '/') {
*validation_result = RMW_TOPIC_INVALID_CONTAINS_REPEATED_FORWARD_SLASH;
if (invalid_index) {
*invalid_index = i + 1;
}
return RMW_RET_OK;
}
if (isdigit(topic_name[i + 1]) != 0) {
// this is the case where a '/' if followed by a number, i.e. [0-9]
*validation_result = RMW_TOPIC_INVALID_NAME_TOKEN_STARTS_WITH_NUMBER;
if (invalid_index) {
*invalid_index = i + 1;
}
return RMW_RET_OK;
}
}
}
// check if the topic name is too long last, since it might be a soft invalidation
if (topic_name_length > RMW_TOPIC_MAX_NAME_LENGTH) {
*validation_result = RMW_TOPIC_INVALID_TOO_LONG;
if (invalid_index) {
*invalid_index = RMW_TOPIC_MAX_NAME_LENGTH - 1;
}
return RMW_RET_OK;
}
// everything was ok, set result to valid topic, avoid setting invalid_index, and return
*validation_result = RMW_TOPIC_VALID;
return RMW_RET_OK;
}
const char *
rmw_full_topic_name_validation_result_string(int validation_result)
{
switch (validation_result) {
case RMW_TOPIC_VALID:
return NULL;
case RMW_TOPIC_INVALID_IS_EMPTY_STRING:
return "topic name must not be empty";
case RMW_TOPIC_INVALID_NOT_ABSOLUTE:
return "topic name must be absolute, it must lead with a '/'";
case RMW_TOPIC_INVALID_ENDS_WITH_FORWARD_SLASH:
return "topic name must not end with a '/'";
case RMW_TOPIC_INVALID_CONTAINS_UNALLOWED_CHARACTERS:
return "topic name must not contain characters other than alphanumerics, '_', or '/'";
case RMW_TOPIC_INVALID_CONTAINS_REPEATED_FORWARD_SLASH:
return "topic name must not contain repeated '/'";
case RMW_TOPIC_INVALID_NAME_TOKEN_STARTS_WITH_NUMBER:
return "topic name must not have a token that starts with a number";
case RMW_TOPIC_INVALID_TOO_LONG:
return "topic length should not exceed '" RMW_STRINGIFY(RMW_TOPIC_MAX_NAME_LENGTH) "'";
default:
return "unknown result code for rwm topic name validation";
}
}