[libpng16] timepng usage message, ability to cache the test set

This makes tests slightly quicker by allowing the temporary file to be created
beforehand.

Signed-off-by: John Bowler <jbowler@acm.org>
This commit is contained in:
John Bowler 2016-02-27 21:35:29 -08:00 committed by Glenn Randers-Pehrson
parent 0df91242a2
commit 2a25fc41f6

View File

@ -304,114 +304,224 @@ static int add_one_file(FILE *fp, char *name)
return 1; return 1;
} }
static void
usage(FILE *fp)
{
if (fp != NULL) fclose(fp);
fprintf(stderr,
"Usage:\n"
" timepng --assemble <assembly> {files}\n"
" Read the files into <assembly>, output the count. Options are ignored.\n"
" timepng --dissemble <assembly> <count> [options]\n"
" Time <count> files from <assembly>, additional files may not be given.\n"
" Otherwise:\n"
" Read the files into a temporary file and time the decode\n"
"Transforms:\n"
" --by-image: read by image with png_read_png\n"
" --<transform>: implies by-image, use PNG_TRANSFORM_<transform>\n"
" Otherwise: read by row using png_read_row (to a single row buffer)\n"
"{files}:\n"
" PNG files to copy into the assembly and time. Invalid files are skipped\n"
" with appropriate error messages. If no files are given the list of files\n"
" is read from stdin with each file name terminated by a newline\n"
"Output:\n"
" For --assemble the output is the name of the assembly file followed by the\n"
" count of the files it contains; the arguments for --dissemble. Otherwise\n"
" the output is the total decode time in seconds.\n");
exit(99);
}
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
int ok = 0; int ok = 0;
int err = 0;
int nfiles = 0;
int transforms = -1; /* by row */ int transforms = -1; /* by row */
FILE *fp = tmpfile(); const char *assembly = NULL;
FILE *fp;
if (fp != NULL) if (argc > 2 && strcmp(argv[1], "--assemble") == 0)
{ {
int err = 0; /* Just build the test file, argv[2] is the file name. */
int nfiles = 0; assembly = argv[2];
fp = fopen(assembly, "wb");
/* Remove and handle options first: */ if (fp == NULL)
while (argc > 1 && argv[1][0] == '-' && argv[1][1] == '-')
{ {
const char *opt = *++argv + 2; perror(assembly);
fprintf(stderr, "timepng --assemble %s: could not open for write\n",
assembly);
usage(NULL);
}
--argc; argv += 2;
argc -= 2;
}
/* Options turn on the by-image processing and maybe set some else if (argc > 3 && strcmp(argv[1], "--dissemble") == 0)
* transforms: {
*/ fp = fopen(argv[2], "rb");
if (transforms == -1)
transforms = PNG_TRANSFORM_IDENTITY;
if (strcmp(opt, "by-image") == 0) if (fp == NULL)
{ {
/* handled above */ perror(argv[2]);
} fprintf(stderr, "timepng --dissemble %s: could not open for read\n",
argv[2]);
usage(NULL);
}
nfiles = atoi(argv[3]);
if (nfiles <= 0)
{
fprintf(stderr,
"timepng --dissemble <file> <count>: %s is not a count\n",
argv[3]);
exit(99);
}
argv += 3;
argc -= 3;
}
else /* Else use a temporary file */
{
fp = tmpfile();
if (fp == NULL)
{
perror("tmpfile");
fprintf(stderr, "timepng: could not open the temporary file\n");
exit(1); /* not a user error */
}
}
/* Handle the transforms: */
while (argc > 1 && argv[1][0] == '-' && argv[1][1] == '-')
{
const char *opt = *++argv + 2;
--argc;
/* Transforms turn on the by-image processing and maybe set some
* transforms:
*/
if (transforms == -1)
transforms = PNG_TRANSFORM_IDENTITY;
if (strcmp(opt, "by-image") == 0)
{
/* handled above */
}
# define OPT(name) else if (strcmp(opt, #name) == 0)\ # define OPT(name) else if (strcmp(opt, #name) == 0)\
transforms |= PNG_TRANSFORM_ ## name transforms |= PNG_TRANSFORM_ ## name
OPT(STRIP_16); OPT(STRIP_16);
OPT(STRIP_ALPHA); OPT(STRIP_ALPHA);
OPT(PACKING); OPT(PACKING);
OPT(PACKSWAP); OPT(PACKSWAP);
OPT(EXPAND); OPT(EXPAND);
OPT(INVERT_MONO); OPT(INVERT_MONO);
OPT(SHIFT); OPT(SHIFT);
OPT(BGR); OPT(BGR);
OPT(SWAP_ALPHA); OPT(SWAP_ALPHA);
OPT(SWAP_ENDIAN); OPT(SWAP_ENDIAN);
OPT(INVERT_ALPHA); OPT(INVERT_ALPHA);
OPT(STRIP_FILLER); OPT(STRIP_FILLER);
OPT(STRIP_FILLER_BEFORE); OPT(STRIP_FILLER_BEFORE);
OPT(STRIP_FILLER_AFTER); OPT(STRIP_FILLER_AFTER);
OPT(GRAY_TO_RGB); OPT(GRAY_TO_RGB);
OPT(EXPAND_16); OPT(EXPAND_16);
OPT(SCALE_16); OPT(SCALE_16);
}
if (argc > 1)
{
int i;
for (i=1; i<argc; ++i)
{
if (add_one_file(fp, argv[i]))
++nfiles;
}
}
else else
{ {
char filename[FILENAME_MAX+1]; fprintf(stderr, "timepng %s: unrecognized transform\n", opt);
usage(fp);
}
}
while (fgets(filename, FILENAME_MAX+1, stdin)) /* Handle the files: */
if (argc > 1 && nfiles > 0)
usage(fp); /* Additional files not valid with --dissemble */
else if (argc > 1)
{
int i;
for (i=1; i<argc; ++i)
{
if (add_one_file(fp, argv[i]))
++nfiles;
}
}
else if (nfiles == 0) /* Read from stdin withoout --dissemble */
{
char filename[FILENAME_MAX+1];
while (fgets(filename, FILENAME_MAX+1, stdin))
{
size_t len = strlen(filename);
if (filename[len-1] == '\n')
{ {
size_t len = strlen(filename); filename[len-1] = 0;
if (add_one_file(fp, filename))
++nfiles;
}
if (filename[len-1] == '\n') else
{
fprintf(stderr, "timepng: file name too long: ...%s\n",
filename+len-32);
err = 1;
break;
}
}
if (ferror(stdin))
{
fprintf(stderr, "timepng: stdin: read error\n");
err = 1;
}
}
/* Perform the test, or produce the --assemble output: */
if (!err)
{
if (nfiles > 0)
{
if (assembly != NULL)
{
if (fflush(fp) && !ferror(fp) && fclose(fp))
{ {
filename[len-1] = 0; perror(assembly);
if (add_one_file(fp, filename)) fprintf(stderr, "%s: close failed\n", assembly);
++nfiles;
} }
else else
{ {
fprintf(stderr, "timepng: file name too long: ...%s\n", printf("%s %d\n", assembly, nfiles);
filename+len-32); fflush(stdout);
err = 1; ok = !ferror(stdout);
break;
} }
} }
if (ferror(stdin)) else
{ {
fprintf(stderr, "timepng: stdin: read error\n"); ok = perform_one_test(fp, nfiles, transforms);
err = 1; (void)fclose(fp);
} }
} }
if (!err) else
{ usage(fp);
if (nfiles > 0)
ok = perform_one_test(fp, nfiles, transforms);
else
fprintf(stderr, "usage: timepng [options] {files}\n"
" or: ls files | timepng [options]\n");
}
(void)fclose(fp);
} }
else else
fprintf(stderr, "timepng: could not open temporary file\n"); (void)fclose(fp);
/* Exit code 0 on success. */ /* Exit code 0 on success. */
return ok == 0; return ok == 0;