"examples/vscode:/vscode.git/clone" did not exist on "a4d5b59f132126c06c1a6b1f266ee44c70440cce"
compress_stream_ex.cpp 9.04 KB
Newer Older
1
// The contents of this file are in the public domain. See LICENSE_FOR_EXAMPLE_PROGRAMS.txt
2
3
4
5
6
7
8
9
10
11
/*

    This is an example illustrating the use of the compress_stream and
    cmd_line_parser components from the dlib C++ Library.  

    This example implements a simple command line compression utility.


    The output from the program when the -h option is given is:

12
        Usage: compress_stream_ex (-c|-d|-l) --in input_file --out output_file
13
        Options:
14
15
16
17
18
19
20
21
22
          -c            Indicates that we want to compress a file. 
          -d            Indicates that we want to decompress a file. 
          -h            Display this help message. 
          --in <arg>    This option takes one argument which specifies the name of the 
                        file we want to compress/decompress. 
          -l <arg>      Set the compression level [1-3], 3 is max compression, default 
                        is 2. 
          --out <arg>   This option takes one argument which specifies the name of the 
                        output file. 
23
24
25
26
27
28
29
30
31
32
33
*/




#include "dlib/compress_stream.h"
#include "dlib/cmd_line_parser.h"
#include <iostream>
#include <fstream>
#include <string>

Davis King's avatar
Davis King committed
34
// I am making a typedefs for the versions of compress_stream I want to use.  
35
36
37
typedef dlib::compress_stream::kernel_1da cs1;
typedef dlib::compress_stream::kernel_1ea cs2;
typedef dlib::compress_stream::kernel_1ec cs3;
38

39
40
41
42
43
44
// Here I am making another typedef, this time for the version of
// cmd_line_parser I want to use.  This version gives me a
// command line parser object that has all the available extensions
// for command line parsers applied to it.  So I will be able to use
// its command line validation utilities as well as option printing.
typedef dlib::cmd_line_parser<char>::check_1a_c clp;
45
46
47
48
49
50
51
52
53
54
55
56


using namespace std;
using namespace dlib;


