14
14
#
15
15
module Ascii85
16
16
class << self
17
+ EMPTY_STRING = '' . dup . force_encoding ( Encoding ::ASCII_8BIT )
18
+ START_MARKER = '<~' . dup . force_encoding ( Encoding ::ASCII_8BIT )
19
+ ENDING_MARKER = '~>' . dup . force_encoding ( Encoding ::ASCII_8BIT )
20
+ LINE_BREAK = "\n " . dup . force_encoding ( Encoding ::ASCII_8BIT )
21
+
17
22
#
18
23
# Encodes the bytes of the given String or IO-like object as Ascii85.
19
24
#
@@ -55,20 +60,17 @@ def encode(str_or_io, wrap_lines = 80, out: nil)
55
60
StringIO . new ( str_or_io . to_s , 'rb' )
56
61
end
57
62
58
- return '' . dup if reader . eof?
63
+ return EMPTY_STRING . dup if reader . eof?
59
64
60
65
# Setup buffered Reader and Writers
61
66
bufreader = BufferedReader . new ( reader , unencoded_chunk_size )
62
67
bufwriter = BufferedWriter . new ( out || StringIO . new ( String . new , 'wb' ) , encoded_chunk_size )
63
68
writer = wrap_lines ? Wrapper . new ( bufwriter , wrap_lines ) : DummyWrapper . new ( bufwriter )
64
69
65
- # We need to enforce the encoding here, because this source file is in UTF-8,
66
- # but we want ASCII-8BIT output.
67
- padding = "\0 \0 \0 \0 " . dup . force_encoding ( Encoding ::ASCII_8BIT )
68
- tuplebuf = '!!!!!' . dup . force_encoding ( Encoding ::ASCII_8BIT )
69
-
70
- exclamations = '!!!!!' . dup . force_encoding ( Encoding ::ASCII_8BIT )
71
- z = 'z' . dup . force_encoding ( Encoding ::ASCII_8BIT )
70
+ padding = unfrozen_binary_copy ( "\0 \0 \0 \0 " )
71
+ tuplebuf = unfrozen_binary_copy ( '!!!!!' )
72
+ exclamations = unfrozen_binary_copy ( '!!!!!' )
73
+ z = unfrozen_binary_copy ( 'z' )
72
74
73
75
bufreader . each_chunk do |chunk |
74
76
chunk . unpack ( 'N*' ) . each do |word |
@@ -156,8 +158,8 @@ def extract(str)
156
158
157
159
# Get the positions of the opening/closing delimiters. If there is no pair
158
160
# of opening/closing delimiters, return an unfrozen empty String.
159
- ( start_pos = input . index ( opening_delim ) ) or return '' . dup
160
- ( end_pos = input . index ( closing_delim , start_pos + 2 ) ) or return '' . dup
161
+ ( start_pos = input . index ( opening_delim ) ) or return EMPTY_STRING . dup
162
+ ( end_pos = input . index ( closing_delim , start_pos + 2 ) ) or return EMPTY_STRING . dup
161
163
162
164
# Get the String inside the delimiter-pair
163
165
input [ ( start_pos + 2 ) ...end_pos ]
@@ -231,7 +233,7 @@ def decode_raw(str_or_io, out: nil)
231
233
end
232
234
233
235
# Return an unfrozen String on empty input
234
- return '' . dup if reader . eof?
236
+ return EMPTY_STRING . dup if reader . eof?
235
237
236
238
# Setup buffered Reader and Writers
237
239
bufreader = BufferedReader . new ( reader , encoded_chunk_size )
@@ -243,8 +245,8 @@ def decode_raw(str_or_io, out: nil)
243
245
# Decode
244
246
word = 0
245
247
count = 0
246
- wordbuf = "\0 \0 \0 \0 " . dup . force_encoding ( Encoding :: ASCII_8BIT )
247
- zeroes = " \0 \0 \0 \0 " . dup . force_encoding ( Encoding :: ASCII_8BIT )
248
+ zeroes = unfrozen_binary_copy ( "\0 \0 \0 \0 " )
249
+ wordbuf = zeroes . dup
248
250
249
251
bufreader . each_chunk do |chunk |
250
252
chunk . each_byte do |c |
@@ -311,6 +313,12 @@ def decode_raw(str_or_io, out: nil)
311
313
312
314
private
313
315
316
+ # Copies the given String and forces the encoding of the returned copy to
317
+ # be Encoding::ASCII_8BIT.
318
+ def unfrozen_binary_copy ( str )
319
+ str . dup . force_encoding ( Encoding ::ASCII_8BIT )
320
+ end
321
+
314
322
# Buffers an underlying IO object to increase efficiency. You do not need
315
323
# to use this directly.
316
324
#
@@ -364,20 +372,17 @@ def flush
364
372
# @private
365
373
#
366
374
class DummyWrapper
367
- START = '<~' . dup . force_encoding ( Encoding ::ASCII_8BIT )
368
- ENDING = '~>' . dup . force_encoding ( Encoding ::ASCII_8BIT )
369
-
370
375
def initialize ( out )
371
376
@out = out
372
- @out . write ( START )
377
+ @out . write ( START_MARKER )
373
378
end
374
379
375
380
def write ( buffer )
376
381
@out . write ( buffer )
377
382
end
378
383
379
384
def finish
380
- @out . write ( ENDING )
385
+ @out . write ( ENDING_MARKER )
381
386
@out . flush
382
387
383
388
@out
@@ -390,15 +395,11 @@ def finish
390
395
# @private
391
396
#
392
397
class Wrapper
393
- LINE_BREAK = 10 . chr . force_encoding ( Encoding ::ASCII_8BIT )
394
- START = '<~' . dup . force_encoding ( Encoding ::ASCII_8BIT )
395
- ENDING = '~>' . dup . force_encoding ( Encoding ::ASCII_8BIT )
396
-
397
398
def initialize ( out , wrap_lines )
398
399
@line_length = [ 2 , wrap_lines . to_i ] . max
399
400
400
401
@out = out
401
- @out . write ( START )
402
+ @out . write ( START_MARKER )
402
403
403
404
@cur_len = 2
404
405
end
@@ -425,7 +426,7 @@ def write(buffer)
425
426
def finish
426
427
# Add the closing delimiter (may need to be pushed to the next line)
427
428
@out . write ( LINE_BREAK ) if @cur_len + 2 > @line_length
428
- @out . write ( ENDING )
429
+ @out . write ( ENDING_MARKER )
429
430
430
431
@out . flush
431
432
@out
0 commit comments