1 /* GStreamer PNM utility functions
2 * Copyright (C) 2009 Lutz Mueller <lutz@users.sourceforge.net>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 */
19
20 #include "gstpnmutils.h"
21
22 GstPnmInfoMngrResult
gst_pnm_info_mngr_scan(GstPnmInfoMngr * mngr,const guint8 * buf,guint buf_len)23 gst_pnm_info_mngr_scan (GstPnmInfoMngr * mngr, const guint8 * buf,
24 guint buf_len)
25 {
26 guint i = 0;
27
28 g_return_val_if_fail (mngr != NULL, GST_PNM_INFO_MNGR_RESULT_FAILED);
29 g_return_val_if_fail (buf || !buf_len, GST_PNM_INFO_MNGR_RESULT_FAILED);
30
31 if (!buf_len)
32 return (mngr->info.fields ==
33 GST_PNM_INFO_FIELDS_ALL) ? GST_PNM_INFO_MNGR_RESULT_FINISHED :
34 GST_PNM_INFO_MNGR_RESULT_READING;
35
36 switch (mngr->state) {
37 case GST_PNM_INFO_MNGR_STATE_COMMENT:
38 for (i = 0; (i < buf_len) && (buf[i] != '\n'); i++);
39 if (i == buf_len)
40 return GST_PNM_INFO_MNGR_RESULT_READING;
41 mngr->state = GST_PNM_INFO_MNGR_STATE_NONE;
42 mngr->data_offset += i;
43 return gst_pnm_info_mngr_scan (mngr, buf + i, buf_len - i);
44 case GST_PNM_INFO_MNGR_STATE_WHITE_SPACE:
45 for (i = 0; (i < buf_len) && ((buf[i] == ' ') || (buf[i] == '\t')
46 || (buf[i] == '\n')); i++);
47 if (i == buf_len)
48 return GST_PNM_INFO_MNGR_RESULT_READING;
49 mngr->state = GST_PNM_INFO_MNGR_STATE_NONE;
50 mngr->data_offset += i;
51 return gst_pnm_info_mngr_scan (mngr, buf + i, buf_len - i);
52 case GST_PNM_INFO_MNGR_STATE_NONE:
53 switch (buf[i++]) {
54 case '#':
55 mngr->state = GST_PNM_INFO_MNGR_STATE_COMMENT;
56 mngr->data_offset += i;
57 return gst_pnm_info_mngr_scan (mngr, buf + i, buf_len - i);
58 case ' ':
59 case '\t':
60 case '\n':
61 mngr->state = GST_PNM_INFO_MNGR_STATE_WHITE_SPACE;
62 mngr->data_offset += i;
63 return gst_pnm_info_mngr_scan (mngr, buf + i, buf_len - i);
64 case 'P':
65 if (mngr->info.fields & GST_PNM_INFO_FIELDS_TYPE)
66 return GST_PNM_INFO_MNGR_RESULT_FAILED;
67 mngr->state = GST_PNM_INFO_MNGR_STATE_DATA_TYPE;
68 mngr->data_offset += i;
69 return gst_pnm_info_mngr_scan (mngr, buf + i, buf_len - i);
70 case '0':
71 case '1':
72 case '2':
73 case '3':
74 case '4':
75 case '5':
76 case '6':
77 case '7':
78 case '8':
79 case '9':
80 if (mngr->info.fields & GST_PNM_INFO_FIELDS_MAX)
81 return GST_PNM_INFO_MNGR_RESULT_FINISHED;
82 if (mngr->info.fields & GST_PNM_INFO_FIELDS_HEIGHT) {
83 mngr->state = GST_PNM_INFO_MNGR_STATE_DATA_MAX;
84 return gst_pnm_info_mngr_scan (mngr, buf, buf_len);
85 }
86 if (mngr->info.fields & GST_PNM_INFO_FIELDS_WIDTH) {
87 mngr->state = GST_PNM_INFO_MNGR_STATE_DATA_HEIGHT;
88 return gst_pnm_info_mngr_scan (mngr, buf, buf_len);
89 }
90 mngr->state = GST_PNM_INFO_MNGR_STATE_DATA_WIDTH;
91 return gst_pnm_info_mngr_scan (mngr, buf, buf_len);
92 default:
93 return GST_PNM_INFO_MNGR_RESULT_FAILED;
94 }
95 case GST_PNM_INFO_MNGR_STATE_DATA_TYPE:
96 switch (buf[i++]) {
97 case '1':
98 mngr->info.type = GST_PNM_TYPE_BITMAP;
99 mngr->info.encoding = GST_PNM_ENCODING_ASCII;
100 break;
101 case '2':
102 mngr->info.type = GST_PNM_TYPE_GRAYMAP;
103 mngr->info.encoding = GST_PNM_ENCODING_ASCII;
104 break;
105 case '3':
106 mngr->info.type = GST_PNM_TYPE_PIXMAP;
107 mngr->info.encoding = GST_PNM_ENCODING_ASCII;
108 break;
109 case '4':
110 mngr->info.type = GST_PNM_TYPE_BITMAP;
111 mngr->info.encoding = GST_PNM_ENCODING_RAW;
112 break;
113 case '5':
114 mngr->info.type = GST_PNM_TYPE_GRAYMAP;
115 mngr->info.encoding = GST_PNM_ENCODING_RAW;
116 break;
117 case '6':
118 mngr->info.type = GST_PNM_TYPE_PIXMAP;
119 mngr->info.encoding = GST_PNM_ENCODING_RAW;
120 break;
121 default:
122 return GST_PNM_INFO_MNGR_RESULT_FAILED;
123 }
124 mngr->info.fields |=
125 GST_PNM_INFO_FIELDS_TYPE | GST_PNM_INFO_FIELDS_ENCODING;
126 mngr->state = GST_PNM_INFO_MNGR_STATE_WHITE_SPACE;
127 if (i == buf_len)
128 return GST_PNM_INFO_MNGR_RESULT_READING;
129 mngr->info.width = mngr->info.height = mngr->info.max = 0;
130 mngr->data_offset += i;
131 return gst_pnm_info_mngr_scan (mngr, buf + i, buf_len - i);
132 case GST_PNM_INFO_MNGR_STATE_DATA_WIDTH:
133 if ((buf[i] < '0') || (buf[i] > '9')) {
134 switch (buf[i]) {
135 case '\n':
136 case '\t':
137 case ' ':
138 mngr->info.fields |= GST_PNM_INFO_FIELDS_WIDTH;
139 mngr->state = GST_PNM_INFO_MNGR_STATE_WHITE_SPACE;
140 mngr->data_offset += i;
141 return gst_pnm_info_mngr_scan (mngr, buf + i, buf_len - i);
142 default:
143 return GST_PNM_INFO_MNGR_RESULT_FAILED;
144 }
145 }
146 mngr->info.width *= 10;
147 mngr->info.width += buf[i++] - 0x030;
148 mngr->data_offset += i;
149 return gst_pnm_info_mngr_scan (mngr, buf + i, buf_len - i);
150 case GST_PNM_INFO_MNGR_STATE_DATA_HEIGHT:
151 if ((buf[i] < '0') || (buf[i] > '9')) {
152 switch (buf[i]) {
153 case '\n':
154 case '\t':
155 case ' ':
156 mngr->info.fields |= GST_PNM_INFO_FIELDS_HEIGHT;
157 mngr->state = GST_PNM_INFO_MNGR_STATE_WHITE_SPACE;
158 mngr->data_offset += i;
159 if (mngr->info.type == GST_PNM_TYPE_BITMAP) {
160 mngr->data_offset += 1;
161 mngr->info.fields |= GST_PNM_INFO_FIELDS_MAX;
162 return GST_PNM_INFO_MNGR_RESULT_FINISHED;
163 }
164 return gst_pnm_info_mngr_scan (mngr, buf + i, buf_len - i);
165 default:
166 return GST_PNM_INFO_MNGR_RESULT_FAILED;
167 }
168 }
169 mngr->info.height *= 10;
170 mngr->info.height += buf[i++] - 0x030;
171 mngr->data_offset += i;
172 return gst_pnm_info_mngr_scan (mngr, buf + i, buf_len - i);
173 case GST_PNM_INFO_MNGR_STATE_DATA_MAX:
174 if ((buf[i] < '0') || (buf[i] > '9')) {
175 switch (buf[i]) {
176 case '\n':
177 case '\t':
178 case ' ':
179 /* Check for maximum and minimum supported bit depth and
180 return error if its out of range */
181 if (mngr->info.type == GST_PNM_TYPE_GRAYMAP) {
182 if ((mngr->info.max > 65535) || (mngr->info.max < 1)) {
183 return GST_PNM_INFO_MNGR_RESULT_FAILED;
184 }
185 } else if ((mngr->info.max > 255) || (mngr->info.max < 1)) {
186 return GST_PNM_INFO_MNGR_RESULT_FAILED;
187 }
188 mngr->info.fields |= GST_PNM_INFO_FIELDS_MAX;
189 mngr->data_offset += i + 1;
190 return GST_PNM_INFO_MNGR_RESULT_FINISHED;
191 default:
192 return GST_PNM_INFO_MNGR_RESULT_FAILED;
193 }
194 }
195 mngr->info.max *= 10;
196 mngr->info.max += buf[i++] - 0x030;
197 mngr->data_offset += i;
198 return gst_pnm_info_mngr_scan (mngr, buf + i, buf_len - i);
199 }
200 return GST_PNM_INFO_MNGR_RESULT_FAILED;
201 }
202