00001
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <config.h>
00022
00023 #include <xapian/queryparser.h>
00024
00025 #include <cstdio>
00026 #include <cstdlib>
00027 #include "safeerrno.h"
00028
00029 #include <string>
00030 #include "stringutils.h"
00031
00032 using namespace std;
00033
00034 namespace Xapian {
00035
00036 Xapian::valueno
00037 StringValueRangeProcessor::operator()(string &begin, string &end)
00038 {
00039 if (str.size()) {
00040 if (prefix) {
00041
00042 if (!startswith(begin, str)) {
00043
00044 return Xapian::BAD_VALUENO;
00045 }
00046 begin.erase(0, str.size());
00047
00048 if (startswith(end, str)) {
00049 end.erase(0, str.size());
00050 }
00051 } else {
00052
00053 if (!endswith(end, str)) {
00054
00055 return Xapian::BAD_VALUENO;
00056 }
00057 end.resize(end.size() - str.size());
00058
00059 if (endswith(begin, str)) {
00060 begin.resize(begin.size() - str.size());
00061 }
00062 }
00063 }
00064 return valno;
00065 }
00066
00067 static bool
00068 decode_xxy(const string & s, int & x1, int &x2, int &y)
00069 {
00070 if (s.size() == 0) {
00071 x1 = x2 = y = -1;
00072 return true;
00073 }
00074 if (s.size() < 5 || s.size() > 10) return false;
00075 size_t i = s.find_first_not_of("0123456789");
00076 if (i < 1 || i > 2 || !(s[i] == '/' || s[i] == '-' || s[i] == '.'))
00077 return false;
00078 size_t j = s.find_first_not_of("0123456789", i + 1);
00079 if (j - (i + 1) < 1 || j - (i + 1) > 2 ||
00080 !(s[j] == '/' || s[j] == '-' || s[j] == '.'))
00081 return false;
00082 if (s.size() - j > 4 + 1) return false;
00083 if (s.find_first_not_of("0123456789", j + 1) != string::npos)
00084 return false;
00085 x1 = atoi(s.c_str());
00086 if (x1 < 1 || x1 > 31) return false;
00087 x2 = atoi(s.c_str() + i + 1);
00088 if (x2 < 1 || x2 > 31) return false;
00089 y = atoi(s.c_str() + j + 1);
00090 return true;
00091 }
00092
00093
00094
00095
00096
00097 static const char max_month_length[12] = {
00098 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
00099 };
00100
00101 static bool
00102 vet_dm(int d, int m)
00103 {
00104 if (m == -1) return true;
00105 if (m > 12 || m < 1) return false;
00106 if (d < 1 || d > max_month_length[m - 1]) return false;
00107 return true;
00108 }
00109
00110
00111 static bool
00112 is_yyyy_mm_dd(const string &s)
00113 {
00114 return (s.find_first_not_of("0123456789") == 4 &&
00115 s.find_first_not_of("0123456789", 5) == 7 &&
00116 s.find_first_not_of("0123456789", 8) == string::npos &&
00117 s[4] == s[7] &&
00118 (s[4] == '-' || s[4] == '.' || s[4] == '/'));
00119 }
00120
00121 Xapian::valueno
00122 DateValueRangeProcessor::operator()(string &begin, string &end)
00123 {
00124 if (StringValueRangeProcessor::operator()(begin, end) == BAD_VALUENO)
00125 return BAD_VALUENO;
00126
00127 if ((begin.size() == 8 || begin.size() == 0) &&
00128 (end.size() == 8 || end.size() == 0) &&
00129 begin.find_first_not_of("0123456789") == string::npos &&
00130 end.find_first_not_of("0123456789") == string::npos) {
00131
00132 return valno;
00133 }
00134 if ((begin.size() == 10 || begin.size() == 0) &&
00135 (end.size() == 10 || end.size() == 0)) {
00136 if ((begin.empty() || is_yyyy_mm_dd(begin)) &&
00137 (end.empty() || is_yyyy_mm_dd(end))) {
00138
00139 if (!begin.empty()) {
00140 begin.erase(7, 1);
00141 begin.erase(4, 1);
00142 }
00143 if (!end.empty()) {
00144 end.erase(7, 1);
00145 end.erase(4, 1);
00146 }
00147 return valno;
00148 }
00149 }
00150
00151 int b_d, b_m, b_y;
00152 int e_d, e_m, e_y;
00153 if (!decode_xxy(begin, b_d, b_m, b_y) || !decode_xxy(end, e_d, e_m, e_y))
00154 return Xapian::BAD_VALUENO;
00155
00156
00157
00158 if (!prefer_mdy && vet_dm(b_d, b_m) && vet_dm(e_d, e_m) &&
00159 (b_y != e_y || b_m < e_m || (b_m == e_m && b_d <= e_d))) {
00160
00161 } else if (vet_dm(b_m, b_d) && vet_dm(e_m, e_d) &&
00162 (b_y != e_y || b_d < e_d || (b_d == e_d && b_m <= e_m))) {
00163 swap(b_m, b_d);
00164 swap(e_m, e_d);
00165 } else if (prefer_mdy && vet_dm(b_d, b_m) && vet_dm(e_d, e_m) &&
00166 (b_y != e_y || b_m < e_m || (b_m == e_m && b_d <= e_d))) {
00167
00168 } else {
00169 return Xapian::BAD_VALUENO;
00170 }
00171
00172 if (b_y < 100) {
00173 b_y += 1900;
00174 if (b_y < epoch_year) b_y += 100;
00175 }
00176 if (e_y < 100) {
00177 e_y += 1900;
00178 if (e_y < epoch_year) e_y += 100;
00179 }
00180
00181 #ifdef SNPRINTF
00182 char buf[9];
00183 if (!begin.empty()) {
00184 SNPRINTF(buf, sizeof(buf), "%08d", b_y * 10000 + b_m * 100 + b_d);
00185 begin.assign(buf, 8);
00186 }
00187 if (!end.empty()) {
00188 SNPRINTF(buf, sizeof(buf), "%08d", e_y * 10000 + e_m * 100 + e_d);
00189 end.assign(buf, 8);
00190 }
00191 #else
00192 char buf[100];
00193 buf[sizeof(buf) - 1] = '\0';
00194 if (!begin.empty()) {
00195 sprintf(buf, "%08d", b_y * 10000 + b_m * 100 + b_d);
00196 if (buf[sizeof(buf) - 1]) abort();
00197 begin.assign(buf, 8);
00198 }
00199 if (!end.empty()) {
00200 sprintf(buf, "%08d", e_y * 10000 + e_m * 100 + e_d);
00201 if (buf[sizeof(buf) - 1]) abort();
00202 end.assign(buf, 8);
00203 }
00204 #endif
00205 return valno;
00206 }
00207
00208 Xapian::valueno
00209 NumberValueRangeProcessor::operator()(string &begin, string &end)
00210 {
00211 if (StringValueRangeProcessor::operator()(begin, end) == BAD_VALUENO)
00212 return BAD_VALUENO;
00213
00214
00215 double beginnum, endnum;
00216 const char * startptr;
00217 char * endptr;
00218
00219 if (!begin.empty()) {
00220 errno = 0;
00221 startptr = begin.c_str();
00222 beginnum = strtod(startptr, &endptr);
00223 if (endptr != startptr + begin.size())
00224
00225 return Xapian::BAD_VALUENO;
00226 if (errno)
00227
00228 return Xapian::BAD_VALUENO;
00229 } else {
00230
00231 beginnum = 0.0;
00232 }
00233
00234 if (!end.empty()) {
00235 errno = 0;
00236 startptr = end.c_str();
00237 endnum = strtod(startptr, &endptr);
00238 if (endptr != startptr + end.size())
00239
00240 return Xapian::BAD_VALUENO;
00241 if (errno)
00242
00243 return Xapian::BAD_VALUENO;
00244 end.assign(Xapian::sortable_serialise(endnum));
00245 }
00246
00247 if (!begin.empty()) {
00248 begin.assign(Xapian::sortable_serialise(beginnum));
00249 }
00250
00251 return valno;
00252 }
00253
00254 }