// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package ascii85 implements the ascii85 data encoding // as used in the btoa tool and Adobe's PostScript and PDF document formats.
package ascii85 import ( ) /* * Encoder */ // Encode encodes src into at most [MaxEncodedLen](len(src)) // bytes of dst, returning the actual number of bytes written. // // The encoding handles 4-byte chunks, using a special encoding // for the last fragment, so Encode is not appropriate for use on // individual blocks of a large data stream. Use [NewEncoder] instead. // // Often, ascii85-encoded data is wrapped in <~ and ~> symbols. // Encode does not add these. func (, []byte) int { if len() == 0 { return 0 } := 0 for len() > 0 { [0] = 0 [1] = 0 [2] = 0 [3] = 0 [4] = 0 // Unpack 4 bytes into uint32 to repack into base 85 5-byte. var uint32 switch len() { default: |= uint32([3]) fallthrough case 3: |= uint32([2]) << 8 fallthrough case 2: |= uint32([1]) << 16 fallthrough case 1: |= uint32([0]) << 24 } // Special case: zero (!!!!!) shortens to z. if == 0 && len() >= 4 { [0] = 'z' = [1:] = [4:] ++ continue } // Otherwise, 5 base 85 digits starting at !. for := 4; >= 0; -- { [] = '!' + byte(%85) /= 85 } // If src was short, discard the low destination bytes. := 5 if len() < 4 { -= 4 - len() = nil } else { = [4:] } = [:] += } return } // MaxEncodedLen returns the maximum length of an encoding of n source bytes. func ( int) int { return ( + 3) / 4 * 5 } // NewEncoder returns a new ascii85 stream encoder. Data written to // the returned writer will be encoded and then written to w. // Ascii85 encodings operate in 32-bit blocks; when finished // writing, the caller must Close the returned encoder to flush any // trailing partial block. func ( io.Writer) io.WriteCloser { return &encoder{w: } } type encoder struct { err error w io.Writer buf [4]byte // buffered data waiting to be encoded nbuf int // number of bytes in buf out [1024]byte // output buffer } func ( *encoder) ( []byte) ( int, error) { if .err != nil { return 0, .err } // Leading fringe. if .nbuf > 0 { var int for = 0; < len() && .nbuf < 4; ++ { .buf[.nbuf] = [] .nbuf++ } += = [:] if .nbuf < 4 { return } := Encode(.out[0:], .buf[0:]) if _, .err = .w.Write(.out[0:]); .err != nil { return , .err } .nbuf = 0 } // Large interior chunks. for len() >= 4 { := len(.out) / 5 * 4 if > len() { = len() } -= % 4 if > 0 { := Encode(.out[0:], [0:]) if _, .err = .w.Write(.out[0:]); .err != nil { return , .err } } += = [:] } // Trailing fringe. copy(.buf[:], ) .nbuf = len() += len() return } // Close flushes any pending output from the encoder. // It is an error to call Write after calling Close. func ( *encoder) () error { // If there's anything left in the buffer, flush it out if .err == nil && .nbuf > 0 { := Encode(.out[0:], .buf[0:.nbuf]) .nbuf = 0 _, .err = .w.Write(.out[0:]) } return .err } /* * Decoder */ type CorruptInputError int64 func ( CorruptInputError) () string { return "illegal ascii85 data at input byte " + strconv.FormatInt(int64(), 10) } // Decode decodes src into dst, returning both the number // of bytes written to dst and the number consumed from src. // If src contains invalid ascii85 data, Decode will return the // number of bytes successfully written and a [CorruptInputError]. // Decode ignores space and control characters in src. // Often, ascii85-encoded data is wrapped in <~ and ~> symbols. // Decode expects these to have been stripped by the caller. // // If flush is true, Decode assumes that src represents the // end of the input stream and processes it completely rather // than wait for the completion of another 32-bit block. // // [NewDecoder] wraps an [io.Reader] interface around Decode. func (, []byte, bool) (, int, error) { var uint32 var int for , := range { if len()- < 4 { return } switch { case <= ' ': continue case == 'z' && == 0: = 5 = 0 case '!' <= && <= 'u': = *85 + uint32(-'!') ++ default: return 0, 0, CorruptInputError() } if == 5 { = + 1 [] = byte( >> 24) [+1] = byte( >> 16) [+2] = byte( >> 8) [+3] = byte() += 4 = 0 = 0 } } if { = len() if > 0 { // The number of output bytes in the last fragment // is the number of leftover input bytes - 1: // the extra byte provides enough bits to cover // the inefficiency of the encoding for the block. if == 1 { return 0, 0, CorruptInputError(len()) } for := ; < 5; ++ { // The short encoding truncated the output value. // We have to assume the worst case values (digit 84) // in order to ensure that the top bits are correct. = *85 + 84 } for := 0; < -1; ++ { [] = byte( >> 24) <<= 8 ++ } } } return } // NewDecoder constructs a new ascii85 stream decoder. func ( io.Reader) io.Reader { return &decoder{r: } } type decoder struct { err error readErr error r io.Reader buf [1024]byte // leftover input nbuf int out []byte // leftover decoded output outbuf [1024]byte } func ( *decoder) ( []byte) ( int, error) { if len() == 0 { return 0, nil } if .err != nil { return 0, .err } for { // Copy leftover output from last decode. if len(.out) > 0 { = copy(, .out) .out = .out[:] return } // Decode leftover input from last read. var , , int if .nbuf > 0 { , , .err = Decode(.outbuf[0:], .buf[0:.nbuf], .readErr != nil) if > 0 { .out = .outbuf[0:] .nbuf = copy(.buf[0:], .buf[:.nbuf]) continue // copy out and return } if == 0 && .err == nil { // Special case: input buffer is mostly filled with non-data bytes. // Filter out such bytes to make room for more input. := 0 for := 0; < .nbuf; ++ { if .buf[] > ' ' { .buf[] = .buf[] ++ } } .nbuf = } } // Out of input, out of decoded output. Check errors. if .err != nil { return 0, .err } if .readErr != nil { .err = .readErr return 0, .err } // Read more data. , .readErr = .r.Read(.buf[.nbuf:]) .nbuf += } }