int main(int argc, char** argv)
{  
    try
    {
        clp parser;

57
58
        // first I will define the command line options I want.  
        // Add a -c option and tell the parser what the option is for.
59
60
        parser.add_option("c","Indicates that we want to compress a file.");
        parser.add_option("d","Indicates that we want to decompress a file.");
61
        // add a --in option that takes 1 argument
62
        parser.add_option("in","This option takes one argument which specifies the name of the file we want to compress/decompress.",1);
63
        // add a --out option that takes 1 argument
64
65
        parser.add_option("out","This option takes one argument which specifies the name of the output file.",1);
        parser.add_option("h","Display this help message.");
66
        parser.add_option("l","Set the compression level [1-3], 3 is max compression, default is 2.",1);
67

68

69
70
71
        // now I will parse the command line
        parser.parse(argc,argv);

72
73
74

        // Now I will use the parser to validate some things about the command line.
        // If any of the following checks fail then an exception will be thrown and it will
Davis King's avatar
Davis King committed
75
        // contain a message that tells the user what the problem was.
76
77
78
79

        // First I want to check that none of the options were given on the command line
        // more than once.  To do this I define an array that contains the options
        // that shouldn't appear more than once and then I just call check_one_time_options()
Davis King's avatar
Davis King committed
80
        const char* one_time_opts[] = {"c", "d", "in", "out", "h", "l"};
81
82
83
84
        parser.check_one_time_options(one_time_opts);
        // Here I'm checking that the user didn't pick both the c and d options at the
        // same time. 
        parser.check_incompatible_options("c", "d");
85
86

        // Here I'm checking that the argument to the l option is an integer in the range 1 to 3.  
87
        // That is, it should be convertible to an int by dlib::string_assign and be either 
88
89
90
91
        // 1, 2, or 3.  Note that if you wanted to allow floating point values in the range 1 to 
        // 3 then you could give a range 1.0 to 3.0 or explicitly supply a type of float or double 
        // to the template argument of the check_option_arg_range() function.
        parser.check_option_arg_range("l", 1, 3);
92

Davis King's avatar
Davis King committed
93
94
95
96
97
        // The 'l' option is a sub-option of the 'c' option. That is, you can only select the
        // compression level when compressing.  This command below checks that the listed
        // sub options are always given in the presence of their parent options.
        const char* c_sub_opts[] = {"l"};
        parser.check_sub_options("c", c_sub_opts);
98

99
100
101
102
        // check if the -h option was given on the command line
        if (parser.option("h"))
        {
            // display all the command line options
103
            cout << "Usage: compress_stream_ex (-c|-d|-l) --in input_file --out output_file\n";
104
105
106
107
            // This function prints out a nicely formatted list of
            // all the options the parser has
            parser.print_options(cout); 
                                       
108
109
110
111
            cout << endl;
            return 0;
        }

112
        // Make some references to the options inside the parser.  This is just
Davis King's avatar
Davis King committed
113
        // for convenience so we don't have to type out the longer form below.  
114
115
116
117
118
        const clp::option_type& option_c = parser.option("c");
        const clp::option_type& option_d = parser.option("d");
        const clp::option_type& option_in = parser.option("in");
        const clp::option_type& option_out = parser.option("out");

119
120
121
        // Figure out what the compression level should be.  If the user didn't supply
        // this command line option then a value of 2 will be used. 
        int compression_level = get_option(parser,"l",2);
122
123
124



125
126
        // make sure one of the c or d options was given
        if (!option_c && !option_d)
127
128
129
130
131
132
133
134
135
136
137
138
        {
            cout << "Error in command line:\n   You must specify either the c option or the d option.\n";
            cout << "\nTry the -h option for more information." << endl;
            return 0;
        }


        string in_file;
        string out_file;

        // check if the user told us the input file and if they did then 
        // get the file name
139
        if (option_in)
140
141
142
143
144
145
146
147
148
149
150
151
152
        {
            in_file = option_in.argument();
        }
        else
        {
            cout << "Error in command line:\n   You must specify an input file.\n";
            cout << "\nTry the -h option for more information." << endl;
            return 0;
        }


        // check if the user told us the output file and if they did then 
        // get the file name
153
        if (option_out)
154
155
156
157
158
159
160
161
162
163
164
        {
            out_file = option_out.argument();
        }
        else
        {
            cout << "Error in command line:\n   You must specify an output file.\n";
            cout << "\nTry the -h option for more information." << endl;
            return 0;
        }


165
        // open the files we will be reading from and writing to
166
167
168
        ifstream fin(in_file.c_str(),ios::binary);
        ofstream fout(out_file.c_str(),ios::binary);

169
        // make sure the files opened correctly
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
        if (!fin)
        {
            cout << "Error opening file " << in_file << ".\n";
            return 0;
        }

        if (!fout)
        {
            cout << "Error creating file " << out_file << ".\n";
            return 0;
        }



        // now perform the actual compression or decompression.
        if (option_c)
        {
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
            // save the compression level to the output file
            serialize(compression_level, fout);

            switch (compression_level)
            {
                case 1:
                    {
                        cs1 compressor;
                        compressor.compress(fin,fout);
                    }break;
                case 2:
                    {
                        cs2 compressor;
                        compressor.compress(fin,fout);
                    }break;
                case 3:
                    {
                        cs3 compressor;
                        compressor.compress(fin,fout);
                    }break;
            }
208
209
210
        }
        else
        {
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
            // obtain the compression level from the input file
            deserialize(compression_level, fin);

            switch (compression_level)
            {
                case 1:
                    {
                        cs1 compressor;
                        compressor.decompress(fin,fout);
                    }break;
                case 2:
                    {
                        cs2 compressor;
                        compressor.decompress(fin,fout);
                    }break;
                case 3:
                    {
                        cs3 compressor;
                        compressor.decompress(fin,fout);
                    }break;
Davis King's avatar
Davis King committed
231
232
233
234
                default:
                    {
                        cout << "Error in compressed file, invalid compression level" << endl;
                    }break;
235
            }
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
        }


        

    }
    catch (exception& e)
    {
        // Note that this will catch any cmd_line_parse_error exceptions and print
        // the default message.   
        cout << e.what() << endl;
    }
    catch (...)
    {
        cout << "Some error occurred" << endl;
    }
}