1/*
2Copyright (c) 2012, Broadcom Europe Ltd
3All rights reserved.
4
5Redistribution and use in source and binary forms, with or without
6modification, are permitted provided that the following conditions are met:
7 * Redistributions of source code must retain the above copyright
8 notice, this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 notice, this list of conditions and the following disclaimer in the
11 documentation and/or other materials provided with the distribution.
12 * Neither the name of the copyright holder nor the
13 names of its contributors may be used to endorse or promote products
14 derived from this software without specific prior written permission.
15
16THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
20DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*/
27#include <stdio.h>
28#include <stdlib.h>
29#include <string.h>
30#include <stdarg.h>
31#include "containers/core/containers_private.h"
32#include "containers/core/containers_io_helpers.h"
33#include "containers/core/containers_logging.h"
34
35void vc_container_helper_format_debug(VC_CONTAINER_T *ctx, int indent, const char *format, ...)
36{
37 char debug_string[512];
38 va_list args;
39 int result;
40
41 if(indent >= (int)sizeof(debug_string)) return;
42 memset(debug_string, ' ', indent);
43
44 va_start( args, format );
45 result = vsnprintf(debug_string + indent, sizeof(debug_string) - indent, format, args);
46 va_end( args );
47
48 if(result <= 0) return;
49
50 vc_container_log(ctx, VC_CONTAINER_LOG_FORMAT, debug_string);
51 fflush(0);
52}
53
54uint64_t vc_container_helper_int_debug(VC_CONTAINER_T *ctx, int type, uint64_t value, const char *name, int indent)
55{
56 VC_CONTAINER_PARAM_UNUSED(ctx);
57
58 if(type == LOG_FORMAT_TYPE_HEX)
59 vc_container_helper_format_debug(ctx, indent, "%s: 0x%"PRIx64, name, value);
60 else
61 vc_container_helper_format_debug(ctx, indent, "%s: %"PRIi64, name, value);
62 return value;
63}
64
65uint64_t vc_container_helper_read_debug(VC_CONTAINER_T *ctx, int type, int size,
66 const char *name, uint8_t *buffer, int indent, int b_skip)
67{
68 int64_t offset = STREAM_POSITION(ctx);
69 uint64_t value = 0;
70 GUID_T guid;
71
72 if(type == LOG_FORMAT_TYPE_STRING ||
73 type == LOG_FORMAT_TYPE_STRING_UTF16_LE ||
74 type == LOG_FORMAT_TYPE_STRING_UTF16_BE)
75 {
76 uint8_t stringbuf[256];
77 char utf8buf[256];
78 int stringsize = sizeof(stringbuf) - 2;
79
80 if(!buffer)
81 {
82 buffer = stringbuf;
83 if(size < stringsize) stringsize = size;
84 }
85 else stringsize = size;
86
87 value = vc_container_io_read(ctx->priv->io, buffer, stringsize);
88
89 if(!utf8_from_charset(type == LOG_FORMAT_TYPE_STRING ? "UTF8" : "UTF16-LE",
90 utf8buf, sizeof(utf8buf), buffer, stringsize))
91 vc_container_helper_format_debug(ctx, indent, "%s: \"%s\"", name, utf8buf);
92 else
93 vc_container_helper_format_debug(ctx, indent, "%s: (could not read)", name);
94
95 if(size - stringsize)
96 value += vc_container_io_skip(ctx->priv->io, size - stringsize);
97 return value;
98 }
99
100 if(type == LOG_FORMAT_TYPE_UINT_LE)
101 {
102 switch(size)
103 {
104 case 1: value = vc_container_io_read_uint8(ctx->priv->io); break;
105 case 2: value = vc_container_io_read_le_uint16(ctx->priv->io); break;
106 case 3: value = vc_container_io_read_le_uint24(ctx->priv->io); break;
107 case 4: value = vc_container_io_read_le_uint32(ctx->priv->io); break;
108 case 5: value = vc_container_io_read_le_uint40(ctx->priv->io); break;
109 case 6: value = vc_container_io_read_le_uint48(ctx->priv->io); break;
110 case 7: value = vc_container_io_read_le_uint56(ctx->priv->io); break;
111 case 8: value = vc_container_io_read_le_uint64(ctx->priv->io); break;
112 }
113 }
114 else if(type == LOG_FORMAT_TYPE_UINT_BE)
115 {
116 switch(size)
117 {
118 case 1: value = vc_container_io_read_uint8(ctx->priv->io); break;
119 case 2: value = vc_container_io_read_be_uint16(ctx->priv->io); break;
120 case 3: value = vc_container_io_read_be_uint24(ctx->priv->io); break;
121 case 4: value = vc_container_io_read_be_uint32(ctx->priv->io); break;
122 case 5: value = vc_container_io_read_be_uint40(ctx->priv->io); break;
123 case 6: value = vc_container_io_read_be_uint48(ctx->priv->io); break;
124 case 7: value = vc_container_io_read_be_uint56(ctx->priv->io); break;
125 case 8: value = vc_container_io_read_be_uint64(ctx->priv->io); break;
126 }
127 }
128 else if(type == LOG_FORMAT_TYPE_FOURCC)
129 {
130 value = vc_container_io_read_fourcc(ctx->priv->io);
131 }
132 else if(type == LOG_FORMAT_TYPE_GUID)
133 {
134 value = vc_container_io_read(ctx->priv->io, &guid, 16);
135 }
136 else
137 {
138 vc_container_assert(0);
139 return 0;
140 }
141
142 if(type == LOG_FORMAT_TYPE_GUID)
143 {
144 if(value == 16)
145 {
146 vc_container_helper_format_debug(ctx, indent, "%s: 0x%x-0x%x-0x%x-0x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x",
147 name, guid.word0, guid.short0, guid.short1,
148 guid.bytes[0], guid.bytes[1], guid.bytes[2], guid.bytes[3],
149 guid.bytes[4], guid.bytes[5], guid.bytes[6], guid.bytes[7]);
150 if(buffer) memcpy(buffer, &guid, sizeof(guid));
151 }
152 }
153 else if(type == LOG_FORMAT_TYPE_FOURCC)
154 {
155 uint32_t val = value;
156 vc_container_helper_format_debug(ctx, indent, "%s: %4.4s", name, (char *)&val);
157 }
158 else
159 {
160 vc_container_helper_format_debug(ctx, indent, "%s: %"PRIi64, name, value);
161 }
162
163 if(b_skip) value = (STREAM_POSITION(ctx) - offset) != size;
164 return value;
165}
166
167VC_CONTAINER_STATUS_T vc_container_helper_write_debug(VC_CONTAINER_T *ctx, int type, int size,
168 const char *name, uint64_t value, const uint8_t *buffer, int indent, int silent)
169{
170 VC_CONTAINER_STATUS_T status = VC_CONTAINER_SUCCESS;
171
172 if(type == LOG_FORMAT_TYPE_STRING)
173 {
174 value = vc_container_io_write(ctx->priv->io, buffer, size);
175 if(!silent)
176 vc_container_helper_format_debug(ctx, indent, "%s: \"%ls\"", name, buffer);
177 return value == (uint64_t)size ? VC_CONTAINER_SUCCESS : VC_CONTAINER_ERROR_FAILED;
178 }
179
180 if(type == LOG_FORMAT_TYPE_UINT_LE)
181 {
182 switch(size)
183 {
184 case 1: status = vc_container_io_write_uint8(ctx->priv->io, (uint8_t)value); break;
185 case 2: status = vc_container_io_write_le_uint16(ctx->priv->io, (uint16_t)value); break;
186 case 3: status = vc_container_io_write_le_uint24(ctx->priv->io, (uint32_t)value); break;
187 case 4: status = vc_container_io_write_le_uint32(ctx->priv->io, (uint32_t)value); break;
188 case 8: status = vc_container_io_write_le_uint64(ctx->priv->io, value); break;
189 }
190 }
191 else if(type == LOG_FORMAT_TYPE_UINT_BE)
192 {
193 switch(size)
194 {
195 case 1: status = vc_container_io_write_uint8(ctx->priv->io, (uint8_t)value); break;
196 case 2: status = vc_container_io_write_be_uint16(ctx->priv->io, (uint16_t)value); break;
197 case 3: status = vc_container_io_write_be_uint24(ctx->priv->io, (uint32_t)value); break;
198 case 4: status = vc_container_io_write_be_uint32(ctx->priv->io, (uint32_t)value); break;
199 case 8: status = vc_container_io_write_be_uint64(ctx->priv->io, value); break;
200 }
201 }
202 else if(type == LOG_FORMAT_TYPE_FOURCC)
203 {
204 status = vc_container_io_write_fourcc(ctx->priv->io, (uint32_t)value);
205 }
206 else if(type == LOG_FORMAT_TYPE_GUID)
207 {
208 value = vc_container_io_write(ctx->priv->io, buffer, 16);
209 }
210 else
211 {
212 vc_container_assert(0);
213 return 0;
214 }
215
216 if(status)
217 {
218 vc_container_helper_format_debug(ctx, indent, "write failed for %s", name);
219 return status;
220 }
221
222 if(!silent)
223 {
224 if (type == LOG_FORMAT_TYPE_FOURCC)
225 {
226 vc_container_helper_format_debug(ctx, indent, "%s: %4.4s", name, (char *)&value);
227 }
228 else if(type == LOG_FORMAT_TYPE_GUID)
229 {
230 GUID_T guid;
231 memcpy(&guid, buffer, sizeof(guid));
232 vc_container_helper_format_debug(ctx, indent, "%s: 0x%x-0x%x-0x%x-0x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x",
233 name, guid.word0, guid.short0, guid.short1,
234 guid.bytes[0], guid.bytes[1], guid.bytes[2], guid.bytes[3],
235 guid.bytes[4], guid.bytes[5], guid.bytes[6], guid.bytes[7]);
236 }
237 else
238 {
239 vc_container_helper_format_debug(ctx, indent, "%s: %"PRIi64, name, value);
240 }
241 }
242
243 return status;
244}
245