]>
Commit | Line | Data |
---|---|---|
3e170ce0 A |
1 | /* |
2 | * Copyright (c) 2015 Apple Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ | |
5 | * | |
6 | * This file contains Original Code and/or Modifications of Original Code | |
7 | * as defined in and that are subject to the Apple Public Source License | |
8 | * Version 2.0 (the 'License'). You may not use this file except in | |
9 | * compliance with the License. The rights granted to you under the License | |
10 | * may not be used to create, or enable the creation or redistribution of, | |
11 | * unlawful or unlicensed copies of an Apple operating system, or to | |
12 | * circumvent, violate, or enable the circumvention or violation of, any | |
13 | * terms of an Apple operating system software license agreement. | |
14 | * | |
15 | * Please obtain a copy of the License at | |
16 | * http://www.opensource.apple.com/apsl/ and read it before using this file. | |
17 | * | |
18 | * The Original Code and all software distributed under the License are | |
19 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
20 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
21 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
22 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. | |
23 | * Please see the License for the specific language governing rights and | |
24 | * limitations under the License. | |
25 | * | |
26 | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ | |
27 | */ | |
28 | ||
29 | #import "KCDBasicTypeDescription.h" | |
30 | ||
39037602 A |
31 | const char * name_for_subtype(uint8_t elem_type); |
32 | ||
33 | const char * name_for_subtype(uint8_t elem_type) | |
34 | { | |
35 | char * retval = "unknown"; | |
36 | ||
37 | switch (elem_type) { | |
38 | case KC_ST_CHAR: retval = "char"; break; | |
39 | case KC_ST_INT8: retval = "int8_t"; break; | |
40 | case KC_ST_UINT8: retval = "uint8_t"; break; | |
41 | case KC_ST_INT16: retval = "int16_t"; break; | |
42 | case KC_ST_UINT16: retval = "uint16_t"; break; | |
43 | case KC_ST_INT32: retval = "int32_t"; break; | |
44 | case KC_ST_UINT32: retval = "uint32_t"; break; | |
45 | case KC_ST_INT64: retval = "int64_t"; break; | |
46 | case KC_ST_UINT64: retval = "uint64_t"; break; | |
47 | ||
48 | default: retval = "Unknown"; break; | |
49 | } | |
50 | ||
51 | return retval; | |
52 | } | |
53 | ||
54 | ||
3e170ce0 A |
55 | @interface |
56 | KCDBasicTypeDescription () { | |
39037602 | 57 | unsigned int _typeID; |
3e170ce0 A |
58 | uint32_t _size; |
59 | uint32_t _count; | |
60 | NSString * _name; | |
61 | struct kcdata_subtype_descriptor _subtype_desc; | |
62 | } | |
63 | ||
64 | @end | |
65 | ||
66 | @implementation KCDBasicTypeDescription | |
67 | ||
68 | - (id)initWithKCTypeDesc:(kcdata_subtype_descriptor_t)sub_type_desc | |
69 | { | |
70 | _typeID = sub_type_desc->kcs_elem_type; | |
71 | _count = kcs_get_elem_count(sub_type_desc); | |
72 | _size = kcs_get_elem_size(sub_type_desc); | |
73 | ||
74 | memcpy(&_subtype_desc, sub_type_desc, sizeof(_subtype_desc)); | |
75 | _name = [NSString stringWithFormat:@"%s", _subtype_desc.kcs_name]; | |
76 | ||
77 | return self; | |
78 | } | |
79 | ||
80 | - (id)createDefaultForType:(uint32_t)typeID | |
81 | { | |
82 | struct kcdata_subtype_descriptor subtype; | |
83 | subtype.kcs_flags = KCS_SUBTYPE_FLAGS_ARRAY; | |
84 | subtype.kcs_elem_type = KC_ST_UINT8; | |
85 | subtype.kcs_elem_offset = 0; | |
86 | subtype.kcs_elem_size = KCS_SUBTYPE_PACK_SIZE(UINT16_MAX, (uint16_t)sizeof(uint8_t)); | |
87 | subtype.kcs_name[0] = '\0'; | |
88 | (void)[self initWithKCTypeDesc:&subtype]; | |
89 | _name = [NSString stringWithFormat:@"Type_0x%x", typeID]; | |
90 | return self; | |
91 | } | |
92 | ||
813fb2f6 A |
93 | #define read_unaligned(type, data) ({ \ |
94 | type x; \ | |
95 | memcpy((void*)&x, (void*)(data), sizeof(type)); \ | |
96 | x; }) | |
97 | ||
3e170ce0 A |
98 | - (NSObject *)objectForType:(kctype_subtype_t)elem_type withData:(uint8_t *)data |
99 | { | |
100 | NSObject * obj; | |
101 | ||
102 | switch (elem_type) { | |
103 | case KC_ST_CHAR: obj = [NSString stringWithFormat:@"%c", *(char *)data]; break; | |
813fb2f6 A |
104 | case KC_ST_INT8: obj = [NSNumber numberWithInt:read_unaligned(int8_t, data)]; break; |
105 | case KC_ST_UINT8: obj = [NSNumber numberWithInt:read_unaligned(uint8_t, data)]; break; | |
106 | case KC_ST_INT16: obj = [NSNumber numberWithShort:read_unaligned(int16_t, data)]; break; | |
107 | case KC_ST_UINT16: obj = [NSNumber numberWithUnsignedShort:read_unaligned(uint16_t, data)]; break; | |
108 | case KC_ST_INT32: obj = [NSNumber numberWithInt:read_unaligned(int32_t, data)]; break; | |
109 | case KC_ST_UINT32: obj = [NSNumber numberWithUnsignedInt:read_unaligned(uint32_t, data)]; break; | |
110 | case KC_ST_INT64: obj = [NSNumber numberWithLongLong:read_unaligned(int64_t, data)]; break; | |
111 | case KC_ST_UINT64: obj = [NSNumber numberWithUnsignedLongLong:read_unaligned(uint64_t, data)]; break; | |
3e170ce0 A |
112 | |
113 | default: obj = @"<Unknown error occurred>"; break; | |
114 | } | |
115 | ||
116 | return obj; | |
117 | } | |
118 | ||
39037602 | 119 | - (NSDictionary *)parseData:(void *)dataBuffer ofLength:(uint32_t)length |
3e170ce0 A |
120 | { |
121 | NSMutableDictionary * retval = [[NSMutableDictionary alloc] init]; | |
39037602 A |
122 | if (length <= _subtype_desc.kcs_elem_offset) |
123 | return retval; | |
3e170ce0 | 124 | uint8_t * data = (uint8_t *)dataBuffer; |
39037602 A |
125 | /* |
126 | * Calculate the maximum number of data elements we can parse, Taking into | |
127 | * account the maximum size specified by the type description, and also the | |
128 | * actual length of the data buffer and the offset into the buffer where we | |
129 | * begin parsing. | |
130 | */ | |
131 | uint32_t elem_count = MIN(_count, (length - _subtype_desc.kcs_elem_offset) / (_size / _count)); | |
3e170ce0 | 132 | uint32_t elem_size = _size / _count; |
39037602 A |
133 | if (elem_count == 0) { |
134 | return retval; | |
135 | } else if (elem_count == 1) { | |
3e170ce0 A |
136 | retval[_name] = [self objectForType:_subtype_desc.kcs_elem_type withData:&data[_subtype_desc.kcs_elem_offset]]; |
137 | } else if (_subtype_desc.kcs_elem_type == KC_ST_CHAR) { | |
39037602 A |
138 | char *s = (char *)&data[_subtype_desc.kcs_elem_offset]; |
139 | if (!(strnlen(s, length) < length)) { | |
140 | return nil; | |
141 | } | |
142 | retval[_name] = [NSString stringWithFormat:@"%s", s]; | |
3e170ce0 A |
143 | } else { |
144 | NSMutableArray * objArray = [NSMutableArray arrayWithCapacity:elem_count]; | |
145 | for (unsigned int i = 0; i < elem_count; i++) { | |
146 | [objArray addObject:[self objectForType:_subtype_desc.kcs_elem_type | |
147 | withData:&data[(_subtype_desc.kcs_elem_offset + (elem_size * i))]]]; | |
148 | } | |
149 | retval[_name] = objArray; | |
150 | } | |
151 | return retval; | |
152 | } | |
153 | ||
154 | - (NSString *)description | |
155 | { | |
39037602 A |
156 | if (_subtype_desc.kcs_flags & KCS_SUBTYPE_FLAGS_ARRAY) { |
157 | return [NSString stringWithFormat:@"[%d,%d] %s %s[%d];", _subtype_desc.kcs_elem_offset, kcs_get_elem_size(&_subtype_desc), name_for_subtype(_subtype_desc.kcs_elem_type), _subtype_desc.kcs_name, kcs_get_elem_count(&_subtype_desc) ]; | |
158 | }else { | |
159 | return [NSString stringWithFormat:@"[%d,%d] %s %s;", _subtype_desc.kcs_elem_offset, kcs_get_elem_size(&_subtype_desc), name_for_subtype(_subtype_desc.kcs_elem_type), _subtype_desc.kcs_name ]; | |
160 | } | |
161 | //return [NSString stringWithFormat:@"type: %d => \"%@\" ", [self typeID], [self name]]; | |
3e170ce0 A |
162 | } |
163 | ||
164 | - (NSString *)name | |
165 | { | |
166 | return _name; | |
167 | } | |
168 | ||
169 | - (uint32_t)count | |
170 | { | |
171 | return _count; | |
172 | } | |
173 | ||
39037602 | 174 | - (unsigned int)typeID |
3e170ce0 A |
175 | { |
176 | return _typeID; | |
177 | } | |
178 | ||
39037602 A |
179 | - (BOOL) shouldMergeData |
180 | { | |
181 | return TRUE; | |
182 | } | |
183 | ||
3e170ce0 | 184 | @end |