bool parse_ip_port_vec(const char *s, vector<entity_addrvec_t>& vec, int type)
{
- const char *p = s;
- const char *end = p + strlen(p);
- while (p < end) {
- entity_addr_t a;
- //cout << " parse at '" << p << "'" << std::endl;
- if (!a.parse(p, &p, type)) {
- //dout(0) << " failed to parse address '" << p << "'" << dendl;
- return false;
+ // first split by [ ;], which are not valid for an addrvec
+ list<string> items;
+ get_str_list(s, " ;", items);
+
+ for (auto& i : items) {
+ const char *s = i.c_str();
+ while (*s) {
+ const char *end;
+
+ // try parsing as an addr
+ entity_addr_t a;
+ if (a.parse(s, &end, type)) {
+ vec.push_back(entity_addrvec_t(a));
+ s = end;
+ if (*s == ',') {
+ ++s;
+ }
+ continue;
+ }
+
+ // ok, try parsing as an addrvec
+ entity_addrvec_t av;
+ if (!av.parse(s, &end)) {
+ return false;
+ }
+ vec.push_back(av);
+ s = end;
+ if (*s == ',') {
+ ++s;
+ }
}
- //cout << " got " << a << ", rest is '" << p << "'" << std::endl;
- vec.push_back(entity_addrvec_t(a));
- while (*p == ',' || *p == ' ' || *p == ';')
- p++;
}
return true;
}
#include "gtest/gtest.h"
#include <vector>
+#include "include/stringify.h"
/* Holds a std::vector with C-strings.
* Will free() them properly in the destructor.
EXPECT_EQ(string("c"), args[3]);
}
}
+
+TEST(CephArgParse, parse_ip_port_vec) {
+ struct {
+ const char *from;
+ int type;
+ const char *to;
+ } tests[] = {
+ { "1.2.3.4", entity_addr_t::TYPE_MSGR2,
+ "v2:1.2.3.4:0/0\n" },
+ { "v1:1.2.3.4", entity_addr_t::TYPE_MSGR2,
+ "v1:1.2.3.4:0/0\n" },
+ { "1.2.3.4", entity_addr_t::TYPE_LEGACY,
+ "v1:1.2.3.4:0/0\n" },
+ { "[::],1.2.3.4", entity_addr_t::TYPE_LEGACY,
+ "v1:[::]:0/0\nv1:1.2.3.4:0/0\n" },
+ { "v2:1.2.3.4:111,v1:5.6.7.8:222", entity_addr_t::TYPE_LEGACY,
+ "v2:1.2.3.4:111/0\nv1:5.6.7.8:222/0\n" },
+ { "v2:1.2.3.4:111 v1:5.6.7.8:222", entity_addr_t::TYPE_LEGACY,
+ "v2:1.2.3.4:111/0\nv1:5.6.7.8:222/0\n" },
+ { "[v2:1.2.3.4:111,v1:5.6.7.8:222] [v2:[::]:3300,v1:[::]:6789]",
+ entity_addr_t::TYPE_LEGACY,
+ "[v2:1.2.3.4:111/0,v1:5.6.7.8:222/0]\n[v2:[::]:3300/0,v1:[::]:6789/0]\n" },
+ { "[v2:1.2.3.4:111,v1:5.6.7.8:222],[v2:[::]:3300,v1:[::]:6789]",
+ entity_addr_t::TYPE_LEGACY,
+ "[v2:1.2.3.4:111/0,v1:5.6.7.8:222/0]\n[v2:[::]:3300/0,v1:[::]:6789/0]\n" },
+ { 0, 0, 0 },
+ };
+
+ for (unsigned i = 0; tests[i].from; ++i) {
+ vector<entity_addrvec_t> v;
+ cout << "-- " << tests[i].from << " type " << tests[i].type
+ << " ->\n" << tests[i].to;
+ ASSERT_TRUE(parse_ip_port_vec(tests[i].from, v, tests[i].type));
+ string actual;
+ for (auto s : v) {
+ actual += stringify(s) + "\n";
+ }
+ ASSERT_EQ(actual, tests[i].to);
+ }
+
+ const char *bad[] = {
+ "1.2.3.4 foo",
+ 0
+ };
+ for (unsigned i = 0; bad[i]; ++i) {
+ vector<entity_addrvec_t> v;
+ cout << "bad " << bad[i] << std::endl;
+ ASSERT_FALSE(parse_ip_port_vec(bad[i], v));
+ }
+}
+
+
/*
* Local Variables:
* compile-command: "cd .. ; make unittest_ceph_argparse && ./unittest_ceph_argparse"