ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Convert-BER-XS/XS.xs
(Generate patch)

Comparing Convert-BER-XS/XS.xs (file contents):
Revision 1.8 by root, Sat Apr 20 01:50:13 2019 UTC vs.
Revision 1.13 by root, Sat Apr 20 13:46:14 2019 UTC

1#include "EXTERN.h" 1#include "EXTERN.h"
2#include "perl.h" 2#include "perl.h"
3#include "XSUB.h" 3#include "XSUB.h"
4 4
5// C99 required 5// C99 required!
6// this is not just for comments, but also for
7// integer constant semantics,
8// sscanf format modifiers and more.
6 9
7enum { 10enum {
8 // ASN_TAG 11 // ASN_TAG
9 ASN_BOOLEAN = 0x01, 12 ASN_BOOLEAN = 0x01,
10 ASN_INTEGER32 = 0x02, 13 ASN_INTEGER32 = 0x02,
92 95
93static profile_type *cur_profile, *default_profile; 96static profile_type *cur_profile, *default_profile;
94static SV *buf_sv; // encoding buffer 97static SV *buf_sv; // encoding buffer
95static U8 *buf, *cur, *end; // buffer start, current, end 98static U8 *buf, *cur, *end; // buffer start, current, end
96 99
100#if PERL_VERSION < 18
101# define utf8_to_uvchr_buf(s,e,l) utf8_to_uvchr (s, l)
102#endif
103
97#if __GNUC__ >= 3 104#if __GNUC__ >= 3
98# define expect(expr,value) __builtin_expect ((expr), (value)) 105# define expect(expr,value) __builtin_expect ((expr), (value))
99# define INLINE static inline 106# define INLINE static inline
100#else 107#else
101# define expect(expr,value) (expr) 108# define expect(expr,value) (expr)
155 return BER_TYPE_BYTES; 162 return BER_TYPE_BYTES;
156 163
157 return SvPVX (sv)[idx]; 164 return SvPVX (sv)[idx];
158} 165}
159 166
160static int 167static void
161profile_set (profile_type *profile, int klass, int tag, int type) 168profile_set (profile_type *profile, int klass, int tag, int type)
162{ 169{
163 SV *sv = (SV *)profile; 170 SV *sv = (SV *)profile;
164 U32 idx = (tag << 2) + klass; 171 U32 idx = (tag << 2) + klass;
165 STRLEN oldlen = SvCUR (sv); 172 STRLEN oldlen = SvCUR (sv);
187 } *celem, default_map[] = { 194 } *celem, default_map[] = {
188 { ASN_UNIVERSAL, ASN_BOOLEAN , BER_TYPE_BOOL }, 195 { ASN_UNIVERSAL, ASN_BOOLEAN , BER_TYPE_BOOL },
189 { ASN_UNIVERSAL, ASN_INTEGER32 , BER_TYPE_INT }, 196 { ASN_UNIVERSAL, ASN_INTEGER32 , BER_TYPE_INT },
190 { ASN_UNIVERSAL, ASN_NULL , BER_TYPE_NULL }, 197 { ASN_UNIVERSAL, ASN_NULL , BER_TYPE_NULL },
191 { ASN_UNIVERSAL, ASN_OBJECT_IDENTIFIER, BER_TYPE_OID }, 198 { ASN_UNIVERSAL, ASN_OBJECT_IDENTIFIER, BER_TYPE_OID },
192 { ASN_UNIVERSAL, ASN_OBJECT_DESCRIPTOR, BER_TYPE_OID },
193 { ASN_UNIVERSAL, ASN_RELATIVE_OID , BER_TYPE_RELOID }, 199 { ASN_UNIVERSAL, ASN_RELATIVE_OID , BER_TYPE_RELOID },
194 { ASN_UNIVERSAL, ASN_REAL , BER_TYPE_REAL }, 200 { ASN_UNIVERSAL, ASN_REAL , BER_TYPE_REAL },
201 { ASN_UNIVERSAL, ASN_ENUMERATED , BER_TYPE_INT },
195 { ASN_UNIVERSAL, ASN_UTF8_STRING , BER_TYPE_UTF8 }, 202 { ASN_UNIVERSAL, ASN_UTF8_STRING , BER_TYPE_UTF8 },
196 { ASN_UNIVERSAL, ASN_BMP_STRING , BER_TYPE_UCS2 }, 203 { ASN_UNIVERSAL, ASN_BMP_STRING , BER_TYPE_UCS2 },
197 { ASN_UNIVERSAL, ASN_UNIVERSAL_STRING , BER_TYPE_UCS4 }, 204 { ASN_UNIVERSAL, ASN_UNIVERSAL_STRING , BER_TYPE_UCS4 },
198 }; 205 };
199 206
200 for (celem = default_map + sizeof (default_map) / sizeof (default_map [0]); celem > default_map; celem--) 207 for (celem = default_map + sizeof (default_map) / sizeof (default_map [0]); celem-- > default_map; )
201 profile_set ((void *)sv, celem->klass, celem->tag, celem->type); 208 profile_set ((profile_type *)sv, celem->klass, celem->tag, celem->type);
202 209
203 return sv_bless (newRV_noinc (sv), profile_stash); 210 return sv_bless (newRV_noinc (sv), profile_stash);
204} 211}
205 212
206///////////////////////////////////////////////////////////////////////////// 213/////////////////////////////////////////////////////////////////////////////
329 // the one-digit case is absolutely predominant, so this pays off (hopefully) 336 // the one-digit case is absolutely predominant, so this pays off (hopefully)
330 if (expect_true (u < 10)) 337 if (expect_true (u < 10))
331 *buf++ = u + '0'; 338 *buf++ = u + '0';
332 else 339 else
333 { 340 {
341 // this *could* be done much faster using branchless fixed-ppint arithmetics
334 char *beg = buf; 342 char *beg = buf;
335 343
336 do 344 do
337 { 345 {
338 *buf++ = u % 10 + '0'; 346 *buf++ = u % 10 + '0';
339 u /= 10; 347 u /= 10;
340 } 348 }
341 while (u); 349 while (u);
342 350
343 // reverse digits 351 // reverse digits
344 for (char *ptr = buf; --ptr != beg; ++beg) 352 char *ptr = buf;
353 while (--ptr > beg)
345 { 354 {
346 char c = *ptr; 355 char c = *ptr;
347 *ptr = *beg; 356 *ptr = *beg;
348 *beg = c; 357 *beg = c;
358 ++beg;
349 } 359 }
350 } 360 }
351 361
352 return buf; 362 return buf;
353} 363}
364 } 374 }
365 375
366 U8 *end = cur + len; 376 U8 *end = cur + len;
367 U32 w = get_w (); 377 U32 w = get_w ();
368 378
369 static char oid[MAX_OID_STRLEN]; // must be static 379 static char oid[MAX_OID_STRLEN]; // static, becaueds too large for stack
370 char *app = oid; 380 char *app = oid;
371 381
372 if (relative) 382 if (relative)
373 app = write_uv (app, w); 383 app = write_uv (app, w);
374 else 384 else
376 app = write_uv (app, (U8)w / 40); 386 app = write_uv (app, (U8)w / 40);
377 *app++ = '.'; 387 *app++ = '.';
378 app = write_uv (app, (U8)w % 40); 388 app = write_uv (app, (U8)w % 40);
379 } 389 }
380 390
391 while (cur < end)
392 {
381 // we assume an oid component is never > 64 bytes 393 // we assume an oid component is never > 64 digits
382 while (cur < end && oid + sizeof (oid) - app > 64) 394 if (oid + sizeof (oid) - app < 64)
383 { 395 croak ("BER_TYPE_OID to long to decode");
396
384 w = get_w (); 397 w = get_w ();
385 *app++ = '.'; 398 *app++ = '.';
386 app = write_uv (app, w); 399 app = write_uv (app, w);
387 } 400 }
388 401
458 } 471 }
459 else 472 else
460 switch (profile_lookup (cur_profile, klass, tag)) 473 switch (profile_lookup (cur_profile, klass, tag))
461 { 474 {
462 case BER_TYPE_NULL: 475 case BER_TYPE_NULL:
476 {
477 U32 len = get_length ();
478
479 if (len)
480 croak ("BER_TYPE_NULL value with non-zero length %d encountered", len);
481
463 res = &PL_sv_undef; 482 res = &PL_sv_undef;
483 }
464 break; 484 break;
465 485
466 case BER_TYPE_BOOL: 486 case BER_TYPE_BOOL:
467 { 487 {
468 U32 len = get_length (); 488 U32 len = get_length ();
469 489
470 if (len != 1) 490 if (len != 1)
471 croak ("BER_TYPE_BOOLEAN type with invalid length %d encountered", len); 491 croak ("BER_TYPE_BOOLEAN value with invalid length %d encountered", len);
472 492
473 res = newSVcacheint (get_u8 () ? 0 : 1); 493 res = newSVcacheint (!!get_u8 ());
474 } 494 }
475 break; 495 break;
476 496
477 case BER_TYPE_OID: 497 case BER_TYPE_OID:
478 res = decode_oid (0); 498 res = decode_oid (0);
553static void 573static void
554set_buf (SV *sv) 574set_buf (SV *sv)
555{ 575{
556 STRLEN len; 576 STRLEN len;
557 buf_sv = sv; 577 buf_sv = sv;
558 buf = SvPVbyte (buf_sv, len); 578 buf = (U8 *)SvPVbyte (buf_sv, len);
559 cur = buf; 579 cur = buf;
560 end = buf + len; 580 end = buf + len;
561} 581}
562 582
563/* similar to SvGROW, but somewhat safer and guarantees exponential realloc strategy */ 583/* similar to SvGROW, but somewhat safer and guarantees exponential realloc strategy */
577need (STRLEN len) 597need (STRLEN len)
578{ 598{
579 if (expect_false ((uintptr_t)(end - cur) < len)) 599 if (expect_false ((uintptr_t)(end - cur) < len))
580 { 600 {
581 STRLEN pos = cur - buf; 601 STRLEN pos = cur - buf;
582 buf = my_sv_grow (buf_sv, pos, len); 602 buf = (U8 *)my_sv_grow (buf_sv, pos, len);
583 cur = buf + pos; 603 cur = buf + pos;
584 end = buf + SvLEN (buf_sv) - 1; 604 end = buf + SvLEN (buf_sv) - 1;
585 } 605 }
586} 606}
587 607
813 put_length (uchars * chrsize); 833 put_length (uchars * chrsize);
814 834
815 while (uchars--) 835 while (uchars--)
816 { 836 {
817 STRLEN uclen; 837 STRLEN uclen;
818 UV uchr = utf8_to_uvchr_buf (ptr, ptr + len, &uclen); 838 UV uchr = utf8_to_uvchr_buf ((U8 *)ptr, (U8 *)ptr + len, &uclen);
819 839
820 ptr += uclen; 840 ptr += uclen;
821 len -= uclen; 841 len -= uclen;
822 842
823 if (chrsize == 4) 843 if (chrsize == 4)
864 int fill = AvFILL (av); 884 int fill = AvFILL (av);
865 885
866 if (expect_false (SvRMAGICAL (av))) 886 if (expect_false (SvRMAGICAL (av)))
867 croak ("BER constructed data must not be tied"); 887 croak ("BER constructed data must not be tied");
868 888
889 int i;
869 for (int i = 0; i <= fill; ++i) 890 for (i = 0; i <= fill; ++i)
870 encode_ber (AvARRAY (av)[i]); 891 encode_ber (AvARRAY (av)[i]);
871 892
872 len_fixup (mark); 893 len_fixup (mark);
873 } 894 }
874 else 895 else
1024ber_decode (SV *ber, SV *profile = &PL_sv_undef) 1045ber_decode (SV *ber, SV *profile = &PL_sv_undef)
1025 CODE: 1046 CODE:
1026{ 1047{
1027 cur_profile = SvPROFILE (profile); 1048 cur_profile = SvPROFILE (profile);
1028 STRLEN len; 1049 STRLEN len;
1029 buf = SvPVbyte (ber, len); 1050 buf = (U8 *)SvPVbyte (ber, len);
1030 cur = buf; 1051 cur = buf;
1031 end = buf + len; 1052 end = buf + len;
1032 1053
1033 RETVAL = decode_ber (); 1054 RETVAL = decode_ber ();
1034} 1055}

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines