Changeset 8105 in project


Ignore:
Timestamp:
02/03/08 09:19:08 (12 years ago)
Author:
Jim Ursetto
Message:

base64: reimplement in C (10-20x speedup)

Location:
release/3/base64
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • release/3/base64/base64.meta

    r2615 r8105  
    11;;; base64.meta -*- Hen -*-
    22((egg "base64.egg")
    3  (date "2003-07-26")
     3 (date "2008-02-03")
    44 (synopsis "Parsing and unparsing of base-64 strings")
    55 (category parsing)
  • release/3/base64/base64.scm

    r2615 r8105  
    2323
    2424;; ported to CHICKEN by felix
     25;; reimplemented in C by zbigniew [2008]
    2526
    2627(declare
    27   (fixnum)
    28   (export base64:encode base64:decode) )
     28 (fixnum)
     29 (export base64:encode base64:decode))
    2930
    30 (define base64:enc-table
    31   '#(#\A #\B #\C #\D #\E #\F #\G #\H #\I #\J #\K #\L #\M #\N #\O #\P #\Q #\R #\S #\T #\U #\V #\W #\X #\Y #\Z
    32      #\a #\b #\c #\d #\e #\f #\g #\h #\i #\j #\k #\l #\m #\n #\o #\p #\q #\r #\s #\t #\u #\v #\w #\x #\y #\z
    33      #\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9 #\+ #\/))
     31#>
     32static char enc_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    3433
    35 ;; easily generated by a macro, but this is more portable / understandable
    36 (define base64:dec-table
    37   '#(0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
    38      0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
    39      0  0  0  0  0  0  0  0  0  0  0  62 0  0  0  63
    40      52 53 54 55 56 57 58 59 60 61 0  0  0  0  0  0
    41      0  0  1  2  3  4  5  6  7  8  9  10 11 12 13 14
    42      15 16 17 18 19 20 21 22 23 24 25 0  0  0  0  0
    43      0  26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
    44      41 42 43 44 45 46 47 48 49 50 51 0  0  0  0  0
    45      0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
    46      0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
    47      0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
    48      0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
    49      0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
    50      0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
    51      0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
    52      0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0))
     34static char dec_table[] = {
     35     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
     36     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
     37     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  62, 0,  0,  0,  63,
     38     52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0,  0,  0,  0,  0,  0,
     39     0,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14,
     40     15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0,  0,  0,  0,  0,
     41     0,  26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
     42     41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0,  0,  0,  0,  0,
     43     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
     44     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
     45     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
     46     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
     47     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
     48     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
     49     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
     50     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
     51};
    5352
    54 ;; the macro for the above
    55 ;;(define-macro (calc-dec)
    56 ;;  (let ((res (make-vector 256 0)))
    57 ;;    (do ((i 0 (+ i 1)))
    58 ;;      ((>= i 64))
    59 ;;      (vector-set! res (char->integer (vector-ref base64:enc-table i)) i))
    60 ;;    `(quote ,res)))
    61 ;;
    62 ;;(define base64:dec-table (calc-dec))
     53static void base64_encode(char *dst, const char *src, int len) {
     54    int i, o, r;
     55    for (i = 0, o = 0, r = len; i < len; i+= 3, o+= 4, r -= 3) {
     56        int n = src[i] << 16;
     57        if (r > 1)
     58            n |= src[i+1] << 8;
     59        dst[o] = enc_table[(n >> 18) & 63];
     60        dst[o+1] = enc_table[(n >> 12) & 63];
     61        if (r > 1) {
     62            if (r > 2) {
     63                n |= src[i+2];
     64                dst[o+3] = enc_table[n & 63];
     65            }
     66            dst[o+2] = enc_table[(n >> 6) & 63];
     67        }
     68    }
     69
     70    switch(r) {
     71      case -2: dst[o-2] = '=';
     72      case -1: dst[o-1] = '=';
     73    }
     74}                                                               
     75
     76static void base64_decode(char *dst, const char *src, int len) {
     77    int i, o, r;
     78    for (i = 0, o = 0, r = len; i < len; i += 4, o += 3, r -= 3) {
     79        int n = dec_table[src[i]] << 18  | dec_table[src[i+1]] << 12 |
     80                dec_table[src[i+2]] << 6 | dec_table[src[i+3]];
     81        dst[o] = (n >> 16) & 255;
     82        if (r > 1) {
     83            dst[o+1] = (n >> 8) & 255;
     84            if (r > 2) {
     85                dst[o+2] = n & 255;
     86            }
     87        }
     88    }
     89}                                                               
     90
     91<#
    6392
    6493(define (base64:encode str)
    65   (let* ((l (string-length str))
    66          (res (make-string (* 4 (fx/ (+ l 2) 3)) #\=))
    67          (bits-at (lambda
    68                     (idx) (char->integer (string-ref str idx)))))
    69 
    70     (do ((i 0 (+ i 3))
    71          (o 0 (+ o 4))
    72          (remaining l (- remaining 3)))
    73       ((>= i l))
    74 
    75       ;; take in 3 bytes, making a 24 bit integer
    76       ;; but this is done in steps depending on how many characters are remaining
    77       ;; always take one
    78       (let ((n (arithmetic-shift (bits-at i) 16)))
    79 
    80         ;; take the second if there is one
    81         (if (> remaining 1)
    82           (set! n (bitwise-ior n (arithmetic-shift (bits-at (+ i 1)) 8))))
    83 
    84         ;; write out the first two characters
    85         (string-set! res o (vector-ref base64:enc-table (bitwise-and (arithmetic-shift n -18) 63)))
    86         (string-set! res (+ o 1) (vector-ref base64:enc-table (bitwise-and (arithmetic-shift n -12) 63)))
    87 
    88         (when (> remaining 1)
    89           ;; if there is a third, add that too, and write out the fourth result
    90           (when (> remaining 2)
    91             (set! n (bitwise-ior n (bits-at (+ i 2))))
    92             (string-set! res (+ o 3) (vector-ref base64:enc-table (bitwise-and n 63))))
    93          
    94           ;; write out the third result
    95           (string-set! res (+ o 2) (vector-ref base64:enc-table (bitwise-and (arithmetic-shift n -6) 63))))))
    96 
    97     res))
    98 
    99 
     94  (define base64_encode (foreign-lambda void base64_encode pointer c-string int))
     95  (let* ((len (string-length str))
     96         (buf (##sys#make-string (* 4 (/ (+ len 2) 3))
     97                                 #f)))
     98    (base64_encode buf str len)
     99    buf))
    100100
    101101(define (base64:decode str)
    102   (let* ((l (string-length str))
    103          (tmp (* 3 (fx/ l 4)))
    104          (res-l (cond
    105                   ((char=? (string-ref str (- l 2)) #\=)
    106                    (- tmp 2))
    107                   ((char=? (string-ref str (- l 1)) #\=)
    108                    (- tmp 1))
    109                   (else tmp)))
    110          (res (make-string res-l))
    111          (bits-at (lambda (idx)
    112                     (vector-ref base64:dec-table (char->integer (string-ref str idx))))))
    113 
    114     (do ((i 0 (+ i 4))
    115          (o 0 (+ o 3))
    116          (remaining res-l (- remaining 3)))
    117       ((>= i l))
    118 
    119       ;; take in 4 bytes, making a 24 bit integer
    120       (let ((n (bitwise-ior
    121                  (bitwise-ior (arithmetic-shift (bits-at i) 18)
    122                          (arithmetic-shift (bits-at (+ i 1)) 12))
    123                  (bitwise-ior (arithmetic-shift (bits-at (+ i 2)) 6)
    124                          (bits-at (+ i 3))))))
    125         ;; now write out 3 bytes at a time
    126         (string-set! res o (integer->char (bitwise-and (arithmetic-shift n -16) 255)))
    127         (when (> remaining 1)
    128           (string-set! res (+ o 1) (integer->char (bitwise-and (arithmetic-shift n -8) 255)))
    129           (when (> remaining 2)
    130             (string-set! res (+ o 2) (integer->char (bitwise-and n 255)))))))
    131 
    132     res))
    133 
     102  (define base64_decode (foreign-lambda void base64_decode pointer c-string int))
     103  (let* ((len (string-length str))
     104         (result-len (- (* 3 (/ len 4))
     105                        (cond ((char=? (string-ref str (- len 2)) #\=) 2)
     106                              ((char=? (string-ref str (- len 1)) #\=) 1)
     107                              (else 0))))
     108         (buf (##sys#make-string result-len #f)))
     109    (base64_decode buf str len)
     110    buf))
  • release/3/base64/base64.setup

    r2615 r8105  
    33 'base64
    44 '("base64.html" "base64.so")
    5  '((version 1.3)
     5 '((version 2.0)
    66   (exports "base64.exports")
    77   (documentation "base64.html")))
Note: See TracChangeset for help on using the changeset viewer.