]>
Commit | Line | Data |
---|---|---|
bac41a7b A |
1 | /* |
2 | * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. | |
3 | * | |
4 | * The contents of this file constitute Original Code as defined in and are | |
5 | * subject to the Apple Public Source License Version 1.2 (the 'License'). | |
6 | * You may not use this file except in compliance with the License. Please obtain | |
7 | * a copy of the License at http://www.apple.com/publicsource and read it before | |
8 | * using this file. | |
9 | * | |
10 | * This Original Code and all software distributed under the License are | |
11 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS | |
12 | * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT | |
13 | * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR | |
14 | * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the | |
15 | * specific language governing rights and limitations under the License. | |
16 | */ | |
17 | ||
18 | ||
19 | // file: .../c++-lib/src/asn-bits.C - AsnBits (ASN.1 BIT STRING) Type | |
20 | // | |
21 | // Mike Sample | |
22 | // 92/07/02 | |
23 | // Copyright (C) 1992 Michael Sample and the University of British Columbia | |
24 | // | |
25 | // This library is free software; you can redistribute it and/or | |
26 | // modify it provided that this copyright/license information is retained | |
27 | // in original form. | |
28 | // | |
29 | // If you modify this file, you must clearly indicate your changes. | |
30 | // | |
31 | // This source code is distributed in the hope that it will be | |
32 | // useful, but WITHOUT ANY WARRANTY; without even the implied warranty | |
33 | // of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |
34 | // | |
5a719ac8 | 35 | // $Header: /cvs/Darwin/src/live/Security/SecuritySNACCRuntime/c++-lib/c++/asn-bits.cpp,v 1.4 2002/03/21 05:38:44 dmitch Exp $ |
bac41a7b | 36 | // $Log: asn-bits.cpp,v $ |
29654253 A |
37 | // Revision 1.4 2002/03/21 05:38:44 dmitch |
38 | // Radar 2868524: no more setjmp/longjmp in SNACC-generated code. | |
39 | // | |
40 | // Revision 1.3.44.1 2002/03/20 00:36:48 dmitch | |
41 | // Radar 2868524: SNACC-generated code now uses throw/catch instead of setjmp/longjmp. | |
42 | // | |
bac41a7b A |
43 | // Revision 1.3 2001/06/28 23:36:11 dmitch |
44 | // Removed SccsId statics. numToHexCharTblG table now const. Radar 2705410. | |
45 | // | |
46 | // Revision 1.2 2001/06/27 23:09:14 dmitch | |
47 | // Pusuant to Radar 2664258, avoid all cerr-based output in NDEBUG configuration. | |
48 | // | |
49 | // Revision 1.1.1.1 2001/05/18 23:14:05 mb | |
50 | // Move from private repository to open source repository | |
51 | // | |
52 | // Revision 1.3 2001/05/05 00:59:17 rmurphy | |
53 | // Adding darwin license headers | |
54 | // | |
55 | // Revision 1.2 2000/12/07 22:15:49 dmitch | |
56 | // Thread-safe mods: added a local StrStk strStkG to the routines which need it. | |
57 | // | |
58 | // Revision 1.1 2000/06/15 18:44:57 dmitch | |
59 | // These snacc-generated source files are now checked in to allow cross-platform build. | |
60 | // | |
61 | // Revision 1.2 2000/06/08 20:05:34 dmitch | |
62 | // Mods for X port. These files are actually machine generated and probably don't need to be in CVS.... | |
63 | // | |
64 | // Revision 1.1.1.1 2000/03/09 01:00:05 rmurphy | |
65 | // Base Fortissimo Tree | |
66 | // | |
67 | // Revision 1.3 1999/03/21 02:07:35 mb | |
68 | // Added Copy to every AsnType. | |
69 | // | |
70 | // Revision 1.2 1999/02/26 00:23:39 mb | |
71 | // Fixed for Mac OS 8 | |
72 | // | |
73 | // Revision 1.1 1999/02/25 05:21:50 mb | |
74 | // Added snacc c++ library | |
75 | // | |
76 | // Revision 1.9 1997/08/27 15:55:15 wan | |
77 | // GetBit now returns 0 or 1, not 0 or <#bit>, even if bool type is emulated. | |
78 | // | |
79 | // Revision 1.8 1997/02/28 13:39:44 wan | |
80 | // Modifications collected for new version 1.3: Bug fixes, tk4.2. | |
81 | // | |
82 | // Revision 1.7 1997/01/01 20:19:01 rj | |
83 | // dereferencing pointer to member function is neither necessary nor allowed | |
84 | // | |
85 | // Revision 1.6 1995/08/17 15:37:49 rj | |
86 | // set Tcl's errorCode variable | |
87 | // | |
88 | // Revision 1.5 1995/07/24 20:09:07 rj | |
89 | // use memzero that is defined in .../snacc.h to use either memset or bzero. | |
90 | // use memcmpeq that is defined in .../snacc.h to use either memcmp or bcmp. | |
91 | // | |
92 | // call constructor with additional pdu and create arguments. | |
93 | // | |
94 | // #if TCL ... #endif wrapped into #if META ... #endif | |
95 | // | |
96 | // changed `_' to `-' in file names. | |
97 | // | |
98 | // Revision 1.4 1994/10/08 04:18:21 rj | |
99 | // code for meta structures added (provides information about the generated code itself). | |
100 | // | |
101 | // code for Tcl interface added (makes use of the above mentioned meta code). | |
102 | // | |
103 | // virtual inline functions (the destructor, the Clone() function, BEnc(), BDec() and Print()) moved from inc/*.h to src/*.C because g++ turns every one of them into a static non-inline function in every file where the .h file gets included. | |
104 | // | |
105 | // made Print() const (and some other, mainly comparison functions). | |
106 | // | |
107 | // several `unsigned long int' turned into `size_t'. | |
108 | // | |
109 | // Revision 1.3 1994/08/31 23:37:57 rj | |
110 | // TRUE turned into true | |
111 | // | |
112 | // Revision 1.2 1994/08/28 10:01:11 rj | |
113 | // comment leader fixed. | |
114 | // | |
115 | // Revision 1.1 1994/08/28 09:20:57 rj | |
116 | // first check-in. for a list of changes to the snacc-1.1 distribution please refer to the ChangeLog. | |
117 | ||
118 | #include "asn-config.h" | |
119 | #include "asn-len.h" | |
120 | #include "asn-tag.h" | |
121 | #include "asn-type.h" | |
122 | #include "asn-bits.h" | |
123 | #include "str-stk.h" | |
124 | ||
125 | #ifndef __APPLE__ | |
126 | ||
127 | /* OS X - thread safe - the only routine which uses this allocates | |
128 | * it on the stack */ | |
129 | extern StrStk strStkG; | |
130 | unsigned short int strStkUnusedBitsG; | |
131 | #endif /* __APPLE__ */ | |
132 | ||
133 | const | |
134 | char numToHexCharTblG[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; | |
135 | ||
136 | AsnBits::~AsnBits() | |
137 | { | |
138 | delete bits; | |
139 | } | |
140 | ||
141 | AsnType *AsnBits::Clone() const | |
142 | { | |
143 | return new AsnBits; | |
144 | } | |
145 | ||
146 | AsnType *AsnBits::Copy() const | |
147 | { | |
148 | return new AsnBits (*this); | |
149 | } | |
150 | ||
151 | // Initializes the bits string with a bit string numBits in length. | |
152 | // All bits are zeroed. | |
153 | void AsnBits::Set (size_t numBits) | |
154 | { | |
155 | bitLen = numBits; | |
156 | size_t octetLen = (bitLen+7)/8; | |
157 | ||
158 | #ifndef _IBM_ENC_ | |
159 | bits = Asn1Alloc (octetLen); | |
160 | #else | |
161 | bits = (char *) mem_mgr_ptr->Get (octetLen); // Guido Grassel, 11.8.93 | |
162 | #endif /* _IBM_ENC_ */ | |
163 | memzero (bits, octetLen); // init to zeros | |
164 | } | |
165 | ||
166 | // initializes a BIT STRING with the given string and bit length | |
167 | // Copies the bits from bitsOcts. | |
168 | void AsnBits::Set (const char *bitOcts, size_t numBits) | |
169 | { | |
170 | if (bitOcts != bits) | |
171 | { | |
172 | bitLen = numBits; | |
173 | size_t octetLen = (bitLen+7)/8; | |
174 | #ifndef _IBM_ENC_ | |
175 | bits = new char[octetLen]; | |
176 | #else | |
177 | bits = (char *) mem_mgr_ptr->Get (octetLen); // Guido Grassel, 11.8.93 | |
178 | #endif /* _IBM_ENC_ */ | |
179 | memcpy (bits, bitOcts, octetLen); | |
180 | } | |
181 | } | |
182 | ||
183 | // initializes a BIT STRING by copying another BIT STRING's bits | |
184 | void AsnBits::Set (const AsnBits &b) | |
185 | { | |
186 | if (&b != this) | |
187 | { | |
188 | bitLen = b.bitLen; | |
189 | size_t octetLen = (bitLen+7)/8; | |
190 | #ifndef _IBM_ENC_ | |
191 | bits = new char[octetLen]; | |
192 | #else | |
193 | bits = (char *) mem_mgr_ptr->Get (octetLen); // Guido Grassel, 11.8.93 | |
194 | #endif /* _IBM_ENC_ */ | |
195 | memcpy (bits, b.bits, octetLen); | |
196 | } | |
197 | } | |
198 | ||
199 | // Initializes the bits string with a bit string numBits in length. | |
200 | // All bits are zeroed. | |
201 | void AsnBits::ReSet (size_t numBits) | |
202 | { | |
203 | #ifndef _IBM_ENC_ | |
204 | delete bits; | |
205 | Set (numBits); | |
206 | #else | |
207 | mem_mgr_ptr->Put ((void *) bits); // Guido Grassel, 11.8.93 | |
208 | Set (numBits); | |
209 | #endif /* _IBM_ENC_ */ | |
210 | } | |
211 | ||
212 | // frees old bits value and then re-initializes the | |
213 | // BIT STRING with the given string and bit length | |
214 | // Copies the bitOcts into bits. | |
215 | void AsnBits::ReSet (const char *bitOcts, size_t numBits) | |
216 | { | |
217 | if (bitOcts != bits) | |
218 | { | |
219 | #ifndef _IBM_ENC_ | |
220 | delete bits; | |
221 | Set (bitOcts, numBits); | |
222 | #else | |
223 | mem_mgr_ptr->Put ((void *) bits); // Guido Grassel, 11.8.93 | |
224 | Set (bitOcts, numBits); | |
225 | #endif /* _IBM_ENC_ */ | |
226 | } | |
227 | } | |
228 | ||
229 | // frees old bits value and then re-initializes the | |
230 | // BIT STRING by copying another BIT STRING's bits | |
231 | void AsnBits::ReSet (const AsnBits &b) | |
232 | { | |
233 | if (&b != this) // avoid b = b; probs | |
234 | { | |
235 | #ifndef _IBM_ENC_ | |
236 | delete bits; | |
237 | Set (b); | |
238 | #else | |
239 | mem_mgr_ptr->Put ((void *) bits); // Guido Grassel, 11.8.93 | |
240 | Set (b); | |
241 | #endif /* _IBM_ENC_ */ | |
242 | } | |
243 | } | |
244 | ||
245 | ||
246 | // Returns true if the given BIT STRING is the same as this one | |
247 | bool AsnBits::BitsEquiv (const AsnBits &ab) const | |
248 | { | |
249 | size_t octetsLessOne = (bitLen-1)/8; | |
250 | size_t octetBits = 7 - (bitLen % 8); | |
251 | ||
252 | if (!bitLen && !ab.bitLen) | |
253 | return true; | |
254 | ||
255 | // trailing bits may not be significant | |
256 | return bitLen == ab.bitLen | |
257 | && !memcmpeq (bits, ab.bits, octetsLessOne) | |
258 | && (bits[octetsLessOne] & (0xFF << octetBits)) == (ab.bits[octetsLessOne] & (0xFF << octetBits)); | |
259 | } /* AsnBits::BitsEquiv */ | |
260 | ||
261 | ||
262 | // set given bit to 1. Most signif. bit is bit 0, least signif bit is bitLen-1 | |
263 | void AsnBits::SetBit (size_t bit) | |
264 | { | |
265 | if (bit < bitLen) | |
266 | { | |
267 | size_t octet = bit/8; | |
268 | size_t octetsBit = 7 - (bit % 8); // bit zero is first/most sig bit in octet | |
269 | bits[octet] |= 1 << octetsBit; | |
270 | } | |
271 | #ifdef DEBUG | |
272 | else | |
273 | Asn1Errror << "AsnBits::SetBit: ERROR - bit larger than bit string" << endl; | |
274 | #endif | |
275 | } /* AsnBits::SetBit */ | |
276 | ||
277 | // Clr bit. Most signif. bit is bit 0, least signif bit is bitLen-1 | |
278 | void AsnBits::ClrBit (size_t bit) | |
279 | { | |
280 | if (bit < bitLen) | |
281 | { | |
282 | size_t octet = bit/8; | |
283 | size_t octetsBit = 7 - (bit % 8); // bit zero is first/most sig bit in octet | |
284 | bits[octet] &= ~(1 << octetsBit); | |
285 | } | |
286 | #ifdef DEBUG | |
287 | else | |
288 | Asn1Errror << "AsnBits::ClrBit: ERROR - bit larger than bit string" << endl; | |
289 | #endif | |
290 | } /* AsnBits::ClrBit */ | |
291 | ||
292 | // returns given bit. Most signif. bit is bit 0, least signif bit is bitLen-1. | |
293 | // Returns false if the givnen bit index is out of range. | |
294 | bool AsnBits::GetBit (size_t bit) const | |
295 | { | |
296 | if (bit < bitLen) | |
297 | { | |
298 | size_t octet = bit/8; | |
299 | size_t octetsBit = 7 - (bit % 8); // bit zero is first/most sig bit in octet | |
300 | return !!(bits[octet] & (1 << octetsBit)); | |
301 | } | |
302 | #ifdef DEBUG | |
303 | else | |
304 | Asn1Errror << "AsnBits::GetBit: ERROR - bit larger than bit string" << endl; | |
305 | #endif | |
306 | ||
307 | return false; | |
308 | } /* AsnBits::GetBit */ | |
309 | ||
310 | ||
311 | // Encoded the content (included unused bits octet) of the BIT STRING | |
312 | // to the given buffer. | |
313 | AsnLen AsnBits::BEncContent (BUF_TYPE b) | |
314 | { | |
315 | size_t byteLen = (bitLen+7)/8; | |
316 | b.PutSegRvs (bits, byteLen); | |
317 | ||
318 | size_t unusedBits = (bitLen % 8); | |
319 | if (unusedBits != 0) | |
320 | unusedBits = 8 - unusedBits; | |
321 | b.PutByteRvs (unusedBits); | |
322 | ||
323 | return byteLen + 1; | |
324 | ||
325 | } /* AsnBits::BEncContent */ | |
326 | ||
327 | ||
328 | // Decodes a BER BIT STRING from the given buffer and stores | |
329 | // the value in this object. | |
330 | void AsnBits::BDecContent (BUF_TYPE b, AsnTag tagId, AsnLen elmtLen, AsnLen &bytesDecoded, ENV_TYPE env) | |
331 | { | |
332 | // char *tmp; | |
333 | ||
334 | /* | |
335 | * tagId is encoded tag shifted into long int. | |
336 | * if CONS bit is set then constructed bit string | |
337 | */ | |
338 | if (tagId & 0x20000000) | |
339 | BDecConsBits (b, elmtLen, bytesDecoded, env); | |
340 | ||
341 | else /* primitive octet string */ | |
342 | { | |
343 | bytesDecoded += elmtLen; | |
344 | elmtLen--; | |
345 | bitLen = (elmtLen * 8) - (unsigned int)b.GetByte(); | |
346 | #ifndef _IBM_ENC_ | |
347 | bits = Asn1Alloc (elmtLen); | |
348 | #else | |
349 | bits = (char *) mem_mgr_ptr->Get (elmtLen); // Guido Grassel, 11.8.93 | |
350 | #endif /* _IBM_ENC_ */ | |
351 | b.CopyOut (bits, elmtLen); | |
352 | if (b.ReadError()) | |
353 | { | |
354 | Asn1Error << "BDecBitString: ERROR - decoded past end of data" << endl; | |
29654253 A |
355 | #if SNACC_EXCEPTION_ENABLE |
356 | SnaccExcep::throwMe(-1); | |
357 | #else | |
bac41a7b | 358 | longjmp (env, -1); |
29654253 | 359 | #endif |
bac41a7b A |
360 | } |
361 | } | |
362 | ||
363 | } /* AsnBits::BDecContent */ | |
364 | ||
365 | AsnLen AsnBits::BEnc (BUF_TYPE b) | |
366 | { | |
367 | AsnLen l; | |
368 | l = BEncContent (b); | |
369 | l += BEncDefLen (b, l); | |
370 | l += BEncTag1 (b, UNIV, PRIM, BITSTRING_TAG_CODE); | |
371 | return l; | |
372 | } | |
373 | ||
374 | void AsnBits::BDec (BUF_TYPE b, AsnLen &bytesDecoded, ENV_TYPE env) | |
375 | { | |
376 | AsnLen elmtLen; | |
377 | AsnTag tag; | |
378 | ||
379 | tag = BDecTag (b, bytesDecoded, env); | |
380 | if ((tag != MAKE_TAG_ID (UNIV, PRIM, BITSTRING_TAG_CODE)) | |
381 | && (tag != MAKE_TAG_ID (UNIV, CONS, BITSTRING_TAG_CODE))) | |
382 | { | |
383 | Asn1Error << "AsnBits::BDec: ERROR tag on BIT STRING is wrong." << endl; | |
29654253 A |
384 | #if SNACC_EXCEPTION_ENABLE |
385 | SnaccExcep::throwMe(-50); | |
386 | #else | |
bac41a7b | 387 | longjmp (env,-50); |
29654253 | 388 | #endif |
bac41a7b A |
389 | } |
390 | elmtLen = BDecLen (b, bytesDecoded, env); | |
391 | BDecContent (b, tag, elmtLen, bytesDecoded, env); | |
392 | } | |
393 | ||
394 | /* | |
395 | * Used to concatentate constructed bit strings when decoding. | |
396 | * | |
397 | * fills string stack with references to the pieces of a | |
398 | * construced bit string. sets strStkUnusedBitsG appropriately. | |
399 | * and strStkTotalByteLenG to bytelen needed to hold the bitstring | |
400 | */ | |
401 | #ifdef __APPLE__ | |
402 | void AsnBits::FillBitStringStk (BUF_TYPE b, AsnLen elmtLen0, | |
403 | AsnLen &bytesDecoded, ENV_TYPE env, | |
404 | StrStk &strStkG, | |
405 | unsigned short int &strStkUnusedBitsG) | |
406 | #else | |
407 | void AsnBits::FillBitStringStk (BUF_TYPE b, AsnLen elmtLen0, | |
408 | AsnLen &bytesDecoded, ENV_TYPE env) | |
409 | #endif | |
410 | { | |
411 | size_t refdLen; | |
412 | size_t totalRefdLen; | |
413 | char *strPtr; | |
414 | AsnLen totalElmtsLen1 = 0; | |
415 | unsigned long int tagId1; | |
416 | AsnLen elmtLen1; | |
417 | size_t lenToRef; | |
418 | // size_t unusedBits; | |
419 | ||
420 | for (; (totalElmtsLen1 < elmtLen0) || (elmtLen0 == INDEFINITE_LEN); ) | |
421 | { | |
422 | tagId1 = BDecTag (b, totalElmtsLen1, env); | |
423 | ||
424 | if ((tagId1 == EOC_TAG_ID) && (elmtLen0 == INDEFINITE_LEN)) | |
425 | { | |
426 | BDEC_2ND_EOC_OCTET (b, totalElmtsLen1, env); | |
427 | break; | |
428 | } | |
429 | ||
430 | elmtLen1 = BDecLen (b, totalElmtsLen1, env); | |
431 | if (tagId1 == MAKE_TAG_ID (UNIV, PRIM, BITSTRING_TAG_CODE)) | |
432 | { | |
433 | /* | |
434 | * primitive part of string, put references to piece (s) in | |
435 | * str stack | |
436 | */ | |
437 | ||
438 | /* | |
439 | * get unused bits octet | |
440 | */ | |
441 | if (strStkUnusedBitsG != 0) | |
442 | { | |
443 | /* | |
444 | * whoa - only allowed non-octed aligned bits on | |
445 | * on last piece of bits string | |
446 | */ | |
447 | Asn1Error << "BDecConsBitString: ERROR - a component of a constructed BIT STRING that is not the last has non-zero unused bits" << endl; | |
29654253 A |
448 | #if SNACC_EXCEPTION_ENABLE |
449 | SnaccExcep::throwMe(-2); | |
450 | #else | |
bac41a7b | 451 | longjmp (env, -2); |
29654253 | 452 | #endif |
bac41a7b A |
453 | } |
454 | ||
455 | if (elmtLen1 != 0) | |
456 | strStkUnusedBitsG = b.GetByte(); | |
457 | ||
458 | totalRefdLen = 0; | |
459 | lenToRef =elmtLen1-1; /* remove one octet for the unused bits oct*/ | |
460 | refdLen = lenToRef; | |
461 | while (1) | |
462 | { | |
463 | strPtr = b.GetSeg (&refdLen); | |
464 | ||
465 | strStkG.Push (strPtr, refdLen); | |
466 | totalRefdLen += refdLen; | |
467 | if (totalRefdLen == lenToRef) | |
468 | break; /* exit this while loop */ | |
469 | ||
470 | if (refdLen == 0) /* end of data */ | |
471 | { | |
472 | Asn1Error << "BDecConsOctetString: ERROR - expecting more data" << endl; | |
29654253 A |
473 | #if SNACC_EXCEPTION_ENABLE |
474 | SnaccExcep::throwMe(-3); | |
475 | #else | |
bac41a7b | 476 | longjmp (env, -3); |
29654253 | 477 | #endif |
bac41a7b A |
478 | } |
479 | refdLen = lenToRef - totalRefdLen; | |
480 | } | |
481 | totalElmtsLen1 += elmtLen1; | |
482 | } | |
483 | ||
484 | ||
485 | else if (tagId1 == MAKE_TAG_ID (UNIV, CONS, BITSTRING_TAG_CODE)) | |
486 | { | |
487 | /* | |
488 | * constructed octets string embedding in this constructed | |
489 | * octet string. decode it. | |
490 | */ | |
491 | FillBitStringStk (b, elmtLen1, totalElmtsLen1, env | |
492 | #ifdef __APPLE__ | |
493 | , strStkG, strStkUnusedBitsG | |
494 | #endif | |
495 | ); | |
496 | } | |
497 | else /* wrong tag */ | |
498 | { | |
499 | Asn1Error << "BDecConsBitString: ERROR - decoded non-BIT STRING tag inside a constructed BIT STRING" << endl; | |
29654253 A |
500 | #if SNACC_EXCEPTION_ENABLE |
501 | SnaccExcep::throwMe(-4); | |
502 | #else | |
bac41a7b | 503 | longjmp (env, -4); |
29654253 | 504 | #endif |
bac41a7b A |
505 | } |
506 | } /* end of for */ | |
507 | ||
508 | bytesDecoded += totalElmtsLen1; | |
509 | } /* FillBitStringStk */ | |
510 | ||
511 | ||
512 | /* | |
513 | * decodes a seq of universally tagged bits until either EOC is | |
514 | * encountered or the given len decoded. Return them in a | |
515 | * single concatenated bit string | |
516 | */ | |
517 | void AsnBits::BDecConsBits (BUF_TYPE b, AsnLen elmtLen, AsnLen &bytesDecoded, ENV_TYPE env) | |
518 | { | |
519 | #ifdef __APPLE__ | |
520 | StrStk strStkG(128, 64); | |
521 | unsigned short int strStkUnusedBitsG; | |
522 | #endif | |
523 | strStkG.Reset(); | |
524 | strStkUnusedBitsG = 0; | |
525 | ||
526 | /* | |
527 | * decode each piece of the octet string, puting | |
528 | * an entry in the octet/bit string stack for each | |
529 | */ | |
530 | FillBitStringStk (b, elmtLen, bytesDecoded, env, strStkG, | |
531 | strStkUnusedBitsG); | |
532 | ||
533 | /* alloc single str long enough for combined bitstring */ | |
534 | bitLen = strStkG.totalByteLen*8 - strStkUnusedBitsG; | |
535 | ||
536 | #ifndef _IBM_ENC_ | |
537 | bits = Asn1Alloc (strStkG.totalByteLen); | |
538 | #else | |
539 | bits = (char *) mem_mgr_ptr->Get (strStkG.totalByteLen); // Guido Grassel, 11.8.93 | |
540 | #endif /* _IBM_ENC_ */ | |
541 | ||
542 | strStkG.CopyOut (bits); | |
543 | ||
544 | } /* BDecConsBits */ | |
545 | ||
546 | // prints the BIT STRING to the given ostream. | |
547 | void AsnBits::Print (ostream &os) const | |
548 | { | |
549 | #ifndef NDEBUG | |
550 | size_t octetLen = (bitLen+7)/8; | |
551 | ||
552 | os << "'"; | |
29654253 | 553 | for (unsigned i = 0; i < octetLen; i++) |
bac41a7b A |
554 | os << TO_HEX (bits[i] >> 4) << (TO_HEX (bits[i])); |
555 | os << "'H -- BIT STRING bitlen = " << bitLen << " --"; | |
556 | #endif /* NDEBUG */ | |
557 | } | |
558 | ||
559 | #if META | |
560 | ||
561 | const AsnBitsTypeDesc AsnBits::_desc (NULL, NULL, false, AsnTypeDesc::BIT_STRING, NULL, NULL); | |
562 | ||
563 | const AsnTypeDesc *AsnBits::_getdesc() const | |
564 | { | |
565 | return &_desc; | |
566 | } | |
567 | ||
568 | #if TCL | |
569 | ||
570 | int AsnBits::TclGetVal (Tcl_Interp *interp) const | |
571 | { | |
572 | Tcl_ResetResult(interp); | |
573 | for (int i=0; i<bitLen; i++) | |
574 | Tcl_AppendResult(interp,GetBit (i) ? "1" : "0",NULL); | |
575 | return TCL_OK; | |
576 | } | |
577 | ||
578 | int AsnBits::TclSetVal (Tcl_Interp *interp, const char *valstr) | |
579 | { | |
580 | int i; | |
581 | const char *p; | |
582 | ||
583 | for (i=0, p=valstr; *p; i++, p++) | |
584 | switch (*p) | |
585 | { | |
586 | case '0': | |
587 | case '1': | |
588 | break; | |
589 | default: | |
590 | const char c[2] = { *p, '\0' }; | |
591 | Tcl_AppendResult (interp, "illegal character '", c, "' for bit in type ", _getdesc()->getmodule()->name, ".", _getdesc()->getname(), NULL); | |
592 | Tcl_SetErrorCode (interp, "SNACC", "ILLBIT", NULL); | |
593 | return TCL_ERROR; | |
594 | } | |
595 | ||
596 | ReSet (i); | |
597 | ||
598 | for (i=0, p=valstr; i<bitLen; i++, p++) | |
599 | *p == '0' ? ClrBit(i) : SetBit(i); | |
600 | ||
601 | return TCL_OK; | |
602 | } | |
603 | ||
604 | #endif /* TCL */ | |
605 | #endif /* META */ |