]> git.tdb.fi Git - libs/datafile.git/blob - tool/tool.cpp
Cosmetic changes
[libs/datafile.git] / tool / tool.cpp
1 #include <msp/core/getopt.h>
2 #include <msp/fs/utils.h>
3 #include <msp/io/buffered.h>
4 #include <msp/io/console.h>
5 #include <msp/io/file.h>
6 #include <msp/datafile/packsource.h>
7 #include <msp/datafile/parser.h>
8 #include <msp/datafile/statement.h>
9 #include "builtingenerator.h"
10 #include "compiler.h"
11 #include "packer.h"
12 #include "tool.h"
13
14 using namespace std;
15 using namespace Msp;
16
17 DataTool::DataTool(int argc, char **argv):
18         out_fn("-"),
19         binary(false),
20         compile(false),
21         float_size(0),
22         compress(false),
23         pack(false),
24         unpack(false),
25         debug(false)
26 {
27         GetOpt getopt;
28         getopt.add_option('b', "binary", binary, GetOpt::NO_ARG).set_help("Produce a binary datafile");
29         getopt.add_option('c', "compile", compile, GetOpt::NO_ARG).set_help("Create a collection based on a template file");
30         getopt.add_option('f', "float-size", float_size, GetOpt::REQUIRED_ARG).set_help("Floating-point precision", "BITS");
31         getopt.add_option('g', "debug", debug, GetOpt::NO_ARG).set_help("Display control statements");
32         getopt.add_option('i', "builtin", builtin, GetOpt::NO_ARG).set_help("Generate a source file for a BuiltinSource");
33         getopt.add_option('m', "module", builtin_module, GetOpt::REQUIRED_ARG).set_help("Name of the builtin source module");
34         getopt.add_option('n', "namespace", builtin_ns, GetOpt::REQUIRED_ARG).set_help("Namespace for the builtin source");
35         getopt.add_option('o', "output", out_fn, GetOpt::REQUIRED_ARG).set_help("Output to a file instead of stdout", "FILE");
36         getopt.add_option('p', "pack", pack, GetOpt::NO_ARG).set_help("Create a pack from multiple files");
37         getopt.add_option('u', "unpack", unpack, GetOpt::NO_ARG).set_help("Unpacks files from packs into the current directory");
38         getopt.add_option('z', "compress", compress, GetOpt::NO_ARG).set_help("Produce a compressed datafile");
39         getopt.add_argument("infile", in_fns, GetOpt::OPTIONAL_ARG).set_help("Files to process");
40         getopt(argc, argv);
41
42         if(compile+pack+unpack+builtin>1)
43                 throw usage_error("Only one of -c, -p, -u and -i may be specified");
44
45         if(pack && out_fn=="-")
46                 throw usage_error("Can't write pack to stdout");
47
48         if(in_fns.empty())
49                 in_fns.push_back("-");
50
51         if(unpack)
52         {
53                 for(list<string>::const_iterator i=in_fns.begin(); i!=in_fns.end(); ++i)
54                         if(*i=="-")
55                                 throw usage_error("Can't unpack from stdout");
56         }
57
58         if(builtin && builtin_module.empty())
59         {
60                 if(out_fn=="-")
61                         throw usage_error("Can't determine builtin module name");
62                 else
63                         builtin_module = FS::basepart(FS::basename(out_fn));
64         }
65 }
66
67 int DataTool::main()
68 {
69         if(pack)
70                 do_pack();
71         else if(unpack)
72                 do_unpack();
73         else if(compile)
74                 do_compile();
75         else if(builtin)
76                 do_generate_builtin();
77         else
78                 do_transfer();
79
80         return 0;
81 }
82
83 void DataTool::do_transfer()
84 {
85         IO::Base *out = open_output(out_fn);
86         DataFile::Writer *writer = create_writer(*out);
87
88         for(list<string>::const_iterator i=in_fns.begin(); i!=in_fns.end(); ++i)
89         {
90                 IO::Base *in = open_input(*i);
91                 DataFile::Parser parser(*in, *i);
92
93                 while(parser)
94                 {
95                         DataFile::Statement st = parser.parse(true);
96                         if(st.valid && (!st.control || st.keyword=="__src" || debug))
97                                 writer->write(st);
98                 }
99
100                 delete in;
101         }
102
103         delete writer;
104         delete out;
105 }
106
107 void DataTool::do_compile()
108 {
109         IO::Base *out = open_output(out_fn);
110         DataFile::Writer *writer = create_writer(*out);
111
112         Compiler compiler(*writer);
113         for(list<string>::const_iterator i=in_fns.begin(); i!=in_fns.end(); ++i)
114         {
115                 IO::Base *in = open_input(*i);
116                 DataFile::Parser parser(*in, *i);
117                 compiler.load(parser);
118                 delete in;
119         }
120
121         delete writer;
122         delete out;
123 }
124
125 void DataTool::do_pack()
126 {
127         Packer packer(*this);
128         for(list<string>::const_iterator i=in_fns.begin(); i!=in_fns.end(); ++i)
129                 packer.pack_file(*i);
130         packer.create_pack(out_fn);
131 }
132
133 void DataTool::do_unpack()
134 {
135         DataFile::PackSource source;
136         for(list<string>::const_iterator i=in_fns.begin(); i!=in_fns.end(); ++i)
137                 source.add_pack_file(*i);
138
139         list<DataFile::PackSource::FileInfo> files = source.list_files();
140         for(list<DataFile::PackSource::FileInfo>::const_iterator i=files.begin(); i!=files.end(); ++i)
141         {
142                 IO::Seekable *in = source.open(i->name);
143                 IO::Base *out = open_output(i->name);
144                 char buf[16384];
145                 while(1)
146                 {
147                         unsigned len = in->read(buf, sizeof(buf));
148                         out->write(buf, len);
149                         if(len<sizeof(buf))
150                                 break;
151                 }
152                 delete in;
153                 delete out;
154         }
155 }
156
157 void DataTool::do_generate_builtin()
158 {
159         IO::Base *out = open_output(out_fn);
160         BuiltinGenerator generator(*out);
161         generator.begin(builtin_ns);
162         for(list<string>::const_iterator i=in_fns.begin(); i!=in_fns.end(); ++i)
163                 generator.add_file(*i);
164         generator.end(builtin_module);
165         delete out;
166 }
167
168 IO::Base *DataTool::open_output(const string &fn)
169 {
170         if(fn=="-")
171                 return new IO::Buffered(IO::cout);
172         else
173                 return new IO::BufferedFile(fn, IO::M_WRITE);
174 }
175
176 IO::Base *DataTool::open_input(const string &fn)
177 {
178         if(fn=="-")
179                 return new IO::Buffered(IO::cin);
180         else
181                 return new IO::BufferedFile(fn, IO::M_READ);
182 }
183
184 DataFile::Writer *DataTool::create_writer(IO::Base &out)
185 {
186         DataFile::Writer *writer = new DataFile::Writer(out);
187         if(compress)
188                 writer->set_compressed();
189         if(binary)
190                 writer->set_binary(true);
191         if(float_size)
192                 writer->set_float_precision(float_size);
193         return writer;
194 }