libtld 2.0.14
A library to determine the Top-Level Domain name of any Internet URI.
tldc.cpp
1/* TLD tools -- TLD, domain name, and sub-domain extraction
2 * Copyright (c) 2011-2025 Made to Order Software Corp. All Rights Reserved
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included
13 * in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23
24// libtld
25//
26#include <libtld/tld_compiler.h>
27#include <libtld/tld_file.h>
28
29
30// C++
31//
32#include <fstream>
33#include <iostream>
34#include <sstream>
35
36
37// C
38//
39#include <string.h>
40
41
43{
44public:
45 std::ostream & error();
46 int exit_code() const;
47 void set_input_path(std::string const & path);
48 void set_output(std::string const & output);
49 void set_c_file(std::string const & c);
50 void set_verify(bool verify);
51 void set_output_json(bool verify);
52 void set_include_offsets(bool include_offsets);
53 void set_verbose(bool verbose);
54
55 void run();
56
57private:
58 void verify_output(tld_compiler & c);
59
60 int f_errcnt = 0;
61 std::string f_input_path = std::string();
62 std::string f_output = std::string();
63 std::string f_c_file = std::string();
64 bool f_verify = false;
65 bool f_output_json = false;
66 bool f_include_offsets = false;
67 bool f_verbose = false;
68};
69
70
71std::ostream & compiler::error()
72{
73 ++f_errcnt;
74 return std::cerr;
75}
76
77
78int compiler::exit_code() const
79{
80 return f_errcnt == 0 ? 0 : 1;
81}
82
83
84void compiler::set_input_path(std::string const & path)
85{
86 f_input_path = path;
87}
88
89
90void compiler::set_output(std::string const & output)
91{
92 f_output = output;
93}
94
95
96void compiler::set_c_file(std::string const & c_file)
97{
98 f_c_file = c_file;
99}
100
101
102void compiler::set_verify(bool verify)
103{
104 f_verify = verify;
105}
106
107
108void compiler::set_output_json(bool output_json)
109{
110 f_output_json = output_json;
111}
112
113
114void compiler::set_include_offsets(bool include_offsets)
115{
116 f_include_offsets = include_offsets;
117}
118
119
120void compiler::set_verbose(bool verbose)
121{
122 f_verbose = verbose;
123}
124
125
126void compiler::run()
127{
128 if(f_errcnt != 0)
129 {
130 // command line found errors, return immediately
131 return;
132 }
133
134 if(f_input_path.empty())
135 {
136 ++f_errcnt;
137 std::cerr << "error: an input path is required.\n";
138 return;
139 }
140
141 if(f_output.empty())
142 {
143 ++f_errcnt;
144 std::cerr << "error: an output filename is required.\n";
145 return;
146 }
147
148 std::cout << "Compiling TLDs from \"" << f_input_path << "\"..." << std::endl;
149
150 tld_compiler c;
151 c.set_input_folder(f_input_path);
152 c.set_output(f_output);
153 c.set_c_file(f_c_file);
154 if(!c.compile())
155 {
156 ++f_errcnt;
157 std::cerr
158 << "error:"
159 << c.get_filename()
160 << ":"
161 << c.get_line()
162 << ": "
163 << c.get_errmsg()
164 << " (errno: "
165 << c.get_errno()
166 << ", "
167 << strerror(c.get_errno())
168 << ")\n";
169 return;
170 }
171
172 std::cout << "Number of strings: " << c.get_string_manager().size() << "\n";
173 std::cout << "Longest string: " << c.get_string_manager().max_length() << "\n";
174 std::cout << "Total string length: " << c.get_string_manager().total_length() << "\n";
175 std::cout << "Included strings: " << c.get_string_manager().included_count() << " (saved length: " << c.get_string_manager().included_length() << ")\n";
176 std::cout << "Mergeable strings: " << c.get_string_manager().merged_count() << " (saved length: " << c.get_string_manager().merged_length() << ")\n";
177 std::cout << "Compressed string length: " << c.get_string_manager().compressed_length() << std::endl;
178 // TODO: add info about tags
179
180 if(f_output_json)
181 {
182 std::string filename;
183 std::string::size_type const dot(f_output.rfind('.'));
184 if(dot != std::string::npos
185 && dot > 0
186 && f_output[dot - 1] != '/')
187 {
188 filename = f_output.substr(0, dot) + ".json";
189 }
190 else
191 {
192 filename = f_output + ".json";
193 }
194 std::ofstream out;
195 out.open(filename);
196 if(out.is_open())
197 {
198 c.output_to_json(out, f_include_offsets);
199 }
200 else
201 {
202 ++f_errcnt;
203 std::cerr
204 << "error: could not open JSON output file: \""
205 << filename
206 << "\".\n";
207 return;
208 }
209 }
210
211 if(f_verify)
212 {
213 verify_output(c);
214 }
215}
216
217
218void compiler::verify_output(tld_compiler & c)
219{
220 tld_file * file(nullptr);
221 auto_free_tld_file auto_free(&file);
222 tld_file_error err(tld_file_load(f_output.c_str(), &file));
223 if(err != TLD_FILE_ERROR_NONE)
224 {
225 ++f_errcnt;
226 std::cerr << "error: could not load output file \""
227 << f_output
228 << "\" -- err: "
229 << tld_file_errstr(err)
230 << " ("
231 << static_cast<int>(err)
232 << ").\n";
233 return;
234 }
235
236 // generate a JSON from what was just loaded
237 // and it has to match the compiler's JSON
238 //
239 char * json(tld_file_to_json(file));
240 if(json == nullptr)
241 {
242 ++f_errcnt;
243 std::cerr << "error: conversion of file to JSON failed.\n";
244 return;
245 }
246 auto_free_string auto_delete(json);
247
248 // save the verification JSON to a file if we also saved the
249 // JSON of the compiler to a file
250 //
251 if(f_output_json)
252 {
253 std::string filename;
254 std::string::size_type const dot(f_output.rfind('.'));
255 if(dot != std::string::npos
256 && dot > 0
257 && f_output[dot - 1] != '/')
258 {
259 filename = f_output.substr(0, dot) + "-verify.json";
260 }
261 else
262 {
263 filename = f_output + "-verify.json";
264 }
265 std::ofstream out;
266 out.open(filename);
267 if(out.is_open())
268 {
269 out.write(json, strlen(json));
270 }
271 else
272 {
273 ++f_errcnt;
274 std::cerr
275 << "error: could not open JSON output file: \""
276 << filename
277 << "\".\n";
278 return;
279 }
280 }
281
282 std::stringstream compiler_json;
283 c.output_to_json(compiler_json, false);
284
285 if(compiler_json.str() != json)
286 {
287 ++f_errcnt;
288 std::cerr
289 << "error: compiler & verification JSON differ."
290 << (f_output_json
291 ? " Check the two .json output files to see the differences."
292 : " Try using the --output-json command line option to get the .json files to find the differences.")
293 << "\n";
294 return;
295 }
296}
297
298
299
300
301void usage(char * argv0)
302{
303 std::string progname(argv0);
304 std::string::size_type pos(progname.rfind('/'));
305 if(pos != std::string::npos)
306 {
307 progname = progname.substr(pos + 1);
308 }
309 std::cout << progname << " v" << LIBTLD_VERSION << "\n";
310 std::cout << "Usage: " << progname << " [--opts] [<output>]\n";
311 std::cout << "Where --opts is one or more of the following:\n";
312 std::cout << " --help | -h prints out this help screen and exit\n";
313 std::cout << " --c-file path and filename to the \"tld_data.c\" file\n";
314 std::cout << " --include-offsets print offset in comment in .json file\n";
315 std::cout << " --output-json also save to a .json file\n";
316 std::cout << " --source | -s <folder> define the source (input) folder\n";
317 std::cout << " --verify verify loading results and compare against sources\n";
318 std::cout << " --verbose print out more information about what is happening\n";
319 std::cout << " --version | -V print out the version and exit\n";
320 std::cout << "\n";
321 std::cout << "The default source is \"/usr/share/libtld/tlds\".\n";
322 std::cout << "The default output is \"/var/lib/libtld/tlds.tld\".\n";
323 std::cout << progname << " will not output a C-file or JSON by default.\n";
324}
325
326
327int main(int argc, char * argv[])
328{
329 compiler tldc;
330
331 for(int i(1); i < argc; ++i)
332 {
333 if(argv[i][0] == '-')
334 {
335 if(strcmp(argv[i], "-h") == 0
336 || strcmp(argv[i], "--help") == 0)
337 {
338 usage(argv[0]);
339 return 1;
340 }
341 else if(strcmp(argv[i], "-V") == 0
342 || strcmp(argv[i], "--version") == 0)
343 {
344 std::cout << LIBTLD_VERSION << std::endl;
345 return 1;
346 }
347 else if(strcmp(argv[i], "-s") == 0
348 || strcmp(argv[i], "--source") == 0)
349 {
350 ++i;
351 if(i >= argc)
352 {
353 tldc.error()
354 << "error: argument missing for --source.\n";
355 }
356 else
357 {
358 tldc.set_input_path(argv[i]);
359 }
360 }
361 else if(strcmp(argv[i], "--verify") == 0)
362 {
363 tldc.set_verify(true);
364 }
365 else if(strcmp(argv[i], "--c-file") == 0)
366 {
367 ++i;
368 if(i >= argc)
369 {
370 tldc.error()
371 << "error: argument missing for --output-c-file.\n";
372 }
373 else
374 {
375 tldc.set_c_file(argv[i]);
376 }
377 }
378 else if(strcmp(argv[i], "--output-json") == 0)
379 {
380 tldc.set_output_json(true);
381 }
382 else if(strcmp(argv[i], "--include-offsets") == 0)
383 {
384 tldc.set_include_offsets(true);
385 }
386 else if(strcmp(argv[i], "--verbose") == 0)
387 {
388 tldc.set_verbose(true);
389 }
390 else
391 {
392 tldc.error()
393 << "error: unknown command line option \""
394 << argv[i]
395 << "\".\n";
396 }
397 }
398 else
399 {
400 tldc.set_output(argv[i]);
401 }
402 }
403
404 tldc.run();
405
406 return tldc.exit_code();
407}
408
409// vim: ts=4 sw=4 et
#define LIBTLD_VERSION
The version of the library as a string.
Definition tld.h:51
Implementation of the TLD parser library.
char * tld_file_to_json(tld_file const *file)
Transform a tld_file to a JSON string.
Definition tld_file.cpp:414
Declaration of the TLD file structures.
int verbose
Whether the user asked for verbosity, false by default.
void usage()
Print out the help of the tld tool.

This document is part of the Snap! Websites Project.

Copyright by Made to Order Software Corp.