Przeglądaj źródła

Add KeyValueRegex query (-r)

Johannes Hofmann 7 lat temu
rodzic
commit
d21337af83
4 zmienionych plików z 152 dodań i 14 usunięć
  1. 8
    0
      src/args.rs
  2. 46
    14
      src/config.rs
  3. 95
    0
      src/query.rs
  4. 3
    0
      src/search.rs

+ 8
- 0
src/args.rs Wyświetl plik

@@ -42,6 +42,14 @@ pub fn parse<'a>() -> clap::ArgMatches<'a> {
42 42
             .multiple(true)
43 43
             .help("Search for places that are tagged with the given key and value")
44 44
             .takes_value(true))
45
+        .arg(Arg::with_name("keyvalregex")
46
+            .short("r")
47
+            .long("keyvalregex")
48
+            .value_names(&["KEY", "REGEX"])
49
+            .number_of_values(2)
50
+            .multiple(true)
51
+            .help("Search for places that are tagged with the given key and a value that matches the given regex")
52
+            .takes_value(true))
45 53
         .arg(Arg::with_name("fps")
46 54
             .long("fps")
47 55
             .value_name("FPS")

+ 46
- 14
src/config.rs Wyświetl plik

@@ -30,6 +30,7 @@ pub struct Config {
30 30
     pbf_path: Option<PathBuf>,
31 31
     search_pattern: Option<String>,
32 32
     keyval: Vec<(String, String)>,
33
+    keyvalregex: Vec<(String, String)>,
33 34
     fps: f64,
34 35
     use_network: bool,
35 36
     async: bool,
@@ -84,6 +85,21 @@ impl Config {
84 85
             },
85 86
         );
86 87
 
88
+        self.keyvalregex = matches.values_of("keyvalregex").map_or_else(
89
+            || vec![],
90
+            |mut kv| {
91
+                let mut vec = vec![];
92
+                loop {
93
+                    if let (Some(k), Some(v)) = (kv.next(), kv.next()) {
94
+                        vec.push((k.to_string(), v.to_string()));
95
+                    } else {
96
+                        break;
97
+                    }
98
+                }
99
+                vec
100
+            },
101
+        );
102
+
87 103
         if let Some(Ok(fps)) = matches.value_of("fps").map(|s| s.parse()) {
88 104
             self.fps = fps;
89 105
         }
@@ -247,6 +263,7 @@ impl Config {
247 263
                         pbf_path,
248 264
                         search_pattern: None,
249 265
                         keyval: vec![],
266
+                        keyvalregex: vec![],
250 267
                         fps,
251 268
                         use_network,
252 269
                         async,
@@ -412,27 +429,42 @@ impl Config {
412 429
         self.keyval.as_slice()
413 430
     }
414 431
 
432
+    pub fn keyvalregex(&self) -> &[(String, String)] {
433
+        self.keyvalregex.as_slice()
434
+    }
435
+
415 436
     pub fn query_args(&self) -> Option<QueryArgs> {
416
-        match (&self.search_pattern, self.keyval.len()) {
417
-            (&Some(ref pattern), 0) => Some(QueryArgs::ValuePattern(pattern.to_string())),
418
-            (&None, 1) => Some(
419
-                QueryArgs::KeyValue(self.keyval[0].0.to_string(), self.keyval[0].1.to_string())
437
+        match (&self.search_pattern, self.keyval.first(), self.keyvalregex.first()) {
438
+            (&Some(ref pattern), None, None) => Some(
439
+                QueryArgs::ValuePattern(pattern.to_string())
440
+            ),
441
+            (&None, Some(keyval), None) => Some(
442
+                QueryArgs::KeyValue(keyval.0.to_string(), keyval.1.to_string())
420 443
             ),
421
-            (&Some(ref pattern), _) => {
422
-                let mut vec = vec![QueryArgs::ValuePattern(pattern.to_string())];
444
+            (&None, None, Some(keyvalregex)) => Some(
445
+                QueryArgs::KeyValueRegex(keyvalregex.0.to_string(), keyvalregex.1.to_string())
446
+            ),
447
+            (pattern_opt, _, _) => {
448
+                let mut vec = vec![];
449
+
450
+                if let Some(ref pattern) = pattern_opt {
451
+                    vec.push(QueryArgs::ValuePattern(pattern.to_string()));
452
+                }
423 453
 
424 454
                 for (k, v) in &self.keyval {
425 455
                     vec.push(QueryArgs::KeyValue(k.to_string(), v.to_string()));
426 456
                 }
427
-                Some(QueryArgs::Intersection(vec))
428
-            },
429
-            (&None, x) if x > 0 => {
430
-                let mut vec = self.keyval.iter()
431
-                    .map(|&(ref k, ref v)| QueryArgs::KeyValue(k.to_string(), v.to_string()))
432
-                    .collect();
433
-                Some(QueryArgs::Intersection(vec))
457
+
458
+                for (k, v) in &self.keyvalregex {
459
+                    vec.push(QueryArgs::KeyValueRegex(k.to_string(), v.to_string()));
460
+                }
461
+
462
+                if vec.is_empty() {
463
+                    None
464
+                } else {
465
+                    Some(QueryArgs::Intersection(vec))
466
+                }
434 467
             },
435
-            (&None, _) => None,
436 468
         }
437 469
     }
438 470
 

+ 95
- 0
src/query.rs Wyświetl plik

@@ -18,6 +18,7 @@ pub trait Query {
18 18
 pub enum QueryArgs {
19 19
     ValuePattern(String),
20 20
     KeyValue(String, String),
21
+    KeyValueRegex(String, String),
21 22
     Intersection(Vec<QueryArgs>),
22 23
 }
23 24
 
@@ -25,6 +26,7 @@ pub enum QueryArgs {
25 26
 pub enum QueryKind {
26 27
     ValuePattern(ValuePatternQuery),
27 28
     KeyValue(KeyValueQuery),
29
+    KeyValueRegex(KeyValueRegexQuery),
28 30
     Intersection(Vec<QueryKind>),
29 31
 }
30 32
 
@@ -37,6 +39,9 @@ impl QueryArgs {
37 39
             QueryArgs::KeyValue(k, v) => {
38 40
                 Ok(QueryKind::KeyValue(KeyValueQuery::new(k, v)))
39 41
             },
42
+            QueryArgs::KeyValueRegex(k, v) => {
43
+                Ok(QueryKind::KeyValueRegex(KeyValueRegexQuery::new(k, &v)?))
44
+            },
40 45
             QueryArgs::Intersection(queries) => {
41 46
                 let mut subqueries = Vec::with_capacity(queries.len());
42 47
                 for q in queries {
@@ -191,6 +196,96 @@ impl Query for KeyValueQuery {
191 196
     }
192 197
 }
193 198
 
199
+#[derive(Debug)]
200
+pub struct KeyValueRegexQuery {
201
+    key: String,
202
+    value_re: Regex,
203
+}
204
+
205
+impl KeyValueRegexQuery {
206
+    pub fn new<S: Into<String>>(key: S, value_pattern: &str) -> Result<Self, String> {
207
+        let value_re = Regex::new(value_pattern)
208
+            .map_err(|e| format!("{}", e))?;
209
+        Ok(KeyValueRegexQuery {
210
+            key: key.into(),
211
+            value_re,
212
+        })
213
+    }
214
+}
215
+
216
+impl Query for KeyValueRegexQuery {
217
+    type BI = (Vec<u32>, Vec<u32>);
218
+
219
+    fn create_block_index(&self, block: &PrimitiveBlock) -> Option<(Vec<u32>, Vec<u32>)> {
220
+        let mut key_indices = vec![];
221
+        let mut value_indices = vec![];
222
+
223
+        let key_bytes = self.key.as_bytes();
224
+
225
+        for (i, string) in block.raw_stringtable().iter().enumerate() {
226
+            if string.as_slice() == key_bytes {
227
+                key_indices.push(i as u32);
228
+            }
229
+
230
+            if let Ok(s) = ::std::str::from_utf8(string) {
231
+                if self.value_re.is_match(s) {
232
+                    value_indices.push(i as u32);
233
+                }
234
+            }
235
+        }
236
+
237
+        if key_indices.is_empty() || value_indices.is_empty() {
238
+            // No matches possible for this block
239
+            return None;
240
+        }
241
+
242
+        key_indices.sort();
243
+        value_indices.sort();
244
+
245
+        Some((key_indices, value_indices))
246
+    }
247
+
248
+    fn node_matches(&self, bi: &Self::BI, node: &Node) -> bool {
249
+        for (key, val) in node.raw_tags() {
250
+            if bi.0.binary_search(&key).is_ok() && bi.1.binary_search(&val).is_ok() {
251
+                return true;
252
+            }
253
+        }
254
+        return false;
255
+    }
256
+
257
+    fn dense_node_matches(&self, bi: &Self::BI, dnode: &DenseNode) -> bool {
258
+        for (key, val) in dnode.raw_tags() {
259
+            if key >= 0 &&
260
+               val >= 0 &&
261
+               bi.0.binary_search(&(key as u32)).is_ok() &&
262
+               bi.1.binary_search(&(val as u32)).is_ok()
263
+            {
264
+                return true;
265
+            }
266
+        }
267
+        return false;
268
+    }
269
+
270
+    fn way_matches(&self, bi: &Self::BI, way: &Way) -> bool {
271
+        for (key, val) in way.raw_tags() {
272
+            if bi.0.binary_search(&key).is_ok() && bi.1.binary_search(&val).is_ok() {
273
+                return true;
274
+            }
275
+        }
276
+        return false;
277
+    }
278
+
279
+    fn relation_matches(&self, bi: &Self::BI, relation: &Relation) -> bool {
280
+        for (key, val) in relation.raw_tags() {
281
+            if bi.0.binary_search(&key).is_ok() && bi.1.binary_search(&val).is_ok() {
282
+                return true;
283
+            }
284
+        }
285
+        return false;
286
+    }
287
+}
288
+
194 289
 pub fn find_query_matches<Q: Query>(
195 290
     block: &PrimitiveBlock,
196 291
     query: &Q,

+ 3
- 0
src/search.rs Wyświetl plik

@@ -96,6 +96,9 @@ fn first_query_pass(block: &PrimitiveBlock, query: &QueryKind)
96 96
         &QueryKind::KeyValue(ref query) => {
97 97
             find_query_matches(block, query, &mut matches, &mut way_node_ids);
98 98
         },
99
+        &QueryKind::KeyValueRegex(ref query) => {
100
+            find_query_matches(block, query, &mut matches, &mut way_node_ids);
101
+        },
99 102
         &QueryKind::Intersection(ref queries) => {
100 103
             let mut q_iter = queries.iter();
101 104