diff options
Diffstat (limited to 'lib/pure/base64.nim')
-rw-r--r-- | lib/pure/base64.nim | 79 |
1 files changed, 58 insertions, 21 deletions
diff --git a/lib/pure/base64.nim b/lib/pure/base64.nim index 41d19dc0f..32d37ce02 100644 --- a/lib/pure/base64.nim +++ b/lib/pure/base64.nim @@ -8,12 +8,44 @@ # ## This module implements a base64 encoder and decoder. +## +## Encoding data +## ------------- +## +## In order to encode some text simply call the ``encode`` procedure: +## +## .. code-block::nim +## import base64 +## let encoded = encode("Hello World") +## echo(encoded) # SGVsbG8gV29ybGQ= +## +## Apart from strings you can also encode lists of integers or characters: +## +## .. code-block::nim +## import base64 +## let encodedInts = encode([1,2,3]) +## echo(encodedInts) # AQID +## let encodedChars = encode(['h','e','y']) +## echo(encodedChars) # aGV5 +## +## The ``encode`` procedure takes an ``openarray`` so both arrays and sequences +## can be passed as parameters. +## +## Decoding data +## ------------- +## +## To decode a base64 encoded data string simply call the ``decode`` +## procedure: +## +## .. code-block::nim +## import base64 +## echo(decode("SGVsbG8gV29ybGQ=")) # Hello World -const +const cb64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" -template encodeInternal(s: expr, lineLen: int, newLine: string): stmt {.immediate.} = - ## encodes `s` into base64 representation. After `lineLen` characters, a +template encodeInternal(s: expr, lineLen: int, newLine: string): stmt {.immediate.} = + ## encodes `s` into base64 representation. After `lineLen` characters, a ## `newline` is added. var total = ((len(s) + 2) div 3) * 4 var numLines = (total + lineLen - 1) div lineLen @@ -29,13 +61,13 @@ template encodeInternal(s: expr, lineLen: int, newLine: string): stmt {.immediat var c = ord(s[i+2]) result[r] = cb64[a shr 2] result[r+1] = cb64[((a and 3) shl 4) or ((b and 0xF0) shr 4)] - result[r+2] = cb64[((b and 0x0F) shl 2) or ((c and 0xC0) shr 6)] - result[r+3] = cb64[c and 0x3F] + result[r+2] = cb64[((b and 0x0F) shl 2) or ((c and 0xC0) shr 6)] + result[r+3] = cb64[c and 0x3F] inc(r, 4) inc(i, 3) inc(currLine, 4) - if currLine >= lineLen and i != s.len-2: - for x in items(newLine): + if currLine >= lineLen and i != s.len-2: + for x in items(newLine): result[r] = x inc(r) currLine = 0 @@ -45,7 +77,7 @@ template encodeInternal(s: expr, lineLen: int, newLine: string): stmt {.immediat var b = ord(s[i+1]) result[r] = cb64[a shr 2] result[r+1] = cb64[((a and 3) shl 4) or ((b and 0xF0) shr 4)] - result[r+2] = cb64[((b and 0x0F) shl 2)] + result[r+2] = cb64[((b and 0x0F) shl 2)] result[r+3] = '=' if r+4 != result.len: setLen(result, r+4) @@ -61,17 +93,22 @@ template encodeInternal(s: expr, lineLen: int, newLine: string): stmt {.immediat #assert(r == result.len) discard -proc encode*[T:SomeInteger|char](s: openarray[T], lineLen = 75, newLine="\13\10"): string = - ## encodes `s` into base64 representation. After `lineLen` characters, a +proc encode*[T:SomeInteger|char](s: openarray[T], lineLen = 75, newLine="\13\10"): string = + ## encodes `s` into base64 representation. After `lineLen` characters, a ## `newline` is added. + ## + ## This procedure encodes an openarray (array or sequence) of either integers + ## or characters. encodeInternal(s, lineLen, newLine) - -proc encode*(s: string, lineLen = 75, newLine="\13\10"): string = - ## encodes `s` into base64 representation. After `lineLen` characters, a + +proc encode*(s: string, lineLen = 75, newLine="\13\10"): string = + ## encodes `s` into base64 representation. After `lineLen` characters, a ## `newline` is added. + ## + ## This procedure encodes a string. encodeInternal(s, lineLen, newLine) - -proc decodeByte(b: char): int {.inline.} = + +proc decodeByte(b: char): int {.inline.} = case b of '+': result = ord('>') of '0'..'9': result = ord(b) + 4 @@ -79,7 +116,7 @@ proc decodeByte(b: char): int {.inline.} = of 'a'..'z': result = ord(b) - 71 else: result = 63 -proc decode*(s: string): string = +proc decode*(s: string): string = ## decodes a string in base64 representation back into its original form. ## Whitespace is skipped. const Whitespace = {' ', '\t', '\v', '\r', '\l', '\f'} @@ -96,7 +133,7 @@ proc decode*(s: string): string = var b = s[i+1].decodeByte var c = s[i+2].decodeByte var d = s[i+3].decodeByte - + result[r] = chr((a shl 2) and 0xff or ((b shr 4) and 0x03)) result[r+1] = chr((b shl 4) and 0xff or ((c shr 2) and 0x0F)) result[r+2] = chr((c shl 6) and 0xff or (d and 0x3F)) @@ -105,19 +142,19 @@ proc decode*(s: string): string = else: break assert i == s.len # adjust the length: - if i > 0 and s[i-1] == '=': + if i > 0 and s[i-1] == '=': dec(r) if i > 1 and s[i-2] == '=': dec(r) setLen(result, r) - + when isMainModule: assert encode("leasure.") == "bGVhc3VyZS4=" assert encode("easure.") == "ZWFzdXJlLg==" assert encode("asure.") == "YXN1cmUu" assert encode("sure.") == "c3VyZS4=" - + const longText = """Man is distinguished, not only by his reason, but by this - singular passion from other animals, which is a lust of the mind, + singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure.""" |