#include <msp/io/buffered.h>
#include <msp/io/console.h>
#include <msp/io/file.h>
+#include <msp/datafile/packsource.h>
#include <msp/datafile/parser.h>
#include <msp/datafile/statement.h>
-#include <msp/datafile/writer.h>
#include "compiler.h"
+#include "packer.h"
#include "tool.h"
using namespace std;
using namespace Msp;
DataTool::DataTool(int argc, char **argv):
- in_fn("-"),
out_fn("-"),
binary(false),
- compile(false)
+ compile(false),
+ float_size(0),
+ compress(false),
+ pack(false),
+ unpack(false),
+ debug(false)
{
GetOpt getopt;
- getopt.add_option('b', "binary", binary, GetOpt::NO_ARG);
- getopt.add_option('c', "compile", compile, GetOpt::NO_ARG);
- getopt.add_option('o', "output", out_fn, GetOpt::REQUIRED_ARG);
+ getopt.add_option('b', "binary", binary, GetOpt::NO_ARG).set_help("Produce a binary datafile");
+ getopt.add_option('c', "compile", compile, GetOpt::NO_ARG).set_help("Create a collection based on a template file");
+ getopt.add_option('f', "float-size", float_size, GetOpt::REQUIRED_ARG).set_help("Floating-point precision", "BITS");
+ getopt.add_option('g', "debug", debug, GetOpt::NO_ARG).set_help("Display control statements");
+ getopt.add_option('o', "output", out_fn, GetOpt::REQUIRED_ARG).set_help("Output to a file instead of stdout", "FILE");
+ getopt.add_option('p', "pack", pack, GetOpt::NO_ARG).set_help("Create a pack from multiple files");
+ getopt.add_option('u', "unpack", unpack, GetOpt::NO_ARG).set_help("Unpacks files from packs into the current directory");
+ getopt.add_option('z', "compress", compress, GetOpt::NO_ARG).set_help("Produce a compressed datafile");
+ getopt.add_argument("infile", in_fns, GetOpt::OPTIONAL_ARG).set_help("Files to process");
getopt(argc, argv);
- const vector<string> &args = getopt.get_args();
- if(!args.empty())
- in_fn = args[0];
+ if(compile+pack+unpack>1)
+ throw usage_error("Only one of -c, -p and -u may be specified");
+
+ if(pack && out_fn=="-")
+ throw usage_error("Can't write pack to stdout");
+
+ if(in_fns.empty())
+ in_fns.push_back("-");
+
+ if(unpack)
+ {
+ for(list<string>::const_iterator i=in_fns.begin(); i!=in_fns.end(); ++i)
+ if(*i=="-")
+ throw usage_error("Can't unpack from stdout");
+ }
}
int DataTool::main()
{
- IO::Base *in;
- if(in_fn=="-")
- in = &IO::cin;
+ if(pack)
+ do_pack();
+ else if(unpack)
+ do_unpack();
+ else if(compile)
+ do_compile();
else
- in = new IO::File(in_fn);
+ do_transfer();
- IO::Base *out;
- if(out_fn=="-")
- out = &IO::cout;
- else
- out = new IO::File(out_fn, IO::M_WRITE);
+ return 0;
+}
+void DataTool::do_transfer()
+{
+ IO::Base *out = open_output(out_fn);
+ DataFile::Writer *writer = create_writer(*out);
+
+ for(list<string>::const_iterator i=in_fns.begin(); i!=in_fns.end(); ++i)
{
- IO::Buffered in_buf(*in);
- DataFile::Parser parser(in_buf, in_fn);
- IO::Buffered out_buf(*out);
- DataFile::Writer writer(out_buf);
- if(binary)
- writer.set_binary(true);
-
- if(compile)
- {
- Compiler compiler(writer);
- compiler.load(parser);
- }
- else
+ IO::Base *in = open_input(*i);
+ DataFile::Parser parser(*in, *i);
+
+ while(parser)
{
- while(parser)
- {
- DataFile::Statement st = parser.parse();
- if(st.valid)
- {
- writer.write(st);
- out_buf.flush();
- }
- }
+ DataFile::Statement st = parser.parse(true);
+ if(st.valid && (!st.control || st.keyword=="__src" || debug))
+ writer->write(st);
}
+
+ delete in;
+ }
+
+ delete writer;
+ delete out;
+}
+
+void DataTool::do_compile()
+{
+ IO::Base *out = open_output(out_fn);
+ DataFile::Writer *writer = create_writer(*out);
+
+ Compiler compiler(*writer);
+ for(list<string>::const_iterator i=in_fns.begin(); i!=in_fns.end(); ++i)
+ {
+ IO::Base *in = open_input(*i);
+ DataFile::Parser parser(*in, *i);
+ compiler.load(parser);
+ delete in;
}
- if(in!=&IO::cin)
+ delete writer;
+ delete out;
+}
+
+void DataTool::do_pack()
+{
+ Packer packer(*this);
+ for(list<string>::const_iterator i=in_fns.begin(); i!=in_fns.end(); ++i)
+ packer.pack_file(*i);
+ packer.create_pack(out_fn);
+}
+
+void DataTool::do_unpack()
+{
+ DataFile::PackSource source;
+ for(list<string>::const_iterator i=in_fns.begin(); i!=in_fns.end(); ++i)
+ source.add_pack_file(*i);
+
+ list<DataFile::PackSource::FileInfo> files = source.list_files();
+ for(list<DataFile::PackSource::FileInfo>::const_iterator i=files.begin(); i!=files.end(); ++i)
+ {
+ IO::Seekable *in = source.open(i->name);
+ IO::Base *out = open_output(i->name);
+ char buf[16384];
+ while(1)
+ {
+ unsigned len = in->read(buf, sizeof(buf));
+ out->write(buf, len);
+ if(len<sizeof(buf))
+ break;
+ }
delete in;
- if(out!=&IO::cout)
delete out;
+ }
+}
- return 0;
+IO::Base *DataTool::open_output(const string &fn)
+{
+ if(fn=="-")
+ return new IO::Buffered(IO::cout);
+ else
+ return new IO::BufferedFile(fn, IO::M_WRITE);
}
-Application::RegApp<DataTool> DataTool::reg;
+IO::Base *DataTool::open_input(const string &fn)
+{
+ if(fn=="-")
+ return new IO::Buffered(IO::cin);
+ else
+ return new IO::BufferedFile(fn, IO::M_READ);
+}
+
+DataFile::Writer *DataTool::create_writer(IO::Base &out)
+{
+ DataFile::Writer *writer = new DataFile::Writer(out);
+ if(compress)
+ writer->set_compressed();
+ if(binary)
+ writer->set_binary(true);
+ if(float_size)
+ writer->set_float_precision(float_size);
+ return writer;
+}