xref: /isa-l/igzip/igzip_file_perf.c (revision 55fbfabfc60f1002bc8133b730a59f6abd22cfce)
1660f49b0SGreg Tucker /**********************************************************************
2660f49b0SGreg Tucker   Copyright(c) 2011-2016 Intel Corporation All rights reserved.
3660f49b0SGreg Tucker 
4660f49b0SGreg Tucker   Redistribution and use in source and binary forms, with or without
5660f49b0SGreg Tucker   modification, are permitted provided that the following conditions
6660f49b0SGreg Tucker   are met:
7660f49b0SGreg Tucker     * Redistributions of source code must retain the above copyright
8660f49b0SGreg Tucker       notice, this list of conditions and the following disclaimer.
9660f49b0SGreg Tucker     * Redistributions in binary form must reproduce the above copyright
10660f49b0SGreg Tucker       notice, this list of conditions and the following disclaimer in
11660f49b0SGreg Tucker       the documentation and/or other materials provided with the
12660f49b0SGreg Tucker       distribution.
13660f49b0SGreg Tucker     * Neither the name of Intel Corporation nor the names of its
14660f49b0SGreg Tucker       contributors may be used to endorse or promote products derived
15660f49b0SGreg Tucker       from this software without specific prior written permission.
16660f49b0SGreg Tucker 
17660f49b0SGreg Tucker   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18660f49b0SGreg Tucker   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19660f49b0SGreg Tucker   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20660f49b0SGreg Tucker   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21660f49b0SGreg Tucker   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22660f49b0SGreg Tucker   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23660f49b0SGreg Tucker   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24660f49b0SGreg Tucker   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25660f49b0SGreg Tucker   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26660f49b0SGreg Tucker   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27660f49b0SGreg Tucker   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28660f49b0SGreg Tucker **********************************************************************/
29660f49b0SGreg Tucker 
3052f644d3SHailiang Wang #define _FILE_OFFSET_BITS 64
31660f49b0SGreg Tucker #include <stdio.h>
32660f49b0SGreg Tucker #include <stdlib.h>
33660f49b0SGreg Tucker #include <assert.h>
34660f49b0SGreg Tucker #include <string.h>
355d155804SRoy Oursler #include <getopt.h>
36660f49b0SGreg Tucker #include "igzip_lib.h"
37660f49b0SGreg Tucker #include "test.h"
38660f49b0SGreg Tucker 
39660f49b0SGreg Tucker #define BUF_SIZE 1024
40660f49b0SGreg Tucker 
414ae2d1beSRoy Oursler int level_size_buf[10] = {
424ae2d1beSRoy Oursler #ifdef ISAL_DEF_LVL0_DEFAULT
434ae2d1beSRoy Oursler         ISAL_DEF_LVL0_DEFAULT,
444ae2d1beSRoy Oursler #else
454ae2d1beSRoy Oursler         0,
464ae2d1beSRoy Oursler #endif
474ae2d1beSRoy Oursler #ifdef ISAL_DEF_LVL1_DEFAULT
484ae2d1beSRoy Oursler         ISAL_DEF_LVL1_DEFAULT,
494ae2d1beSRoy Oursler #else
504ae2d1beSRoy Oursler         0,
514ae2d1beSRoy Oursler #endif
524ae2d1beSRoy Oursler #ifdef ISAL_DEF_LVL2_DEFAULT
534ae2d1beSRoy Oursler         ISAL_DEF_LVL2_DEFAULT,
544ae2d1beSRoy Oursler #else
554ae2d1beSRoy Oursler         0,
564ae2d1beSRoy Oursler #endif
574ae2d1beSRoy Oursler #ifdef ISAL_DEF_LVL3_DEFAULT
584ae2d1beSRoy Oursler         ISAL_DEF_LVL3_DEFAULT,
594ae2d1beSRoy Oursler #else
604ae2d1beSRoy Oursler         0,
614ae2d1beSRoy Oursler #endif
624ae2d1beSRoy Oursler #ifdef ISAL_DEF_LVL4_DEFAULT
634ae2d1beSRoy Oursler         ISAL_DEF_LVL4_DEFAULT,
644ae2d1beSRoy Oursler #else
654ae2d1beSRoy Oursler         0,
664ae2d1beSRoy Oursler #endif
674ae2d1beSRoy Oursler #ifdef ISAL_DEF_LVL5_DEFAULT
684ae2d1beSRoy Oursler         ISAL_DEF_LVL5_DEFAULT,
694ae2d1beSRoy Oursler #else
704ae2d1beSRoy Oursler         0,
714ae2d1beSRoy Oursler #endif
724ae2d1beSRoy Oursler #ifdef ISAL_DEF_LVL6_DEFAULT
734ae2d1beSRoy Oursler         ISAL_DEF_LVL6_DEFAULT,
744ae2d1beSRoy Oursler #else
754ae2d1beSRoy Oursler         0,
764ae2d1beSRoy Oursler #endif
774ae2d1beSRoy Oursler #ifdef ISAL_DEF_LVL7_DEFAULT
784ae2d1beSRoy Oursler         ISAL_DEF_LVL7_DEFAULT,
794ae2d1beSRoy Oursler #else
804ae2d1beSRoy Oursler         0,
814ae2d1beSRoy Oursler #endif
824ae2d1beSRoy Oursler #ifdef ISAL_DEF_LVL8_DEFAULT
834ae2d1beSRoy Oursler         ISAL_DEF_LVL8_DEFAULT,
844ae2d1beSRoy Oursler #else
854ae2d1beSRoy Oursler         0,
864ae2d1beSRoy Oursler #endif
874ae2d1beSRoy Oursler #ifdef ISAL_DEF_LVL9_DEFAULT
884ae2d1beSRoy Oursler         ISAL_DEF_LVL9_DEFAULT,
894ae2d1beSRoy Oursler #else
904ae2d1beSRoy Oursler         0,
914ae2d1beSRoy Oursler #endif
924ae2d1beSRoy Oursler };
934ae2d1beSRoy Oursler 
94*55fbfabfSMarcel Cornu int
usage(void)95*55fbfabfSMarcel Cornu usage(void)
965d155804SRoy Oursler {
97*55fbfabfSMarcel Cornu         fprintf(stderr, "Usage: igzip_file_perf [options] <infile>\n"
985d155804SRoy Oursler                         "  -h        help\n"
995d155804SRoy Oursler                         "  -X        use compression level X with 0 <= X <= 1\n"
1005d155804SRoy Oursler                         "  -b <size> input buffer size, 0 buffers all the input\n"
10189f7c46cSGreg Tucker                         "  -i <time> time in seconds to benchmark (at least 0)\n"
1021500db75SColin Ian King                         "  -o <file> output file for compressed data\n"
103aa8b5193SRoy Oursler                         "  -d <file> dictionary file used by compression\n"
104aa8b5193SRoy Oursler                         "  -w <size> log base 2 size of history window, between 8 and 15\n");
105ed15402fSRoy Oursler 
1065d155804SRoy Oursler         exit(0);
1075d155804SRoy Oursler }
1085d155804SRoy Oursler 
109*55fbfabfSMarcel Cornu void
deflate_perf(struct isal_zstream * stream,uint8_t * inbuf,size_t infile_size,size_t inbuf_size,uint8_t * outbuf,size_t outbuf_size,int level,uint8_t * level_buf,int level_size,uint32_t hist_bits,uint8_t * dictbuf,size_t dictfile_size,struct isal_dict * dict_str,struct isal_hufftables * hufftables_custom)110*55fbfabfSMarcel Cornu deflate_perf(struct isal_zstream *stream, uint8_t *inbuf, size_t infile_size, size_t inbuf_size,
111*55fbfabfSMarcel Cornu              uint8_t *outbuf, size_t outbuf_size, int level, uint8_t *level_buf, int level_size,
112*55fbfabfSMarcel Cornu              uint32_t hist_bits, uint8_t *dictbuf, size_t dictfile_size, struct isal_dict *dict_str,
11319035917SGreg Tucker              struct isal_hufftables *hufftables_custom)
114699bb5bdSRoy Oursler {
115699bb5bdSRoy Oursler         int avail_in;
116699bb5bdSRoy Oursler         isal_deflate_init(stream);
117699bb5bdSRoy Oursler         stream->level = level;
118699bb5bdSRoy Oursler         stream->level_buf = level_buf;
119699bb5bdSRoy Oursler         stream->level_buf_size = level_size;
12019035917SGreg Tucker 
12119035917SGreg Tucker         if (COMP_OK != isal_deflate_reset_dict(stream, dict_str))
12219035917SGreg Tucker                 if (dictbuf != NULL)
12319035917SGreg Tucker                         isal_deflate_set_dict(stream, dictbuf, dictfile_size);
12419035917SGreg Tucker 
12519035917SGreg Tucker         stream->end_of_stream = 0;
12619035917SGreg Tucker         stream->flush = NO_FLUSH;
127699bb5bdSRoy Oursler         stream->next_out = outbuf;
128699bb5bdSRoy Oursler         stream->avail_out = outbuf_size;
129699bb5bdSRoy Oursler         stream->next_in = inbuf;
130699bb5bdSRoy Oursler         if (hufftables_custom != NULL)
131699bb5bdSRoy Oursler                 stream->hufftables = hufftables_custom;
132699bb5bdSRoy Oursler         stream->hist_bits = hist_bits;
133699bb5bdSRoy Oursler         avail_in = infile_size;
134699bb5bdSRoy Oursler 
135699bb5bdSRoy Oursler         while (avail_in > 0) {
136699bb5bdSRoy Oursler                 stream->avail_in = avail_in >= inbuf_size ? inbuf_size : avail_in;
137699bb5bdSRoy Oursler                 avail_in -= inbuf_size;
138699bb5bdSRoy Oursler 
139699bb5bdSRoy Oursler                 if (avail_in <= 0)
140699bb5bdSRoy Oursler                         stream->end_of_stream = 1;
141699bb5bdSRoy Oursler 
142699bb5bdSRoy Oursler                 isal_deflate(stream);
143699bb5bdSRoy Oursler 
144699bb5bdSRoy Oursler                 if (stream->avail_in != 0)
145699bb5bdSRoy Oursler                         break;
146699bb5bdSRoy Oursler         }
147699bb5bdSRoy Oursler }
148699bb5bdSRoy Oursler 
149*55fbfabfSMarcel Cornu int
main(int argc,char * argv[])150*55fbfabfSMarcel Cornu main(int argc, char *argv[])
151660f49b0SGreg Tucker {
152ed15402fSRoy Oursler         FILE *in = NULL, *out = NULL, *dict = NULL;
153ed15402fSRoy Oursler         unsigned char *inbuf, *outbuf, *level_buf = NULL, *dictbuf = NULL;
154699bb5bdSRoy Oursler         int c, time = BENCHMARK_TIME, inbuf_size = 0;
155699bb5bdSRoy Oursler         size_t infile_size, outbuf_size, dictfile_size;
156660f49b0SGreg Tucker         struct isal_huff_histogram histogram;
157660f49b0SGreg Tucker         struct isal_hufftables hufftables_custom;
158699bb5bdSRoy Oursler         int level = 0, level_size = 0;
159ed15402fSRoy Oursler         char *in_file_name = NULL, *out_file_name = NULL, *dict_file_name = NULL;
160aa8b5193SRoy Oursler         uint32_t hist_bits = 0;
161699bb5bdSRoy Oursler         struct isal_zstream stream;
162660f49b0SGreg Tucker 
163aa8b5193SRoy Oursler         while ((c = getopt(argc, argv, "h0123456789i:b:o:d:w:")) != -1) {
1644ae2d1beSRoy Oursler                 if (c >= '0' && c <= '9') {
1654ae2d1beSRoy Oursler                         if (c > '0' + ISAL_DEF_MAX_LEVEL)
1664ae2d1beSRoy Oursler                                 usage();
1674ae2d1beSRoy Oursler                         else {
1684ae2d1beSRoy Oursler                                 level = c - '0';
1694ae2d1beSRoy Oursler                                 level_size = level_size_buf[level];
1704ae2d1beSRoy Oursler                         }
1714ae2d1beSRoy Oursler                         continue;
1724ae2d1beSRoy Oursler                 }
1734ae2d1beSRoy Oursler 
1745d155804SRoy Oursler                 switch (c) {
1755d155804SRoy Oursler                 case 'o':
1765d155804SRoy Oursler                         out_file_name = optarg;
1775d155804SRoy Oursler                         break;
178ed15402fSRoy Oursler                 case 'd':
179ed15402fSRoy Oursler                         dict_file_name = optarg;
180ed15402fSRoy Oursler                         break;
1815d155804SRoy Oursler                 case 'i':
182699bb5bdSRoy Oursler                         time = atoi(optarg);
18389f7c46cSGreg Tucker                         if (time < 0)
1845d155804SRoy Oursler                                 usage();
1855d155804SRoy Oursler                         break;
1865d155804SRoy Oursler                 case 'b':
1875d155804SRoy Oursler                         inbuf_size = atoi(optarg);
1885d155804SRoy Oursler                         break;
189aa8b5193SRoy Oursler                 case 'w':
190aa8b5193SRoy Oursler                         hist_bits = atoi(optarg);
191aa8b5193SRoy Oursler                         if (hist_bits > 15 || hist_bits < 8)
192aa8b5193SRoy Oursler                                 usage();
193aa8b5193SRoy Oursler                         break;
1945d155804SRoy Oursler                 case 'h':
1955d155804SRoy Oursler                 default:
1965d155804SRoy Oursler                         usage();
1975d155804SRoy Oursler                         break;
198660f49b0SGreg Tucker                 }
1995d155804SRoy Oursler         }
2005d155804SRoy Oursler 
2015d155804SRoy Oursler         if (optind < argc) {
2025d155804SRoy Oursler                 in_file_name = argv[optind];
2035d155804SRoy Oursler                 in = fopen(in_file_name, "rb");
2045d155804SRoy Oursler         } else
2055d155804SRoy Oursler                 usage();
2065d155804SRoy Oursler 
207660f49b0SGreg Tucker         if (!in) {
2085d155804SRoy Oursler                 fprintf(stderr, "Can't open %s for reading\n", in_file_name);
209660f49b0SGreg Tucker                 exit(0);
210660f49b0SGreg Tucker         }
2115d155804SRoy Oursler         if (out_file_name != NULL) {
2125d155804SRoy Oursler                 out = fopen(out_file_name, "wb");
213660f49b0SGreg Tucker                 if (!out) {
2145d155804SRoy Oursler                         fprintf(stderr, "Can't open %s for writing\n", out_file_name);
215660f49b0SGreg Tucker                         exit(0);
216660f49b0SGreg Tucker                 }
2175d155804SRoy Oursler                 printf("outfile=%s\n", out_file_name);
218660f49b0SGreg Tucker         }
2195d155804SRoy Oursler 
220ed15402fSRoy Oursler         if (dict_file_name != NULL) {
221ed15402fSRoy Oursler                 dict = fopen(dict_file_name, "rb");
222ed15402fSRoy Oursler                 if (!dict) {
223ed15402fSRoy Oursler                         fprintf(stderr, "Can't open %s for reading\n", dict_file_name);
224ed15402fSRoy Oursler                         exit(0);
225ed15402fSRoy Oursler                 }
226ed15402fSRoy Oursler                 printf("outfile=%s\n", dict_file_name);
227ed15402fSRoy Oursler         }
228ed15402fSRoy Oursler 
229aa8b5193SRoy Oursler         if (hist_bits == 0)
2305d155804SRoy Oursler                 printf("Window Size: %d K\n", IGZIP_HIST_SIZE / 1024);
231aa8b5193SRoy Oursler 
232aa8b5193SRoy Oursler         else if (hist_bits < 10)
233aa8b5193SRoy Oursler                 printf("Window Size: %.2f K\n", 1.0 * (1 << hist_bits) / 1024);
234aa8b5193SRoy Oursler         else
235aa8b5193SRoy Oursler                 printf("Window Size: %d K\n", (1 << hist_bits) / 1024);
236aa8b5193SRoy Oursler 
237660f49b0SGreg Tucker         printf("igzip_file_perf: \n");
238660f49b0SGreg Tucker         fflush(0);
2395d155804SRoy Oursler 
240660f49b0SGreg Tucker         /* Allocate space for entire input file and output
241660f49b0SGreg Tucker          * (assuming some possible expansion on output size)
242660f49b0SGreg Tucker          */
243660f49b0SGreg Tucker         infile_size = get_filesize(in);
244660f49b0SGreg Tucker 
2455d155804SRoy Oursler         outbuf_size = 2 * infile_size + BUF_SIZE;
2465d155804SRoy Oursler 
24748d74d6eSGreg Tucker         dictfile_size = (dict_file_name != NULL) ? get_filesize(dict) : 0;
248ed15402fSRoy Oursler 
249660f49b0SGreg Tucker         inbuf = malloc(infile_size);
250660f49b0SGreg Tucker         if (inbuf == NULL) {
251660f49b0SGreg Tucker                 fprintf(stderr, "Can't allocate input buffer memory\n");
252660f49b0SGreg Tucker                 exit(0);
253660f49b0SGreg Tucker         }
254660f49b0SGreg Tucker         outbuf = malloc(outbuf_size);
255660f49b0SGreg Tucker         if (outbuf == NULL) {
256660f49b0SGreg Tucker                 fprintf(stderr, "Can't allocate output buffer memory\n");
257660f49b0SGreg Tucker                 exit(0);
258660f49b0SGreg Tucker         }
259660f49b0SGreg Tucker 
260ed15402fSRoy Oursler         if (dictfile_size != 0) {
261ed15402fSRoy Oursler                 dictbuf = malloc(dictfile_size);
262ed15402fSRoy Oursler                 if (dictbuf == NULL) {
263ed15402fSRoy Oursler                         fprintf(stderr, "Can't allocate dictionary buffer memory\n");
264ed15402fSRoy Oursler                         exit(0);
265ed15402fSRoy Oursler                 }
266ed15402fSRoy Oursler         }
267ed15402fSRoy Oursler 
2685d155804SRoy Oursler         if (level_size != 0) {
2695d155804SRoy Oursler                 level_buf = malloc(level_size);
2705d155804SRoy Oursler                 if (level_buf == NULL) {
2715d155804SRoy Oursler                         fprintf(stderr, "Can't allocate level buffer memory\n");
2725d155804SRoy Oursler                         exit(0);
2735d155804SRoy Oursler                 }
2745d155804SRoy Oursler         }
2755d155804SRoy Oursler 
2765d155804SRoy Oursler         inbuf_size = inbuf_size ? inbuf_size : infile_size;
2775d155804SRoy Oursler 
278699bb5bdSRoy Oursler         printf("igzip_file_perf: %s\n", in_file_name);
27948d74d6eSGreg Tucker 
280660f49b0SGreg Tucker         /* Read complete input file into buffer */
281660f49b0SGreg Tucker         stream.avail_in = (uint32_t) fread(inbuf, 1, infile_size, in);
282660f49b0SGreg Tucker         if (stream.avail_in != infile_size) {
283660f49b0SGreg Tucker                 fprintf(stderr, "Couldn't fit all of input file into buffer\n");
284660f49b0SGreg Tucker                 exit(0);
285660f49b0SGreg Tucker         }
286660f49b0SGreg Tucker 
28748d74d6eSGreg Tucker         /* Read complete dictionary into buffer */
28848d74d6eSGreg Tucker         if ((dictfile_size != 0) && (dictfile_size != fread(dictbuf, 1, dictfile_size, dict))) {
289ed15402fSRoy Oursler                 fprintf(stderr, "Couldn't fit all of dictionary file into buffer\n");
290ed15402fSRoy Oursler                 exit(0);
291ed15402fSRoy Oursler         }
292ed15402fSRoy Oursler 
29319035917SGreg Tucker         struct isal_dict dict_str;
29419035917SGreg Tucker         stream.level = level;
29519035917SGreg Tucker         isal_deflate_process_dict(&stream, &dict_str, dictbuf, dictfile_size);
29619035917SGreg Tucker 
297699bb5bdSRoy Oursler         struct perf start;
29889f7c46cSGreg Tucker         if (time > 0) {
299699bb5bdSRoy Oursler                 BENCHMARK(&start, time,
300699bb5bdSRoy Oursler                           deflate_perf(&stream, inbuf, infile_size, inbuf_size, outbuf, outbuf_size,
301699bb5bdSRoy Oursler                                        level, level_buf, level_size, hist_bits, dictbuf,
302*55fbfabfSMarcel Cornu                                        dictfile_size, &dict_str, NULL));
303*55fbfabfSMarcel Cornu         } else {
304*55fbfabfSMarcel Cornu                 deflate_perf(&stream, inbuf, infile_size, inbuf_size, outbuf, outbuf_size, level,
305*55fbfabfSMarcel Cornu                              level_buf, level_size, hist_bits, dictbuf, dictfile_size, &dict_str,
306*55fbfabfSMarcel Cornu                              NULL);
30789f7c46cSGreg Tucker         }
308660f49b0SGreg Tucker         if (stream.avail_in != 0) {
309660f49b0SGreg Tucker                 fprintf(stderr, "Could not compress all of inbuf\n");
310660f49b0SGreg Tucker                 exit(0);
311660f49b0SGreg Tucker         }
312660f49b0SGreg Tucker 
313*55fbfabfSMarcel Cornu         printf("  file %s - in_size=%lu out_size=%d ratio=%3.1f%%", in_file_name, infile_size,
314*55fbfabfSMarcel Cornu                stream.total_out, 100.0 * stream.total_out / infile_size);
3155d155804SRoy Oursler 
3165d155804SRoy Oursler         if (level == 0) {
3175d155804SRoy Oursler                 memset(&histogram, 0, sizeof(histogram));
318660f49b0SGreg Tucker 
319660f49b0SGreg Tucker                 isal_update_histogram(inbuf, infile_size, &histogram);
320660f49b0SGreg Tucker                 isal_create_hufftables(&hufftables_custom, &histogram);
321660f49b0SGreg Tucker 
322*55fbfabfSMarcel Cornu                 deflate_perf(&stream, inbuf, infile_size, inbuf_size, outbuf, outbuf_size, level,
323*55fbfabfSMarcel Cornu                              level_buf, level_size, hist_bits, dictbuf, dictfile_size, &dict_str,
324*55fbfabfSMarcel Cornu                              &hufftables_custom);
3255d155804SRoy Oursler 
3265d155804SRoy Oursler                 printf(" ratio_custom=%3.1f%%", 100.0 * stream.total_out / infile_size);
3275d155804SRoy Oursler         }
3285d155804SRoy Oursler         printf("\n");
329660f49b0SGreg Tucker 
330660f49b0SGreg Tucker         if (stream.avail_in != 0) {
331660f49b0SGreg Tucker                 fprintf(stderr, "Could not compress all of inbuf\n");
332660f49b0SGreg Tucker                 exit(0);
333660f49b0SGreg Tucker         }
334660f49b0SGreg Tucker 
335660f49b0SGreg Tucker         printf("igzip_file: ");
336699bb5bdSRoy Oursler         perf_print(start, (long long) infile_size);
337660f49b0SGreg Tucker 
338660f49b0SGreg Tucker         if (argc > 2 && out) {
3395d155804SRoy Oursler                 printf("writing %s\n", out_file_name);
340660f49b0SGreg Tucker                 fwrite(outbuf, 1, stream.total_out, out);
341660f49b0SGreg Tucker                 fclose(out);
342660f49b0SGreg Tucker         }
343660f49b0SGreg Tucker 
344660f49b0SGreg Tucker         fclose(in);
345660f49b0SGreg Tucker         printf("End of igzip_file_perf\n\n");
346660f49b0SGreg Tucker         fflush(0);
347660f49b0SGreg Tucker         return 0;
348660f49b0SGreg Tucker }
349