]> git.proxmox.com Git - ceph.git/blob - ceph/src/tools/ceph-diff-sorted.cc
import 15.2.9
[ceph.git] / ceph / src / tools / ceph-diff-sorted.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3
4 /*
5 * diffsorted -- a utility to compute a line-by-line diff on two
6 * sorted input files
7 *
8 * Copyright © 2019 Red Hat
9 *
10 * Author: J. Eric Ivancich
11 *
12 * This is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License version 2.1, as published by the Free Software
15 * Foundation.
16 */
17
18
19 /*
20 * SUMMARY
21 *
22 * The `diffsorted` utility does a line-by-line diff on two sorted text
23 * files and indicating lines that are in one file but not the other
24 * using diff-style notation (although line numbers are not indicated).
25 *
26 * USAGE
27 *
28 * rgw-diff-sorted file1.txt file2.txt
29 *
30 * NOTES
31 *
32 * Each files should have its lines in sorted order and should have no
33 * empty lines.
34 *
35 * A potential input file can be sorted using the `sort` utility provided
36 * that LANG=C to insure byte lexical order. For example:
37 *
38 * LANG=C sort unsorted.txt >sorted.txt
39 *
40 * or:
41 *
42 * export LANG=C
43 * sort unsorted.txt >sorted.txt
44 *
45 * EXIT STATUS
46 *
47 * 0 : files same
48 * 1 : files different
49 * 2 : usage problem (e.g., wrong number of command-line arguments)
50 * 3 : problem opening input file
51 * 4 : bad file content (e.g., unsorted order or empty lines)
52 */
53
54
55 #include <iostream>
56 #include <fstream>
57
58
59 struct FileOfLines {
60 const char* filename;
61 std::ifstream input;
62 std::string this_line, prev_line;
63 bool next_eof;
64 bool is_eof;
65
66 FileOfLines(const char* _filename) :
67 filename(_filename),
68 input(filename),
69 next_eof(false),
70 is_eof(false)
71 { }
72
73 void dump(const std::string& prefix) {
74 do {
75 std::cout << prefix << this_line << std::endl;
76 advance();
77 } while (!eof());
78 }
79
80 bool eof() const {
81 return is_eof;
82 }
83
84 bool good() const {
85 return input.good();
86 }
87
88 void advance() {
89 if (next_eof) {
90 is_eof = true;
91 return;
92 }
93
94 prev_line = this_line;
95 std::getline(input, this_line);
96 if (this_line.empty()) {
97 if (!input.eof()) {
98 std::cerr << "Error: " << filename << " has an empty line." <<
99 std::endl;
100 exit(4);
101 }
102 is_eof = true;
103 return;
104 } else if (input.eof()) {
105 next_eof = true;
106 }
107
108 if (this_line < prev_line) {
109 std::cerr << "Error: " << filename << " is not in sorted order; \"" <<
110 this_line << "\" follows \"" << prev_line << "\"." << std::endl;
111 exit(4);
112 }
113 }
114
115 const std::string line() const {
116 return this_line;
117 }
118 };
119
120 int main(int argc, const char* argv[]) {
121 if (argc != 3) {
122 std::cerr << "Usage: " << argv[0] << " <file1> <file2>" << std::endl;
123 exit(2);
124 }
125
126 FileOfLines input1(argv[1]);
127 if (!input1.good()) {
128 std::cerr << "Error opening " << argv[1] <<
129 "." << std::endl;
130 exit(3);
131 }
132
133 FileOfLines input2(argv[2]);
134 if (!input2.good()) {
135 std::cerr << "Error opening " << argv[2] <<
136 "." << std::endl;
137 exit(3);
138 }
139
140 bool files_same = true;
141
142 input1.advance();
143 input2.advance();
144
145 while (!input1.eof() && !input2.eof()) {
146 if (input1.line() == input2.line()) {
147 input1.advance();
148 input2.advance();
149 } else if (input1.line() < input2.line()) {
150 files_same = false;
151 std::cout << "< " << input1.line() << std::endl;
152 input1.advance();
153 } else {
154 files_same = false;
155 std::cout << "> " << input2.line() << std::endl;
156 input2.advance();
157 }
158 }
159
160 if (!input1.eof()) {
161 files_same = false;
162 input1.dump("< ");
163 } else if (!input2.eof()) {
164 files_same = false;
165 input2.dump("> ");
166 }
167
168 if (files_same) {
169 exit(0);
170 } else {
171 exit(1);
172 }
173 }