Module: ScrubRb

Defined in:
lib/scrub_rb.rb,
lib/scrub_rb/version.rb

Constant Summary collapse

VERSION =
"1.0.1"

Class Method Summary collapse

Class Method Details

.scrub(str, replacement = nil, &block) ⇒ Object

static function implementation of String#scrub, where first arg is the string.

ScrubRb.scrub("abc\u3042\x81") #=> "abc\u3042\uFFFD"
ScrubRb.scrub("abc\u3042\x81", "*") #=> "abc\u3042*"
ScrubRb.scrub("abc\u3042\xE3\x80") {|bytes| '<'+bytes.unpack('H*')[0]+'>' } #=> "abc\u3042<e380>"


12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/scrub_rb.rb', line 12

def self.scrub(str, replacement=nil, &block)
  return str if str.nil?

  if replacement.nil? && ! block_given?
    replacement =
       # UTF-8 for unicode replacement char \uFFFD, encode in
       # encoding of input string, using '?' as a fallback where
       # it can't be (which should be non-unicode encodings)
       "\xEF\xBF\xBD".force_encoding("UTF-8").encode( str.encoding,
                                                :undef => :replace,
                                                :replace => '?' )  
  end

  result          = "".force_encoding("BINARY")
  bad_chars       = "".force_encoding("BINARY")
  bad_char_flag   = false # weirdly, optimization to use flag

  str.chars.each do |c|
    if c.valid_encoding?
      if bad_char_flag
        scrub_replace(result, bad_chars, replacement, block)
        bad_char_flag = false
      end
      result << c
    else
      bad_char_flag = true
      bad_chars << c
    end
  end
  if bad_char_flag
    scrub_replace(result, bad_chars, replacement, block)
  end

  result.force_encoding(str.encoding)

  return result
end