1 /* utils.c
2 *
3 * Copyright (c) 2002 Lutz Mueller <lutz@users.sourceforge.net>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301 USA.
19 */
20
21 #include "config.h"
22 #include "utils.h"
23
24 #include <string.h>
25 #include <stdlib.h>
26 #include <stdio.h>
27
28 ExifTag
exif_tag_from_string(const char * string)29 exif_tag_from_string (const char *string)
30 {
31 ExifTag tag;
32 unsigned int i, number;
33 int t;
34 const char *name;
35
36 if (!string)
37 return EXIF_INVALID_TAG;
38
39 /* Is the string a decimal number? */
40 if (strspn (string, "0123456789") == strlen (string))
41 return (atoi (string));
42
43 /* Is the string a hexadecimal number? */
44 if (sscanf (string, "0x%x%n", &number, &i) == 1 && !string[i])
45 return ((ExifTag)number);
46
47 /* Is the string a tag's name? */
48 if ((tag = exif_tag_from_name (string)) != 0)
49 return (tag);
50
51 /* Is the string a tag's title? */
52 for (t = 0xffff; t >= 0; t--) {
53 tag = (ExifTag) t;
54 name = exif_tag_get_title (tag);
55 if (name && !strcmp (string, name))
56 return (tag);
57 }
58 return EXIF_INVALID_TAG;
59 }
60
61 ExifIfd
exif_ifd_from_string(const char * string)62 exif_ifd_from_string (const char *string)
63 {
64 unsigned int i;
65
66 if (!string)
67 return (-1);
68
69 for (i = 0; i < EXIF_IFD_COUNT; i++) {
70 if (!strcmp (string, exif_ifd_get_name (i)))
71 return (i);
72 }
73
74 return (-1);
75 }
76
77 /*! An alternative to exif_loader_get_data() that allows the options and
78 * data type to be set.
79 *
80 * \param[in] loader the loader
81 * \param[in] options one or more bitwise ORred options from ExifDataOption
82 * \param[in] dt image data type
83 * \return allocated ExifData
84 */
85 ExifData *
exif_get_data_opts(ExifLoader * loader,ExifLog * log,int options,ExifDataType dt)86 exif_get_data_opts(ExifLoader *loader, ExifLog *log,
87 int options, ExifDataType dt)
88 {
89 ExifData *ed;
90 const unsigned char *buf;
91 unsigned int buf_size;
92
93 if (!loader || !log)
94 return NULL;
95
96 exif_loader_get_buf (loader, &buf, &buf_size);
97 if (buf_size == 0)
98 return NULL;
99 ed = exif_data_new();
100 exif_data_log (ed, log);
101
102 /* Clear the slate before setting the requested options */
103 exif_data_unset_option (ed, ~0);
104 exif_data_set_option (ed, options);
105 exif_data_set_data_type (ed, dt);
106 exif_data_load_data (ed, buf, buf_size);
107
108 return ed;
109 }
110
111 /*! Returns the number of bytes of data needed to display n characters of
112 * the given multibyte string in the current locale character encoding.
113 * Any multibyte conversion error is treated as the end of the string.
114 * \param[in] mbs multibyte string
115 * \param[in,out] len number of characters for which a count of bytes is
116 * requested; on exit, returns the number of characters that are represented
117 * by the returned number of bytes (this may be less but never more than the
118 * value on entry)
119 * \return number of bytes starting at mbs make up len characters
120 * \note This can probably be rewritten using mbsrtowcs()
121 */
122 #ifdef HAVE_MBLEN
exif_mbstrlen(const char * mbs,size_t * len)123 size_t exif_mbstrlen(const char *mbs, size_t *len)
124 {
125 int clen;
126 size_t blen = 0, count = 0, maxlen = strlen(mbs);
127
128 /* Iterate through the multibyte string one character at a time */
129 while (*mbs && *len) {
130 clen = mblen(mbs, maxlen);
131 if (clen < 0)
132 break;
133 mbs += clen;
134 blen += clen; /* total bytes needed for string so far */
135 --*len;
136 ++count; /* number of characters in string so far */
137 maxlen -= clen;
138 }
139 *len = count;
140 return blen;
141 }
142 #else
143 /* Simple version that works only with single-byte-per-character encodings */
exif_mbstrlen(const char * mbs,size_t * len)144 size_t exif_mbstrlen(const char *mbs, size_t *len)
145 {
146 size_t clen = strlen(mbs);
147 if (clen < *len)
148 *len = clen;
149 return *len;
150 }
151 #endif
152