1 /* Copyright (C) 2005-2021 J.F.Dockes
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the
14 * Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16 */
17 #include "autoconfig.h"
18
19 #include "log.h"
20 #include "filtseq.h"
21 #include "rclconfig.h"
22
23 using std::string;
24
filter(const DocSeqFiltSpec & fs,const Rcl::Doc * x)25 static bool filter(const DocSeqFiltSpec& fs, const Rcl::Doc *x)
26 {
27 LOGDEB2(" Filter: ncrits " << fs.crits.size() << "\n");
28 // Compare using each criterion in term. We're doing an or: 1st ok ends
29 for (unsigned int i = 0; i < fs.crits.size(); i++) {
30 switch (fs.crits[i]) {
31 case DocSeqFiltSpec::DSFS_MIMETYPE:
32 LOGDEB2(" filter: MIMETYPE: me [" << fs.values[i] << "] doc [" << x->mimetype << "]\n");
33 if (x->mimetype == fs.values[i])
34 return true;
35 break;
36 case DocSeqFiltSpec::DSFS_QLANG: {
37 LOGDEB(" filter: QLANG [" << fs.values[i] << "]!!\n");
38 }
39 break;
40 case DocSeqFiltSpec::DSFS_PASSALL:
41 return true;
42 }
43 }
44 // Did all comparisons
45 return false;
46 }
47
DocSeqFiltered(RclConfig * conf,std::shared_ptr<DocSequence> iseq,DocSeqFiltSpec & filtspec)48 DocSeqFiltered::DocSeqFiltered(
49 RclConfig *conf, std::shared_ptr<DocSequence> iseq, DocSeqFiltSpec &filtspec)
50 : DocSeqModifier(iseq), m_config(conf)
51 {
52 setFiltSpec(filtspec);
53 }
54
setFiltSpec(const DocSeqFiltSpec & filtspec)55 bool DocSeqFiltered::setFiltSpec(const DocSeqFiltSpec &filtspec)
56 {
57 LOGDEB0("DocSeqFiltered::setFiltSpec\n");
58 for (unsigned int i = 0; i < filtspec.crits.size(); i++) {
59 switch (filtspec.crits[i]) {
60 case DocSeqFiltSpec::DSFS_MIMETYPE:
61 m_spec.orCrit(filtspec.crits[i], filtspec.values[i]);
62 break;
63 case DocSeqFiltSpec::DSFS_QLANG: {
64 // There are very few lang constructs that we can interpret. The
65 // default config uses rclcat:value only. That will be all for now...
66 string val = filtspec.values[i];
67 if (val.find("rclcat:") == 0) {
68 string catg = val.substr(7);
69 vector<string> tps;
70 m_config->getMimeCatTypes(catg, tps);
71 for (const auto& mime : tps) {
72 LOGDEB2("Adding mime: [" << mime << "]\n");
73 m_spec.orCrit(DocSeqFiltSpec::DSFS_MIMETYPE, mime);
74 }
75 }
76 }
77 break;
78 default:
79 break;
80 }
81 }
82 // If m_spec ends up empty, pass everything, better than filtering all.
83 if (m_spec.crits.empty()) {
84 m_spec.orCrit(DocSeqFiltSpec::DSFS_PASSALL, "");
85 }
86 m_dbindices.clear();
87 return true;
88 }
89
getDoc(int idx,Rcl::Doc & doc,string *)90 bool DocSeqFiltered::getDoc(int idx, Rcl::Doc &doc, string *)
91 {
92 LOGDEB2("DocSeqFiltered::getDoc() fetching " << idx << "\n");
93
94 if (idx >= (int)m_dbindices.size()) {
95 // Have to fetch docs and filter until we get enough or
96 // fail
97 m_dbindices.reserve(idx+1);
98
99 // First backend seq doc we fetch is the one after last stored
100 int backend_idx = m_dbindices.size() > 0 ? m_dbindices.back() + 1 : 0;
101
102 // Loop until we get enough docs
103 Rcl::Doc tdoc;
104 while (idx >= (int)m_dbindices.size()) {
105 if (!m_seq->getDoc(backend_idx, tdoc))
106 return false;
107 if (filter(m_spec, &tdoc)) {
108 m_dbindices.push_back(backend_idx);
109 }
110 backend_idx++;
111 }
112 doc = tdoc;
113 } else {
114 // The corresponding backend indice is already known
115 if (!m_seq->getDoc(m_dbindices[idx], doc))
116 return false;
117 }
118 return true;
119 }
120
121