1 /*
2  * Copyright Samsung Electronics Co.,LTD.
3  * Copyright (C) 2015 The Android Open Source Project
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 #ifndef __HARDWARE_SAMSUNG_SLSI_EXYNOS_IFDWRITER_H__
18 #define __HARDWARE_SAMSUNG_SLSI_EXYNOS_IFDWRITER_H__
19 
20 #include "hwjpeg-internal.h"
21 
22 class CEndianessChecker {
23     bool __little;
24 public:
25     CEndianessChecker();
26     operator bool() { return __little; }
27 };
28 #ifndef __LITTLE_ENDIAN__
29 extern CEndianessChecker __LITTLE_ENDIAN__;
30 #endif
31 
32 template <typename T>
WriteDataInBig(char * p,T val)33 char *WriteDataInBig(char *p, T val)
34 {
35     if (sizeof(val) == 1) {
36         *p++ = val;
37     } else if (__LITTLE_ENDIAN__) {
38         switch (sizeof(val)) {
39             case 2:
40                 *p++ = static_cast<char>((val >> 8) & 0xFF);
41                 *p++ = static_cast<char>(val & 0xFF);
42                 break;
43             case 4:
44                 *p++ = static_cast<char>((val >> 24) & 0xFF);
45                 *p++ = static_cast<char>((val >> 16) & 0xFF);
46                 *p++ = static_cast<char>((val >> 8) & 0xFF);
47                 *p++ = static_cast<char>(val & 0xFF);
48                 break;
49         }
50     } else {
51         switch (sizeof(val)) {
52             case 2:
53                 *p++  = static_cast<char>(val & 0xFF);
54                 *p++ = static_cast<char>((val >> 8) & 0xFF);
55                 break;
56             case 4:
57                 *p++ = static_cast<char>(val & 0xFF);
58                 *p++ = static_cast<char>((val >> 8) & 0xFF);
59                 *p++ = static_cast<char>((val >> 16) & 0xFF);
60                 *p++ = static_cast<char>((val >> 24) & 0xFF);
61                 break;
62         }
63     }
64 
65     return p;
66 }
67 
68 template <typename T>
WriteData(char * p,T val)69 char *WriteData(char *p, T val)
70 {
71     const char *pt = reinterpret_cast<char *>(&val);
72     for (size_t i = 0; i < sizeof(val); i++)
73         *p++ = *pt++;
74     return p;
75 }
76 
77 class CIFDWriter {
78     char *m_pBase;
79     char *m_pIFDBase;
80     char *m_pValue;
81     unsigned int m_nTags;
82 
WriteOffset(char * target,char * addr)83     char *WriteOffset(char *target, char *addr) {
84         uint32_t val = Offset(addr);
85         const char *p = reinterpret_cast<char *>(&val);
86         *target++ = *p++;
87         *target++ = *p++;
88         *target++ = *p++;
89         *target++ = *p++;
90         return target;
91     }
92 
WriteTagTypeCount(uint16_t tag,uint16_t type,uint32_t count)93     void WriteTagTypeCount(uint16_t tag, uint16_t type, uint32_t count) {
94         const char *p = reinterpret_cast<char *>(&tag);
95         *m_pIFDBase++ = *p++;
96         *m_pIFDBase++ = *p++;
97 
98         p = reinterpret_cast<char *>(&type);
99         *m_pIFDBase++ = *p++;
100         *m_pIFDBase++ = *p++;
101 
102         p = reinterpret_cast<char *>(&count);
103         *m_pIFDBase++ = *p++;
104         *m_pIFDBase++ = *p++;
105         *m_pIFDBase++ = *p++;
106         *m_pIFDBase++ = *p++;
107 
108         m_nTags--;
109     }
110 public:
CIFDWriter(char * offset_base,char * ifdbase,uint16_t tagcount)111     CIFDWriter(char *offset_base, char *ifdbase, uint16_t tagcount) {
112         m_nTags = tagcount;
113         m_pBase = offset_base;
114         m_pIFDBase = ifdbase;
115         m_pValue = m_pIFDBase + IFD_FIELDCOUNT_SIZE +
116                    IFD_FIELD_SIZE * tagcount + IFD_NEXTIFDOFFSET_SIZE;
117 
118         // COUNT field of IFD
119         const char *pval = reinterpret_cast<char *>(&m_nTags);
120         *m_pIFDBase++ = *pval++;
121         *m_pIFDBase++ = *pval++;
122     }
123 
Offset(char * p)124     uint32_t Offset(char *p) {
125         return static_cast<uint32_t>(PTR_TO_ULONG(p) - PTR_TO_ULONG(m_pBase));
126     }
127 
WriteByte(uint16_t tag,uint32_t count,const uint8_t value[])128     void WriteByte(uint16_t tag, uint32_t count, const uint8_t value[]) {
129         ALOG_ASSERT(m_nTags == 0);
130 
131         WriteTagTypeCount(tag, EXIF_TYPE_BYTE, count);
132 
133         if (count > IFD_VALOFF_SIZE) {
134             m_pIFDBase = WriteOffset(m_pIFDBase, m_pValue);
135             for (uint32_t i = 0; i < count; i++) {
136                 *m_pValue++ = static_cast<char>(value[i]);
137             }
138         } else {
139             for (uint32_t i = 0; i < count; i++)
140                 *m_pIFDBase++ = static_cast<char>(value[i]);
141             m_pIFDBase += IFD_VALOFF_SIZE - count;
142         }
143     }
144 
WriteShort(uint16_t tag,uint32_t count,const uint16_t value[])145     void WriteShort(uint16_t tag, uint32_t count, const uint16_t value[]) {
146         ALOG_ASSERT(m_nTags == 0);
147 
148         WriteTagTypeCount(tag, EXIF_TYPE_SHORT, count);
149 
150         const char *p = reinterpret_cast<const char *>(&value[0]);
151 
152         if (count > (IFD_VALOFF_SIZE / sizeof(value[0]))) {
153             m_pIFDBase = WriteOffset(m_pIFDBase, m_pValue);
154             for (uint32_t i = 0; i < count; i++) {
155                 *m_pValue++ = *p++;
156                 *m_pValue++ = *p++;
157             }
158         } else {
159             for (uint32_t i = 0; i < count; i++) {
160                 *m_pIFDBase++ = *p++;
161                 *m_pIFDBase++ = *p++;
162             }
163             m_pIFDBase += IFD_VALOFF_SIZE - count * sizeof(value[0]);
164         }
165     }
166 
WriteLong(uint16_t tag,uint32_t count,const uint32_t value[])167     void WriteLong(uint16_t tag, uint32_t count, const uint32_t value[]) {
168         ALOG_ASSERT(m_nTags == 0);
169 
170         WriteTagTypeCount(tag, EXIF_TYPE_LONG, count);
171 
172         const char *p = reinterpret_cast<const char *>(&value[0]);
173         if (count > (IFD_VALOFF_SIZE / sizeof(value[0]))) {
174             m_pIFDBase = WriteOffset(m_pIFDBase, m_pValue);
175             *m_pValue++ = *p++;
176         } else {
177             *m_pIFDBase++ = *p++;
178             *m_pIFDBase++ = *p++;
179             *m_pIFDBase++ = *p++;
180             *m_pIFDBase++ = *p++;
181         }
182     }
183 
WriteASCII(uint16_t tag,uint32_t count,const char * value)184     void WriteASCII(uint16_t tag, uint32_t count, const char *value) {
185         ALOG_ASSERT(m_nTags == 0);
186 
187         WriteTagTypeCount(tag, EXIF_TYPE_ASCII, count);
188 
189         if (count > IFD_VALOFF_SIZE) {
190             m_pIFDBase = WriteOffset(m_pIFDBase, m_pValue);
191             memcpy(m_pValue, value, count);
192             m_pValue[count - 1] = '\0';
193             m_pValue += count;
194         } else {
195             for (uint32_t i = 0; i < count; i++)
196                 *m_pIFDBase++ = value[i];
197             *(m_pIFDBase - 1) = '\0';
198             m_pIFDBase += IFD_VALOFF_SIZE - count;
199         }
200     }
201 
WriteCString(uint16_t tag,uint32_t count,const char * string)202     void WriteCString(uint16_t tag, uint32_t count, const char *string) {
203         ALOG_ASSERT(m_nTags == 0);
204 
205         WriteTagTypeCount(tag, EXIF_TYPE_ASCII, count);
206 
207         if (count > IFD_VALOFF_SIZE) {
208             m_pIFDBase = WriteOffset(m_pIFDBase, m_pValue);
209             strncpy(m_pValue, string, count);
210             m_pValue[count - 1] = '\0';
211             m_pValue += count;
212         } else {
213             uint32_t i;
214 
215             for (i = 0; (i < (count - 1)) && (string[i] != '\0'); i++)
216                 *m_pIFDBase++ = string[i];
217 
218             while (i++ < count)
219                 *m_pIFDBase++ = '\0';
220 
221             m_pIFDBase += IFD_VALOFF_SIZE - count;
222         }
223     }
224 
WriteRational(uint16_t tag,uint32_t count,const rational_t value[])225     void WriteRational(uint16_t tag, uint32_t count, const rational_t value[]) {
226         ALOG_ASSERT(m_nTags == 0);
227 
228         WriteTagTypeCount(tag, EXIF_TYPE_RATIONAL, count);
229         m_pIFDBase = WriteOffset(m_pIFDBase, m_pValue);
230 
231         for (uint32_t i = 0; i < count; i++) {
232             const char *pt;
233             pt = reinterpret_cast<const char *>(&value[i].num);
234             *m_pValue++ = *pt++;
235             *m_pValue++ = *pt++;
236             *m_pValue++ = *pt++;
237             *m_pValue++ = *pt++;
238             pt = reinterpret_cast<const char *>(&value[i].den);
239             *m_pValue++ = *pt++;
240             *m_pValue++ = *pt++;
241             *m_pValue++ = *pt++;
242             *m_pValue++ = *pt++;
243         }
244     }
245 
WriteSRational(uint16_t tag,uint32_t count,const srational_t value[])246     void WriteSRational(uint16_t tag, uint32_t count, const srational_t value[]) {
247         ALOG_ASSERT(m_nTags == 0);
248 
249         WriteTagTypeCount(tag, EXIF_TYPE_SRATIONAL, count);
250         m_pIFDBase = WriteOffset(m_pIFDBase, m_pValue);
251 
252         const char *pt = reinterpret_cast<const char *>(value);
253         for (uint32_t i = 0; i < sizeof(srational_t) * count; i++)
254             *m_pValue++ = *pt++;
255     }
256 
WriteUndef(uint16_t tag,uint32_t count,const unsigned char * value)257     void WriteUndef(uint16_t tag, uint32_t count, const unsigned char *value) {
258         ALOG_ASSERT(m_nTags == 0);
259 
260         WriteTagTypeCount(tag, EXIF_TYPE_UNDEFINED, count);
261         if (count > IFD_VALOFF_SIZE) {
262             m_pIFDBase = WriteOffset(m_pIFDBase, m_pValue);
263             memcpy(m_pValue, value, count);
264             m_pValue += count;
265         } else {
266             for (uint32_t i = 0; i < count; i++)
267                 *m_pIFDBase++ = static_cast<char>(value[i]);
268             m_pIFDBase += IFD_VALOFF_SIZE - count;
269         }
270     }
271 
BeginSubIFD(uint16_t tag)272     char *BeginSubIFD(uint16_t tag) {
273         ALOG_ASSERT(m_nTags == 0);
274 
275         WriteTagTypeCount(tag, EXIF_TYPE_LONG, 1);
276 
277         uint32_t offset = Offset(m_pValue);
278         const char *poff = reinterpret_cast<char *>(&offset);
279         *m_pIFDBase++ = *poff++;
280         *m_pIFDBase++ = *poff++;
281         *m_pIFDBase++ = *poff++;
282         *m_pIFDBase++ = *poff++;
283 
284         return m_pValue;
285     }
286 
EndSubIFD(char * end_of_subIFD)287     void EndSubIFD(char *end_of_subIFD) { m_pValue = end_of_subIFD; }
CancelSubIFD()288     void CancelSubIFD() { m_pIFDBase -= IFD_FIELD_SIZE; }
289 
Finish(bool last)290     void Finish(bool last) {
291         ALOG_ASSERT(m_nTags > 0);
292 
293         uint32_t offset = last ? 0 : Offset(m_pValue);
294         const char *pv = reinterpret_cast<char *>(&offset);
295         *m_pIFDBase++ = *pv++;
296         *m_pIFDBase++ = *pv++;
297         *m_pIFDBase++ = *pv++;
298         *m_pIFDBase++ = *pv++;
299     }
300 
GetNextIFDBase()301     char *GetNextIFDBase() { return m_pValue; }
GetNextTagAddress()302     char *GetNextTagAddress() { return m_pIFDBase; }
303 };
304 
305 #endif //__HARDWARE_SAMSUNG_SLSI_EXYNOS_IFDWRITER_H__
306