All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
query.cpp
Go to the documentation of this file.
1 /*
2 Copyright (c) 2009 zooml.com
3 
4 Permission is hereby granted, free of charge, to any person obtaining a copy
5 of this software and associated documentation files (the "Software"), to deal
6 in the Software without restriction, including without limitation the rights
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the Software is
9 furnished to do so, subject to the following conditions:
10 
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13 
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 THE SOFTWARE.
21 */
22 #include "query.h"
23 #include "urisyn.h"
24 #include <stdexcept>
25 #include <algorithm>
26 namespace te
27 {
28  namespace common
29  {
30  namespace uri
31  {
32  const char query::PAIRS_SEP_CHAR = '&';
33  const char query::PAIRS_SEP_CHAR2 = ';';
34  const char query::KEY_VALUE_SEP_CHAR = '=';
35  query::query() : sorted_(false) {}
36  query::query(const std::string& v, bool dosort) : sorted_(false) {
37  std::string::const_iterator first = v.begin();
38  std::string errs;
39  if (!parse(first, v.end(), *this, &errs) || first != v.end())
40  throw std::invalid_argument("invalid URI query: \"" + v + "\"");
41  if (!errs.empty())
42  throw std::invalid_argument(errs);
43  if (!empty() && dosort)
44  sort();
45  }
46  void query::sort() {
47  std::sort(begin(), end());
48  sorted_ = true;
49  }
50  std::string query::encoding() const {
51  std::string s;
52  for (const_iterator it = begin(); it != end(); ++it) {
53  if (it != begin())
54  s += PAIRS_SEP_CHAR;
55  s += urisyn::encode(urisyn::QUERY_TRAITS, it->first); // Encode and append.
56  s += KEY_VALUE_SEP_CHAR;
57  s += urisyn::encode(urisyn::QUERY_TRAITS, it->second); // Encode and append.
58  }
59  return s;
60  }
61  query::const_iterator query::find(const std::string& key) const {
62  // DUPLICATED BELOW!!!
63  const_iterator it;
64  if (sorted_) {
65  const_iterator lb = std::lower_bound(begin(), end(), value_type(key, ""));
66  it = (lb != end() && lb->first == key) ? lb : end();
67  } else {
68  for (it = begin(); it != end(); ++it)
69  if (it->first == key)
70  break;
71  }
72  return it;
73  }
74  query::iterator query::find(const std::string& key) {
75  // DUPLICATED ABOVE!!!
76  iterator it;
77  if (sorted_) {
78  iterator lb = std::lower_bound(begin(), end(), value_type(key, ""));
79  it = (lb != end() && lb->first == key) ? lb : end();
80  } else {
81  for (it = begin(); it != end(); ++it)
82  if (it->first == key)
83  break;
84  }
85  return it;
86  }
87  bool parse(std::string::const_iterator& first, std::string::const_iterator last, query& v, std::string* errs) {
88  std::string::const_iterator f = first;
89  query tmp;
90  std::string e;
91  for (bool eof = false; !eof;) {
92  std::string key;
93  std::string value;
94  bool nokvsep = false;
95  for (int i = 0; i < 2; ++i) {
96  std::string::const_iterator anchor = f;
97  // Read until end or separator.
98  for (;; ++f)
99  if (f == last) {
100  eof = true;
101  break;
102  } else {
103  char c = *f;
105  break;
106  if (urisyn::QUERY_TRAITS.char_class[(unsigned char)c] < urisyn::CVAL) {
107  eof = true;
108  break;
109  }
110  }
111  if (i)
112  value.assign(anchor, f);
113  else {
114  key.assign(anchor, f);
115  if (eof || *f == query::PAIRS_SEP_CHAR || *f == query::PAIRS_SEP_CHAR2) { // No kv sep or value.
116  i = 2;
117  nokvsep = true;
118  }
119  }
120  if (!eof)
121  ++f; // Skip separator.
122  }
123  if (key.empty()) { // Need a key but missing.
124  if (!value.empty()) {
125  if (!errs || tmp.empty())
126  return false;
127  e += ", (" + convert(f - first) + ") missing key (ignoring value)";
128  }
129  } else if (nokvsep) { // Missing '='.
130  if (!errs || tmp.empty())
131  return false;
132  e += ", (" + convert(f - first) + ") missing \"" + std::string(1, query::KEY_VALUE_SEP_CHAR) + "\" (ignoring key)";
133  } else {
134  if (!urisyn::decode(key)) { // Bad encoding.
135  if (!errs || tmp.empty())
136  return false;
137  e += ", (" + convert(f - first) + ") invalid key encoding (using as is)";
138  }
139  if (!urisyn::decode(value)) { // Bad encoding.
140  if (!errs || tmp.empty())
141  return false;
142  e += ", (" + convert(f - first) + ") invalid value encoding (using as is)";
143  }
144  tmp.push_back(std::make_pair(key, value));
145  }
146  }
147  if (errs && !e.empty()) {
148  if (!errs->empty())
149  *errs += "; ";
150  *errs += "URI query: \"" + std::string(first, f) + "\"" + e;
151  }
152  v = tmp;
153  first = f;
154  return true;
155  }
156  }
157  }
158 }
static const char KEY_VALUE_SEP_CHAR
key-value separator char ('=')
Definition: query.h:88
void sort()
Sort the pairs by key.
Definition: query.cpp:46
query()
Construct.
Definition: query.cpp:35
bool parse(std::string::const_iterator &first, std::string::const_iterator last, authority &v)
Parse URI authority, returning whether found or not and advancing first and setting authority if foun...
Definition: authority.cpp:156
std::string encoding() const
Calculate encoded string.
Definition: query.cpp:50
static const char PAIRS_SEP_CHAR2
pairs separator char (';') // added by Lauro
Definition: query.h:87
std::string encode(const traits &ts, const std::string &comp)
Encode the URI (sub) component.
Definition: urisyn.cpp:157
static const char PAIRS_SEP_CHAR
pairs separator char ('&')
Definition: query.h:86
friend bool TECOMMONEXPORT parse(std::string::const_iterator &first, std::string::const_iterator last, query &v, std::string *errs)
Parse URI query, returning whether found or not and advancing first and setting query if found...
Definition: query.cpp:87
const traits QUERY_TRAITS
query traits
Definition: urisyn.cpp:94
bool decode(std::string &s)
Decode the pct-encoded (hex) sequences, if any, return success.
Definition: urisyn.cpp:171
const_iterator find(const std::string &key) const
Find the const_iterator for the key.
Definition: query.cpp:61
URI query component.
Definition: query.h:54
valid any position
Definition: urisyn.h:39
std::string convert(const path &v)
URI path to string.
Definition: path.cpp:219