Factor out code for $sort
[xapian.git] / xapian-applications / omega / sort.cc
blob0423a3c9bc5e74339f62b3325dd7fe9f9ecce1d8
1 /* @file sort.cc
2 * @brief OmegaScript $sort function
3 */
4 /* Copyright (C) 2018 Olly Betts
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of the
9 * License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
19 * USA
22 #include <config.h>
24 #include "sort.h"
26 #include <algorithm>
27 #include <string>
28 #include <vector>
30 using namespace std;
32 void
33 omegascript_sort(const vector<string>& args,
34 string& value)
36 const string &list = args[0];
37 if (list.empty()) return;
39 bool uniq = false;
40 bool rev = false;
41 if (args.size() > 1) {
42 for (auto opt_ch : args[1]) {
43 switch (opt_ch) {
44 case 'r':
45 rev = true;
46 break;
47 case 'u':
48 uniq = true;
49 break;
50 default:
51 throw string("Unknown $sort option: ") + opt_ch;
55 vector<string> items;
56 string::size_type split = 0, split2;
57 do {
58 split2 = list.find('\t', split);
59 items.emplace_back(list, split, split2 - split);
60 split = split2 + 1;
61 } while (split2 != string::npos);
63 if (!rev) {
64 sort(items.begin(), items.end());
65 } else {
66 sort(items.begin(), items.end(),
67 [](const string& a, const string& b) {
68 return a > b;
69 });
72 value.reserve(list.size());
73 bool tab = false;
74 const string* prev = nullptr;
75 for (auto&& item : items) {
76 // Skip duplicates if "u" flag specified.
77 if (prev && *prev == item) {
78 continue;
80 if (uniq) {
81 prev = &item;
84 if (tab) {
85 value += '\t';
86 } else {
87 tab = true;
89 value += item;