common/safe_io.c \
common/snap_types.cc \
common/str_list.cc \
+ common/str_map.cc \
common/errno.cc \
common/RefCountedObj.cc \
common/blkdev.cc \
--- /dev/null
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2013 Cloudwatt <libre.licensing@cloudwatt.com>
+ *
+ * Author: Loic Dachary <loic@dachary.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ */
+
+#include <errno.h>
+
+#include "include/str_map.h"
+#include "include/str_list.h"
+
+#include "json_spirit/json_spirit.h"
+
+using namespace std;
+
+int get_str_map(const string &str,
+ stringstream &ss,
+ map<string,string> *str_map)
+{
+ json_spirit::mValue json;
+ try {
+ // try json parsing first
+
+ json_spirit::read_or_throw(str, json);
+
+ if (json.type() != json_spirit::obj_type) {
+ ss << str << " must be a JSON object but is of type "
+ << json.type() << " instead";
+ return -EINVAL;
+ }
+
+ json_spirit::mObject o = json.get_obj();
+
+ for (map<string, json_spirit::mValue>::iterator i = o.begin();
+ i != o.end();
+ ++i) {
+ (*str_map)[i->first] = i->second.get_str();
+ }
+
+ } catch (json_spirit::Error_position &e) {
+ // fallback to key=value format
+
+ list<string> pairs;
+ get_str_list(str, "\t\n ", pairs);
+ for (list<string>::iterator i = pairs.begin(); i != pairs.end(); i++) {
+ size_t equal = i->find('=');
+ if (equal == string::npos)
+ (*str_map)[*i] = string();
+ else {
+ const string key = i->substr(0, equal);
+ equal++;
+ const string value = i->substr(equal);
+ (*str_map)[key] = value;
+ }
+ }
+ }
+ return 0;
+}
include/rbd_types.h \
include/statlite.h \
include/str_list.h \
+ include/str_map.h \
include/stringify.h \
include/triple.h \
include/types.h \
--- /dev/null
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2013 Cloudwatt <libre.licensing@cloudwatt.com>
+ *
+ * Author: Loic Dachary <loic@dachary.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ */
+
+#ifndef CEPH_STRMAP_H
+#define CEPH_STRMAP_H
+
+#include <map>
+#include <string>
+#include <sstream>
+
+/**
+ * Parse **str** and set **str_map** with the key/value pairs read
+ * from it. The format of **str** is either a well formed JSON object
+ * or a custom key[=value] plain text format.
+ *
+ * JSON is tried first. If successfully parsed into a JSON object, it
+ * is copied into **str_map** verbatim. If it is not a JSON object ( a
+ * string, integer etc. ), -EINVAL is returned and **ss** is set to
+ * a human readable error message.
+ *
+ * If **str** is no valid JSON, it is assumed to be a string
+ * containing white space separated key=value pairs. A white space is
+ * either space, tab or newline. The value is optional, in which case
+ * it defaults to an empty string. For example:
+ *
+ * insert your own=political statement=here
+ *
+ * will be parsed into:
+ *
+ * { "insert": "",
+ * "your": "",
+ * "own": "policital",
+ * "statement": "here" }
+ *
+ * Returns 0 on success.
+ *
+ * @param [in] str JSON or plain text key/value pairs
+ * @param [out] ss human readable message on error
+ * @param [out] str_map key/value pairs read from str
+ * @return **0** on success or a -EINVAL on error.
+ */
+extern int get_str_map(const std::string &str,
+ std::stringstream &ss,
+ std::map<std::string,std::string> *str_map);
+
+#endif
unittest_bloom_filter_LDADD = $(UNITTEST_LDADD) $(CEPH_GLOBAL)
check_PROGRAMS += unittest_bloom_filter
+unittest_str_map_SOURCES = test/common/test_str_map.cc
+unittest_str_map_CXXFLAGS = $(UNITTEST_CXXFLAGS)
+unittest_str_map_LDADD = $(UNITTEST_LDADD) $(CEPH_GLOBAL)
+check_PROGRAMS += unittest_str_map
+
unittest_sharedptr_registry_SOURCES = test/common/test_sharedptr_registry.cc
unittest_sharedptr_registry_CXXFLAGS = $(UNITTEST_CXXFLAGS)
unittest_sharedptr_registry_LDADD = $(UNITTEST_LDADD) $(CEPH_GLOBAL)
--- /dev/null
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2013 Cloudwatt <libre.licensing@cloudwatt.com>
+ *
+ * Author: Loic Dachary <loic@dachary.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ */
+
+#include <errno.h>
+#include <gtest/gtest.h>
+
+#include "include/str_map.h"
+
+using namespace std;
+
+TEST(str_map, json) {
+ map<string,string> str_map;
+ stringstream ss;
+ // well formatted
+ ASSERT_EQ(0, get_str_map("{\"key\": \"value\"}", ss, &str_map));
+ ASSERT_EQ("value", str_map["key"]);
+ // well formatted but not a JSON object
+ ASSERT_EQ(-EINVAL, get_str_map("\"key\"", ss, &str_map));
+ ASSERT_NE(string::npos, ss.str().find("must be a JSON object"));
+}
+
+TEST(str_map, plaintext) {
+ stringstream ss;
+ {
+ map<string,string> str_map;
+ ASSERT_EQ(0, get_str_map(" foo=bar\t\nfrob=nitz yeah right= \n\t",
+ ss, &str_map));
+ ASSERT_EQ(4u, str_map.size());
+ ASSERT_EQ("bar", str_map["foo"]);
+ ASSERT_EQ("nitz", str_map["frob"]);
+ ASSERT_EQ("", str_map["yeah"]);
+ ASSERT_EQ("", str_map["right"]);
+ }
+ {
+ map<string,string> str_map;
+ ASSERT_EQ(0, get_str_map("that", ss, &str_map));
+ ASSERT_EQ(1u, str_map.size());
+ ASSERT_EQ("", str_map["that"]);
+ }
+ {
+ map<string,string> str_map;
+ ASSERT_EQ(0, get_str_map(" \t \n ", ss, &str_map));
+ ASSERT_EQ(0u, str_map.size());
+ ASSERT_EQ(0, get_str_map("", ss, &str_map));
+ ASSERT_EQ(0u, str_map.size());
+ }
+}
+
+/*
+ * Local Variables:
+ * compile-command: "cd ../.. ; make -j4 &&
+ * make unittest_str_map &&
+ * valgrind --tool=memcheck --leak-check=full \
+ * ./unittest_str_map
+ * "
+ * End:
+ */