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 <stdio.h>
00026 #include <stdlib.h>
00027 #include "safeerrno.h"
00028
00029 #include <string>
00030 #include "stringutils.h"
00031
00032 using namespace std;
00033
00034 static bool
00035 decode_xxy(const string & s, int & x1, int &x2, int &y)
00036 {
00037 if (s.size() < 5 || s.size() > 10) return false;
00038 size_t i = s.find_first_not_of("0123456789");
00039 if (i < 1 || i > 2 || !(s[i] == '/' || s[i] == '-' || s[i] == '.'))
00040 return false;
00041 size_t j = s.find_first_not_of("0123456789", i + 1);
00042 if (j - (i + 1) < 1 || j - (i + 1) > 2 ||
00043 !(s[j] == '/' || s[j] == '-' || s[j] == '.'))
00044 return false;
00045 if (s.size() - j > 4 + 1) return false;
00046 if (s.find_first_not_of("0123456789", j + 1) != string::npos)
00047 return false;
00048 x1 = atoi(s.c_str());
00049 if (x1 < 1 || x1 > 31) return false;
00050 x2 = atoi(s.c_str() + i + 1);
00051 if (x2 < 1 || x2 > 31) return false;
00052 y = atoi(s.c_str() + j + 1);
00053 return true;
00054 }
00055
00056
00057
00058
00059
00060 static const char max_month_length[12] = {
00061 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
00062 };
00063
00064 static bool
00065 vet_dm(int d, int m)
00066 {
00067 if (m > 12 || m < 1) return false;
00068 if (d < 1 || d > max_month_length[m - 1]) return false;
00069 return true;
00070 }
00071
00072 Xapian::valueno
00073 Xapian::DateValueRangeProcessor::operator()(string &begin, string &end)
00074 {
00075 if (begin.size() == 8 && end.size() == 8 &&
00076 begin.find_first_not_of("0123456789") == string::npos &&
00077 end.find_first_not_of("0123456789") == string::npos) {
00078
00079 return valno;
00080 }
00081 if (begin.size() == 10 && end.size() == 10 &&
00082 begin.find_first_not_of("0123456789") == 4 &&
00083 end.find_first_not_of("0123456789") == 4 &&
00084 begin.find_first_not_of("0123456789", 5) == 7 &&
00085 end.find_first_not_of("0123456789", 5) == 7 &&
00086 begin.find_first_not_of("0123456789", 8) == string::npos &&
00087 end.find_first_not_of("0123456789", 8) == string::npos &&
00088 begin[4] == begin[7] && end[4] == end[7] && begin[4] == end[4] &&
00089 (end[4] == '-' || end[4] == '.' || end[4] == '/')) {
00090
00091 begin.erase(7, 1);
00092 begin.erase(4, 1);
00093 end.erase(7, 1);
00094 end.erase(4, 1);
00095 return valno;
00096 }
00097
00098 int b_d, b_m, b_y;
00099 int e_d, e_m, e_y;
00100 if (!decode_xxy(begin, b_d, b_m, b_y) || !decode_xxy(end, e_d, e_m, e_y))
00101 return Xapian::BAD_VALUENO;
00102
00103
00104
00105 if (!prefer_mdy && vet_dm(b_d, b_m) && vet_dm(e_d, e_m) &&
00106 (b_y != e_y || b_m < e_m || (b_m == e_m && b_d <= e_d))) {
00107
00108 } else if (vet_dm(b_m, b_d) && vet_dm(e_m, e_d) &&
00109 (b_y != e_y || b_d < e_d || (b_d == e_d && b_m <= e_m))) {
00110 swap(b_m, b_d);
00111 swap(e_m, e_d);
00112 } else if (prefer_mdy && vet_dm(b_d, b_m) && vet_dm(e_d, e_m) &&
00113 (b_y != e_y || b_m < e_m || (b_m == e_m && b_d <= e_d))) {
00114
00115 } else {
00116 return Xapian::BAD_VALUENO;
00117 }
00118
00119 if (b_y < 100) {
00120 b_y += 1900;
00121 if (b_y < epoch_year) b_y += 100;
00122 }
00123 if (e_y < 100) {
00124 e_y += 1900;
00125 if (e_y < epoch_year) e_y += 100;
00126 }
00127
00128 #ifdef SNPRINTF
00129 char buf[9];
00130 SNPRINTF(buf, sizeof(buf), "%08d", b_y * 10000 + b_m * 100 + b_d);
00131 begin.assign(buf, 8);
00132 SNPRINTF(buf, sizeof(buf), "%08d", e_y * 10000 + e_m * 100 + e_d);
00133 end.assign(buf, 8);
00134 #else
00135 char buf[100];
00136 buf[sizeof(buf) - 1] = '\0';
00137 sprintf(buf, "%08d", b_y * 10000 + b_m * 100 + b_d);
00138 if (buf[sizeof(buf) - 1]) abort();
00139 begin.assign(buf, 8);
00140 sprintf(buf, "%08d", e_y * 10000 + e_m * 100 + e_d);
00141 if (buf[sizeof(buf) - 1]) abort();
00142 end.assign(buf, 8);
00143 #endif
00144 return valno;
00145 }
00146
00147 Xapian::valueno
00148 Xapian::NumberValueRangeProcessor::operator()(string &begin, string &end)
00149 {
00150 size_t b_b = 0, e_b = 0;
00151 size_t b_e = string::npos, e_e = string::npos;
00152
00153 if (str.size()) {
00154 if (prefix) {
00155
00156 if (!startswith(begin, str)) {
00157
00158 return Xapian::BAD_VALUENO;
00159 }
00160 b_b = str.size();
00161
00162 if (startswith(end, str)) {
00163 e_b = str.size();
00164 }
00165 } else {
00166
00167 if (!endswith(end, str)) {
00168
00169 return Xapian::BAD_VALUENO;
00170 }
00171 e_e = end.size() - str.size();
00172
00173 if (endswith(begin, str)) {
00174 b_e = begin.size() - str.size();
00175 }
00176 }
00177 }
00178
00179
00180 if (b_e != string::npos)
00181 begin.resize(b_e);
00182
00183
00184 if (e_e != string::npos)
00185 end.resize(e_e);
00186
00187
00188 double beginnum, endnum;
00189 const char * startptr;
00190 char * endptr;
00191
00192 errno = 0;
00193 startptr = begin.c_str() + b_b;
00194 beginnum = strtod(startptr, &endptr);
00195 if (endptr != startptr - b_b + begin.size())
00196
00197 return Xapian::BAD_VALUENO;
00198 if (errno)
00199
00200 return Xapian::BAD_VALUENO;
00201
00202 errno = 0;
00203 startptr = end.c_str() + e_b;
00204 endnum = strtod(startptr, &endptr);
00205 if (endptr != startptr - e_b + end.size())
00206
00207 return Xapian::BAD_VALUENO;
00208 if (errno)
00209
00210 return Xapian::BAD_VALUENO;
00211
00212 begin.assign(Xapian::sortable_serialise(beginnum));
00213 end.assign(Xapian::sortable_serialise(endnum));
00214
00215 return valno;
00216 }