1/*
2 * Copyright 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <img_utils/TiffIfd.h>
18#include <img_utils/TiffHelpers.h>
19#include <img_utils/TiffEntry.h>
20
21#include <utils/Errors.h>
22#include <utils/StrongPointer.h>
23#include <utils/Vector.h>
24
25namespace android {
26namespace img_utils {
27
28TiffEntry::~TiffEntry() {}
29
30/**
31 * Specialize for each valid type, including sub-IFDs.
32 *
33 * Values with types other than the ones given here should not compile.
34 */
35
36template<>
37const sp<TiffIfd>* TiffEntry::forceValidType<sp<TiffIfd> >(TagType type, const sp<TiffIfd>* value) {
38    if (type == LONG) {
39        return value;
40    }
41    ALOGE("%s: Value of type 'ifd' is not valid for tag with TIFF type %d.",
42            __FUNCTION__, type);
43    return NULL;
44}
45
46template<>
47const uint8_t* TiffEntry::forceValidType<uint8_t>(TagType type, const uint8_t* value) {
48    if (type == BYTE || type == ASCII || type == UNDEFINED) {
49        return value;
50    }
51    ALOGE("%s: Value of type 'uint8_t' is not valid for tag with TIFF type %d.",
52            __FUNCTION__, type);
53    return NULL;
54}
55
56template<>
57const int8_t* TiffEntry::forceValidType<int8_t>(TagType type, const int8_t* value) {
58    if (type == SBYTE || type == ASCII || type == UNDEFINED) {
59        return value;
60    }
61    ALOGE("%s: Value of type 'int8_t' is not valid for tag with TIFF type %d.",
62            __FUNCTION__, type);
63    return NULL;
64}
65
66template<>
67const uint16_t* TiffEntry::forceValidType<uint16_t>(TagType type, const uint16_t* value) {
68    if (type == SHORT) {
69        return value;
70    }
71    ALOGE("%s: Value of type 'uint16_t' is not valid for tag with TIFF type %d.",
72            __FUNCTION__, type);
73    return NULL;
74}
75
76template<>
77const int16_t* TiffEntry::forceValidType<int16_t>(TagType type, const int16_t* value) {
78    if (type == SSHORT) {
79        return value;
80    }
81    ALOGE("%s: Value of type 'int16_t' is not valid for tag with TIFF type %d.",
82            __FUNCTION__, type);
83    return NULL;
84}
85
86template<>
87const uint32_t* TiffEntry::forceValidType<uint32_t>(TagType type, const uint32_t* value) {
88    if (type == LONG || type == RATIONAL) {
89        return value;
90    }
91    ALOGE("%s: Value of type 'uint32_t' is not valid for tag with TIFF type %d.",
92            __FUNCTION__, type);
93    return NULL;
94}
95
96template<>
97const int32_t* TiffEntry::forceValidType<int32_t>(TagType type, const int32_t* value) {
98    if (type == SLONG || type == SRATIONAL) {
99        return value;
100    }
101    ALOGE("%s: Value of type 'int32_t' is not valid for tag with TIFF type %d.",
102            __FUNCTION__, type);
103    return NULL;
104}
105
106template<>
107const double* TiffEntry::forceValidType<double>(TagType type, const double* value) {
108    if (type == DOUBLE) {
109        return value;
110    }
111    ALOGE("%s: Value of type 'double' is not valid for tag with TIFF type %d.",
112            __FUNCTION__, type);
113    return NULL;
114}
115
116template<>
117const float* TiffEntry::forceValidType<float>(TagType type, const float* value) {
118    if (type == FLOAT) {
119        return value;
120    }
121    ALOGE("%s: Value of type 'float' is not valid for tag with TIFF type %d.",
122            __FUNCTION__, type);
123    return NULL;
124}
125
126String8 TiffEntry::toString() const {
127    String8 output;
128    uint32_t count = getCount();
129    output.appendFormat("[id: %x, type: %d, count: %u, value: '", getTag(), getType(), count);
130
131    size_t cappedCount = count;
132    if (count > MAX_PRINT_STRING_LENGTH) {
133        cappedCount = MAX_PRINT_STRING_LENGTH;
134    }
135
136    TagType type = getType();
137    switch (type) {
138        case UNDEFINED:
139        case BYTE: {
140            const uint8_t* typed_data = getData<uint8_t>();
141            for (size_t i = 0; i < cappedCount; ++i) {
142                output.appendFormat("%u ", typed_data[i]);
143            }
144            break;
145        }
146        case ASCII: {
147            const char* typed_data = reinterpret_cast<const char*>(getData<uint8_t>());
148            size_t len = count;
149            if (count > MAX_PRINT_STRING_LENGTH) {
150                 len = MAX_PRINT_STRING_LENGTH;
151            }
152            output.append(typed_data, len);
153            break;
154        }
155        case SHORT: {
156            const uint16_t* typed_data = getData<uint16_t>();
157            for (size_t i = 0; i < cappedCount; ++i) {
158                output.appendFormat("%u ", typed_data[i]);
159            }
160            break;
161        }
162        case LONG: {
163            const uint32_t* typed_data = getData<uint32_t>();
164            for (size_t i = 0; i < cappedCount; ++i) {
165                output.appendFormat("%u ", typed_data[i]);
166            }
167            break;
168        }
169        case RATIONAL: {
170            const uint32_t* typed_data = getData<uint32_t>();
171            cappedCount <<= 1;
172            for (size_t i = 0; i < cappedCount; i+=2) {
173                output.appendFormat("%u/%u ", typed_data[i], typed_data[i + 1]);
174            }
175            break;
176        }
177        case SBYTE: {
178            const int8_t* typed_data = getData<int8_t>();
179            for (size_t i = 0; i < cappedCount; ++i) {
180                output.appendFormat("%d ", typed_data[i]);
181            }
182            break;
183        }
184        case SSHORT: {
185            const int16_t* typed_data = getData<int16_t>();
186            for (size_t i = 0; i < cappedCount; ++i) {
187                output.appendFormat("%d ", typed_data[i]);
188            }
189            break;
190        }
191        case SLONG: {
192            const int32_t* typed_data = getData<int32_t>();
193            for (size_t i = 0; i < cappedCount; ++i) {
194                output.appendFormat("%d ", typed_data[i]);
195            }
196            break;
197        }
198        case SRATIONAL: {
199            const int32_t* typed_data = getData<int32_t>();
200            cappedCount <<= 1;
201            for (size_t i = 0; i < cappedCount; i+=2) {
202                output.appendFormat("%d/%d ", typed_data[i], typed_data[i + 1]);
203            }
204            break;
205        }
206        case FLOAT: {
207            const float* typed_data = getData<float>();
208            for (size_t i = 0; i < cappedCount; ++i) {
209                output.appendFormat("%f ", typed_data[i]);
210            }
211            break;
212        }
213        case DOUBLE: {
214            const double* typed_data = getData<double>();
215            for (size_t i = 0; i < cappedCount; ++i) {
216                output.appendFormat("%f ", typed_data[i]);
217            }
218            break;
219        }
220        default: {
221            output.append("unknown type ");
222            break;
223        }
224    }
225
226    if (count > MAX_PRINT_STRING_LENGTH) {
227        output.append("...");
228    }
229    output.append("']");
230    return output;
231}
232
233} /*namespace img_utils*/
234} /*namespace android*/
235