1b8bc0d8aSopenharmony_ci/** \file test-parse.c
2b8bc0d8aSopenharmony_ci * \brief Completely parse all files given on the command line.
3b8bc0d8aSopenharmony_ci *
4b8bc0d8aSopenharmony_ci * Copyright (C) 2007 Hans Ulrich Niedermann <gp@n-dimensional.de>
5b8bc0d8aSopenharmony_ci *
6b8bc0d8aSopenharmony_ci * This library is free software; you can redistribute it and/or
7b8bc0d8aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public
8b8bc0d8aSopenharmony_ci * License as published by the Free Software Foundation; either
9b8bc0d8aSopenharmony_ci * version 2 of the License, or (at your option) any later version.
10b8bc0d8aSopenharmony_ci *
11b8bc0d8aSopenharmony_ci * This library is distributed in the hope that it will be useful,
12b8bc0d8aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of
13b8bc0d8aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14b8bc0d8aSopenharmony_ci * Lesser General Public License for more details.
15b8bc0d8aSopenharmony_ci *
16b8bc0d8aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public
17b8bc0d8aSopenharmony_ci * License along with this library; if not, write to the
18b8bc0d8aSopenharmony_ci * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19b8bc0d8aSopenharmony_ci * Boston, MA  02110-1301  USA.
20b8bc0d8aSopenharmony_ci *
21b8bc0d8aSopenharmony_ci */
22b8bc0d8aSopenharmony_ci
23b8bc0d8aSopenharmony_ci#include "libexif/exif-data.h"
24b8bc0d8aSopenharmony_ci#include "libexif/exif-system.h"
25b8bc0d8aSopenharmony_ci
26b8bc0d8aSopenharmony_ci#include <string.h>
27b8bc0d8aSopenharmony_ci#include <stdio.h>
28b8bc0d8aSopenharmony_ci#include <stdlib.h>
29b8bc0d8aSopenharmony_ci
30b8bc0d8aSopenharmony_cistatic unsigned entry_count;
31b8bc0d8aSopenharmony_ci
32b8bc0d8aSopenharmony_ci/** Callback function handling an ExifEntry. */
33b8bc0d8aSopenharmony_cistatic void content_foreach_func(ExifEntry *entry, void *UNUSED(callback_data))
34b8bc0d8aSopenharmony_ci{
35b8bc0d8aSopenharmony_ci  char buf[2000];
36b8bc0d8aSopenharmony_ci  exif_entry_get_value(entry, buf, sizeof(buf));
37b8bc0d8aSopenharmony_ci  printf("    Entry %u: %s (%s)\n"
38b8bc0d8aSopenharmony_ci	 "      Size, Comps: %d, %d\n"
39b8bc0d8aSopenharmony_ci	 "      Value: %s\n",
40b8bc0d8aSopenharmony_ci	 entry_count,
41b8bc0d8aSopenharmony_ci	 exif_tag_get_name(entry->tag),
42b8bc0d8aSopenharmony_ci	 exif_format_get_name(entry->format),
43b8bc0d8aSopenharmony_ci	 entry->size,
44b8bc0d8aSopenharmony_ci	 (int)(entry->components),
45b8bc0d8aSopenharmony_ci	 exif_entry_get_value(entry, buf, sizeof(buf)));
46b8bc0d8aSopenharmony_ci  ++entry_count;
47b8bc0d8aSopenharmony_ci}
48b8bc0d8aSopenharmony_ci
49b8bc0d8aSopenharmony_ci
50b8bc0d8aSopenharmony_ci/** Callback function handling an ExifContent (corresponds 1:1 to an IFD). */
51b8bc0d8aSopenharmony_cistatic void data_foreach_func(ExifContent *content, void *callback_data)
52b8bc0d8aSopenharmony_ci{
53b8bc0d8aSopenharmony_ci  static unsigned content_count;
54b8bc0d8aSopenharmony_ci  entry_count = 0;
55b8bc0d8aSopenharmony_ci  printf("  Content %u: ifd=%d\n", content_count, exif_content_get_ifd(content));
56b8bc0d8aSopenharmony_ci  exif_content_foreach_entry(content, content_foreach_func, callback_data);
57b8bc0d8aSopenharmony_ci  ++content_count;
58b8bc0d8aSopenharmony_ci}
59b8bc0d8aSopenharmony_ci
60b8bc0d8aSopenharmony_cistatic void dump_makernote(ExifData *d) {
61b8bc0d8aSopenharmony_ci  ExifMnoteData *mn = exif_data_get_mnote_data(d);
62b8bc0d8aSopenharmony_ci  if (mn) {
63b8bc0d8aSopenharmony_ci    char buf[2000];
64b8bc0d8aSopenharmony_ci    int i;
65b8bc0d8aSopenharmony_ci    int num = exif_mnote_data_count(mn);
66b8bc0d8aSopenharmony_ci    printf("  MakerNote\n");
67b8bc0d8aSopenharmony_ci    for (i=0; i < num; ++i) {
68b8bc0d8aSopenharmony_ci      if (exif_mnote_data_get_value(mn, i, buf, sizeof(buf))) {
69b8bc0d8aSopenharmony_ci	const char *name = exif_mnote_data_get_name(mn, i);
70b8bc0d8aSopenharmony_ci	unsigned int id = exif_mnote_data_get_id(mn, i);
71b8bc0d8aSopenharmony_ci	if (!name)
72b8bc0d8aSopenharmony_ci	    name = "(unknown)";
73b8bc0d8aSopenharmony_ci	printf("    Entry %u: %u, %s\n"
74b8bc0d8aSopenharmony_ci	       "      Size: %u\n"
75b8bc0d8aSopenharmony_ci	       "      Value: %s\n", i, id, name, (unsigned)strlen(buf), buf);
76b8bc0d8aSopenharmony_ci      }
77b8bc0d8aSopenharmony_ci    }
78b8bc0d8aSopenharmony_ci  }
79b8bc0d8aSopenharmony_ci}
80b8bc0d8aSopenharmony_ci
81b8bc0d8aSopenharmony_ci/** Run EXIF parsing test on the given file. */
82b8bc0d8aSopenharmony_cistatic void test_parse(const char *filename, void *callback_data, int swap)
83b8bc0d8aSopenharmony_ci{
84b8bc0d8aSopenharmony_ci  ExifData *d;
85b8bc0d8aSopenharmony_ci
86b8bc0d8aSopenharmony_ci  /* Skip over path to display only the file name */
87b8bc0d8aSopenharmony_ci  const char *fn = strrchr(filename, '/');
88b8bc0d8aSopenharmony_ci  if (fn)
89b8bc0d8aSopenharmony_ci    ++fn;
90b8bc0d8aSopenharmony_ci  else
91b8bc0d8aSopenharmony_ci    fn = filename;
92b8bc0d8aSopenharmony_ci  printf("File %s\n", fn);
93b8bc0d8aSopenharmony_ci
94b8bc0d8aSopenharmony_ci  d = exif_data_new_from_file(filename);
95b8bc0d8aSopenharmony_ci  if (!d) {
96b8bc0d8aSopenharmony_ci      fprintf (stderr, "Could not load data from '%s'!\n", filename);
97b8bc0d8aSopenharmony_ci      return;
98b8bc0d8aSopenharmony_ci  }
99b8bc0d8aSopenharmony_ci  printf("Byte order: %s\n",
100b8bc0d8aSopenharmony_ci          exif_byte_order_get_name(exif_data_get_byte_order(d)));
101b8bc0d8aSopenharmony_ci
102b8bc0d8aSopenharmony_ci  if (swap) {
103b8bc0d8aSopenharmony_ci      ExifByteOrder order = EXIF_BYTE_ORDER_INTEL;
104b8bc0d8aSopenharmony_ci      if (exif_data_get_byte_order(d) == order) {
105b8bc0d8aSopenharmony_ci          order = EXIF_BYTE_ORDER_MOTOROLA;
106b8bc0d8aSopenharmony_ci      }
107b8bc0d8aSopenharmony_ci      /* This switches the byte order of the entire EXIF data structure,
108b8bc0d8aSopenharmony_ci       * including the MakerNote */
109b8bc0d8aSopenharmony_ci      exif_data_set_byte_order(d, order);
110b8bc0d8aSopenharmony_ci      printf("New byte order: %s\n",
111b8bc0d8aSopenharmony_ci              exif_byte_order_get_name(exif_data_get_byte_order(d)));
112b8bc0d8aSopenharmony_ci  }
113b8bc0d8aSopenharmony_ci
114b8bc0d8aSopenharmony_ci  exif_data_foreach_content(d, data_foreach_func, callback_data);
115b8bc0d8aSopenharmony_ci
116b8bc0d8aSopenharmony_ci  dump_makernote(d);
117b8bc0d8aSopenharmony_ci
118b8bc0d8aSopenharmony_ci  exif_data_unref(d);
119b8bc0d8aSopenharmony_ci}
120b8bc0d8aSopenharmony_ci
121b8bc0d8aSopenharmony_ci
122b8bc0d8aSopenharmony_ci/** Callback function prototype for string parsing. */
123b8bc0d8aSopenharmony_citypedef void (*test_parse_func) (const char *filename, void *callback_data, int swap);
124b8bc0d8aSopenharmony_ci
125b8bc0d8aSopenharmony_ci
126b8bc0d8aSopenharmony_ci/** Split string at whitespace and call callback with each substring. */
127b8bc0d8aSopenharmony_cistatic void split_ws_string(const char *string, test_parse_func func, void *callback_data)
128b8bc0d8aSopenharmony_ci{
129b8bc0d8aSopenharmony_ci  const char *start = string;
130b8bc0d8aSopenharmony_ci  const char *p = start;
131b8bc0d8aSopenharmony_ci  for (;;) {
132b8bc0d8aSopenharmony_ci    if (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r' || *p == '\0' ) {
133b8bc0d8aSopenharmony_ci      size_t len = p-start;
134b8bc0d8aSopenharmony_ci      if (len > 0) {
135b8bc0d8aSopenharmony_ci	/* emulate strndup */
136b8bc0d8aSopenharmony_ci	char *str = malloc(1+len);
137b8bc0d8aSopenharmony_ci	if (str) {
138b8bc0d8aSopenharmony_ci	  memcpy(str, start, len);
139b8bc0d8aSopenharmony_ci	  str[len] = '\0';
140b8bc0d8aSopenharmony_ci	  func(str, callback_data, 0);
141b8bc0d8aSopenharmony_ci	  free(str);
142b8bc0d8aSopenharmony_ci	  start = p+1;
143b8bc0d8aSopenharmony_ci	}
144b8bc0d8aSopenharmony_ci      } else {
145b8bc0d8aSopenharmony_ci	start = p+1;
146b8bc0d8aSopenharmony_ci      }
147b8bc0d8aSopenharmony_ci    }
148b8bc0d8aSopenharmony_ci    if (*p == '\0') {
149b8bc0d8aSopenharmony_ci      break;
150b8bc0d8aSopenharmony_ci    }
151b8bc0d8aSopenharmony_ci    p++;
152b8bc0d8aSopenharmony_ci  }
153b8bc0d8aSopenharmony_ci}
154b8bc0d8aSopenharmony_ci
155b8bc0d8aSopenharmony_ci
156b8bc0d8aSopenharmony_ci/** Main program. */
157b8bc0d8aSopenharmony_ciint main(const int argc, const char *argv[])
158b8bc0d8aSopenharmony_ci{
159b8bc0d8aSopenharmony_ci  int i;
160b8bc0d8aSopenharmony_ci  void *callback_data = NULL;
161b8bc0d8aSopenharmony_ci  int swap = 0;
162b8bc0d8aSopenharmony_ci  int first = 1;
163b8bc0d8aSopenharmony_ci
164b8bc0d8aSopenharmony_ci  if (argc > 1 && !strcmp(argv[1], "--swap-byte-order")) {
165b8bc0d8aSopenharmony_ci      swap = 1;
166b8bc0d8aSopenharmony_ci      ++first;
167b8bc0d8aSopenharmony_ci  }
168b8bc0d8aSopenharmony_ci
169b8bc0d8aSopenharmony_ci  if (argc > first) {
170b8bc0d8aSopenharmony_ci    for (i=first; i<argc; i++) {
171b8bc0d8aSopenharmony_ci      test_parse(argv[i], callback_data, swap);
172b8bc0d8aSopenharmony_ci    }
173b8bc0d8aSopenharmony_ci  } else {
174b8bc0d8aSopenharmony_ci    /* If no command-line argument is found, get the file names from
175b8bc0d8aSopenharmony_ci       the environment. */
176b8bc0d8aSopenharmony_ci    const char *envar = getenv("TEST_IMAGES");
177b8bc0d8aSopenharmony_ci    if (envar) {
178b8bc0d8aSopenharmony_ci      split_ws_string(envar, test_parse, callback_data);
179b8bc0d8aSopenharmony_ci    }
180b8bc0d8aSopenharmony_ci  }
181b8bc0d8aSopenharmony_ci
182b8bc0d8aSopenharmony_ci  return 0;
183b8bc0d8aSopenharmony_ci}
184