441
441
#endif
442
442
443
443
444
+ #ifdef INCLUDE_BASE36
445
+ #define BASE36_LENGTH 13
446
+ /***********************************************************************
447
+ **
448
+ */ static const REBYTE Enbase36 [36 ] =
449
+ /*
450
+ ** Base-36 binary encoder table.
451
+ **
452
+ ***********************************************************************/
453
+ {
454
+ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
455
+ };
456
+
457
+ static REBU64 base36_powers [BASE36_LENGTH ] = {
458
+ 1ULL ,
459
+ 36ULL ,
460
+ 1296ULL ,
461
+ 46656ULL ,
462
+ 1679616ULL ,
463
+ 60466176ULL ,
464
+ 2176782336ULL ,
465
+ 78364164096ULL ,
466
+ 2821109907456ULL ,
467
+ 101559956668416ULL ,
468
+ 3656158440062976ULL ,
469
+ 131621703842267136ULL ,
470
+ 4738381338321616896ULL
471
+ };
472
+ #endif
473
+
474
+
444
475
/***********************************************************************
445
476
**
446
477
*/ static REBSER * Decode_Base2 (const REBYTE * * src , REBCNT len , REBYTE delim )
727
758
}
728
759
#endif
729
760
761
+ #ifdef INCLUDE_BASE36
762
+ /***********************************************************************
763
+ **
764
+ */ static REBSER * Decode_Base36 (const REBYTE * * src , REBCNT len , REBYTE delim )
765
+ /*
766
+ ***********************************************************************/
767
+ {
768
+ REBYTE * bp ;
769
+ const REBYTE * cp ;
770
+ REBSER * ser ;
771
+ REBCNT ser_size ;
772
+ REBCNT chunk ;
773
+ REBINT pad = 0 ;
774
+ REBU64 c = 0 ;
775
+ REBINT i , d = 0 ;
776
+
777
+ cp = * src ;
778
+
779
+ if (len > BASE36_LENGTH ) goto err ;
780
+ else if (len == 0 ) {
781
+ ser = Make_Binary (1 );
782
+ ser -> tail = 0 ;
783
+ return ser ;
784
+ }
785
+
786
+ for (i = 0 ; i < len ; i ++ ) {
787
+ if (cp [i ] >= '0' && cp [i ] <= '9' )
788
+ d = cp [i ] - '0' ;
789
+ else if (cp [i ] >= 'A' && cp [i ] <= 'Z' )
790
+ d = 10 + cp [i ] - 'A' ;
791
+ else if (cp [i ] >= 'a' && cp [i ] <= 'z' )
792
+ d = 10 + cp [i ] - 'a' ;
793
+ else goto err ;
794
+
795
+ c += d * base36_powers [len - i - 1 ];
796
+ if (c < 0 ) goto err ;
797
+ }
798
+ // Allocate buffer large enough to hold result:
799
+ ser = Make_Binary (8 );
800
+ ser_size = SERIES_AVAIL (ser );
801
+ bp = STR_HEAD (ser );
802
+
803
+ for (i = 7 ; i >= 0 ; i -- ) {
804
+ bp [i ] = (REBYTE )(c & 0xFF );
805
+ c >>= 8 ;
806
+ }
807
+ ser -> tail = 8 ;
808
+ return ser ;
809
+
810
+ err :
811
+ * src = cp ;
812
+ return 0 ;
813
+ }
814
+ #endif
815
+
730
816
731
817
/***********************************************************************
732
818
**
753
839
ser = Decode_Base85 (& src , len , delim );
754
840
#else
755
841
Trap0 (RE_FEATURE_NA );
842
+ #endif
843
+ break ;
844
+ case 36 :
845
+ #ifdef INCLUDE_BASE36
846
+ ser = Decode_Base36 (& src , len , delim );
847
+ #else
848
+ Trap0 (RE_FEATURE_NA );
756
849
#endif
757
850
break ;
758
851
}
954
1047
955
1048
return series ;
956
1049
}
1050
+ #endif
1051
+
1052
+
1053
+ #ifdef INCLUDE_BASE36
1054
+ /***********************************************************************
1055
+ **
1056
+ */ REBSER * Encode_Base36 (REBVAL * value , REBSER * series , REBCNT len , REBFLG brk )
1057
+ /*
1058
+ ** Base36 encode a given series. Must be BYTES, not UNICODE.
1059
+ **
1060
+ ***********************************************************************/
1061
+ {
1062
+ REBYTE * bp ;
1063
+ REBYTE * src ;
1064
+ REBOOL discard = TRUE;
1065
+ REBU64 d , m = 0 ;
1066
+ REBCNT n , p = 0 ;
1067
+ REBINT i ;
1068
+
1069
+ if (len > VAL_LEN (value )) len = VAL_LEN (value );
1070
+ if (len > sizeof (REBI64 )) {
1071
+ Trap1 (RE_OUT_OF_RANGE , value );
1072
+ }
1073
+ else if (len == 0 ) {
1074
+ series = Prep_String (series , & bp , 1 );
1075
+ SERIES_TAIL (series ) = 0 ;
1076
+ return series ;
1077
+ }
1078
+ src = VAL_BIN_DATA (value );
1079
+
1080
+ for (bp = src , n = len ; n ; n -- , bp ++ )
1081
+ m = (m << 8 ) | * bp ;
1082
+
1083
+ series = Prep_String (series , & bp , BASE36_LENGTH + 1 );
1084
+
1085
+ for (i = BASE36_LENGTH - 1 ; i >= 0 ; i -- ) {
1086
+ d = m / base36_powers [i ];
1087
+ m = m - base36_powers [i ] * d ;
1088
+ discard = discard && (d == 0 && i > 0 );
1089
+ if (!discard )
1090
+ bp [p ++ ] = Enbase36 [d ];
1091
+ }
1092
+ SERIES_TAIL (series ) = p ;
1093
+ return series ;
1094
+ }
957
1095
#endif
0 commit comments