module GxG::Support::Library::Transcoding

Public Instance Methods

convert_to_string(the_object=nil,encoding=::Encoding.default_external,conversion_options={}) click to toggle source
# File lib/gxg/gxg_transcode.rb, line 214
def convert_to_string(the_object=nil,encoding=::Encoding.default_external,conversion_options={})
  # return the supplied string, or supported object string data, or UTF_8 codepoint, un-transcoded
  # encoding is used for when a byte value integer is passed to know what encoding to set.
  the_string = ""
  the_string.force_encoding(encoding || ::Encoding.default_external)
  if the_object
    if the_object.is_a?(::Array)
      dataset = the_object.flatten
    else
      dataset = [(the_object)]
    end
    dataset.to_enum(:each).each do |object|
      buffer = ""
      if object.is_a?(::String)
        # find the string content of these classes and pass them for transcoding: Numeric, String, ::IO via gets, ::StringIO via gets, ::GxG::ByteArray
        buffer = object.dup
      else
        if object.is_any?(::IO, ::StringIO)
          # Note: what issues arise when the_object is in binary mode?  Also, how does this scale to very large things or files?
          buffer = object.gets().to_s
        end
        if object.is_any?(::GxG::ByteArray)
          buffer = object.to_s
        end
        if object.is_a?(::Numeric)
          if object.to_i >= 0
            data = ""
            if (0xFFFFFFFF && object.to_i) > 255
              # interprets as unicode code point
              data.force_encoding(::Encoding::UTF_8)
            else
              # interprets as a char value in its own encoding, no transcoding needed.
              data.force_encoding(encoding || ::Encoding.default_external)
            end
            buffer = (data << object.to_i)
            data = nil
          else
            # signed integers not supported for char values or codepoints at this time.
          end
        end
      end
      #
      if buffer.size > 0
        if (buffer.encoding == (encoding || ::Encoding.default_external) && ! self.binmode?())
          the_string << buffer
        else
          # ::String::transcode_options((encoding || ::Encoding.default_external),buffer.encoding, (conversion_options || {}))
          if self.binmode?()
            buffer.to_enum(:chars).each do |the_char|
              the_char.to_enum(:bytes).each do |the_byte|
                the_string << the_byte
              end
            end
          else
            nl_op = self.newline_option_used(conversion_options)
            options = {}
            if nl_op
              options[(nl_op)] = true
            end
            #
            the_string << buffer.transcode!((encoding || ::Encoding.default_external),options)
          end
        end
      end
      #
    end
  end
  #
  the_string
end
field_separator_used(io_channel=:external) click to toggle source
# File lib/gxg/gxg_transcode.rb, line 162
def field_separator_used(io_channel=:external)
  unless self.instance_variable_defined?(:@internal_encoding)
    @internal_encoding = nil
  end
  unless self.instance_variable_defined?(:@internal_field_separator)
    @internal_field_separator = nil
  end
  unless self.instance_variable_defined?(:@external_field_separator)
    @external_field_separator = nil
  end
  field_separator = ""
  if io_channel == :internal
    field_separator.force_encoding((@internal_encoding || self.external_encoding))
    field_separator << (@internal_field_separator || ($,).to_s)
  else
    io_channel = :external
    field_separator.force_encoding(self.external_encoding)
    field_separator << (@external_field_separator || ($,).to_s)
  end
  if field_separator.size > 0
    field_separator
  else
    nil
  end
end
newline_option_used(io_channel=:external) click to toggle source
# File lib/gxg/gxg_transcode.rb, line 103
def newline_option_used(io_channel=:external)
  unless self.instance_variable_defined?(:@conversion_options)
    @conversion_options = {:internal => {}, :external => {}}
  end
  # determine the correct new_line trancoding option used
  if io_channel.is_a?(::Hash)
    options = io_channel
  else
    options = (@conversion_options[(io_channel.to_sym)] || {})
  end
  if options[:cr_newline]
    :cr_newline
  else
    if options[:crlf_newline]
      :crlf_newline
    else
      if options[:universal_newline]
        :universal_newline
      else
        # use nil if none specified
        nil
      end
    end
  end
  #
end
newline_used(io_channel=:external) click to toggle source
# File lib/gxg/gxg_transcode.rb, line 130
def newline_used(io_channel=:external)
  unless self.instance_variable_defined?(:@conversion_options)
    @conversion_options = {:internal => {}, :external => {}}
  end
  unless self.instance_variable_defined?(:@internal_encoding)
    @internal_encoding = nil
  end
  newline = ""
  if io_channel == :internal
    newline.force_encoding((@internal_encoding || self.external_encoding))
  else
    io_channel = :external
    newline.force_encoding(self.external_encoding)
  end
  # determine the correct new_line_separator
  if @conversion_options[(io_channel)][:cr_newline]
    newline << "\r"
  else
    if @conversion_options[(io_channel)][:crlf_newline]
      newline << "\r\n"
    else
      if @conversion_options[(io_channel)][:universal_newline]
        newline << "\n"
      else
        # use global default if none specified
        newline << $/
      end
    end
  end
  newline
end
prepare_conversion_options(options={}) click to toggle source

Instance Methods

# File lib/gxg/gxg_transcode.rb, line 8
def prepare_conversion_options(options={})
  # obsoleted by ::String::transcode_options
  unless options.is_a?(::Hash)
    raise ArgumentError, "You must pass conversion options parameter as a Hash"
  end
  #
  new_options = {}
  #
  valid_options = [:invalid,:undef,:replace,:fallback,:xml,:cr_newline,:crlf_newline,:universal_newline]
  #
  for the_option_key in valid_options
    #
    if options[(the_option_key)]
      # Note Source: http://ruby-doc.org/core-1.9.3/String.html#method-i-encode
      if the_option_key == :fallback
        #    Sets the replacement string by the given object for undefined character. The object should be a Hash, a Proc, a Method,
        #    or an object which has [] method. Its key is an undefined character encoded in the source encoding of current transcoder.
        #    Its value can be any encoding until it can be converted into the destination encoding of the transcoder.
        unless new_options[:replace]
          if (options[:fallback].is_any?(::Hash, ::Struct, ::Proc, ::Method) || options[:fallback].respond_to?(:[]))
            # if :fallback will not process an Array as mentioned above ... remove :[] respond_to? condition.
            new_options[:fallback] = options[:fallback]
          end
        end
      end
      #
      if the_option_key == :invalid
        #    If the value is :replace, encode replaces invalid byte sequences in str with the replacement character. The default is to
        #    raise the Encoding::InvalidByteSequenceError exception
        unless new_options[:fallback]
          if options[:invalid] == :replace
            new_options[:invalid] = :replace
          end
        end
      end
      #
      if (the_option_key == :undef)
        #    If the value is :replace, encode replaces characters which are undefined in the destination encoding with the replacement character.
        #    The default is to raise the Encoding::UndefinedConversionError.
        unless new_options[:fallback]
          if options[:undef] == :replace
            new_options[:undef] = :replace
          end
        end
      end
      if (the_option_key == :replace)
        #    Sets the replacement string to the given value. The default replacement string is “uFFFD” for Unicode encoding forms, and “?” otherwise.
        unless new_options[:fallback]
          if options[:replace].is_a?(::String)
            new_options[:replace] = options[:replace]
          end
        end
      end
      if the_option_key == :xml
        #    The value must be :text or :attr. If the value is :text encode replaces undefined characters with their (upper-case hexadecimal) numeric character
        #    references. ‘&’, ‘<’, and ‘>’ are converted to “&amp;”, “&lt;”, and “&gt;”, respectively. If the value is :attr, encode also quotes the replacement
        #    result (using ‘“’), and replaces ‘”’ with “&quot;”.
        if [:text, :attr].include?(options[:xml])
          new_options[:xml] = options[:xml]
        end
      end
      if the_option_key == :cr_newline
        #    Replaces LF (“n”) with CR (“r”) if value is true.
        unless (new_options[:crlf_newline] || new_options[:universal_newline])
          if options[(the_option_key)] == true
            new_options[(the_option_key)] = true
          end
        end
      end
      #
      if the_option_key == :crlf_newline
        #    Replaces LF (“n”) with CRLF (“rn”) if value is true.
        unless (new_options[:cr_newline] || new_options[:universal_newline])
          if options[(the_option_key)] == true
            new_options[(the_option_key)] = true
          end
        end
      end
      #
      if the_option_key == :universal_newline
        #    Replaces CRLF (“rn”) and CR (“r”) with LF (“n”) if value is true.
        unless (new_options[:cr_newline] || new_options[:crlf_newline])
          if options[(the_option_key)] == true
            new_options[(the_option_key)] = true
          end
        end
      end
      #
    end
    #
    pause
  end
  new_options
end
record_separator_used(io_channel=:external) click to toggle source
# File lib/gxg/gxg_transcode.rb, line 188
def record_separator_used(io_channel=:external)
  unless self.instance_variable_defined?(:@internal_encoding)
    @internal_encoding = nil
  end
  unless self.instance_variable_defined?(:@internal_record_separator)
    @internal_record_separator = nil
  end
  unless self.instance_variable_defined?(:@external_record_separator)
    @external_record_separator = nil
  end
  record_separator = ""
  if io_channel == :internal
    record_separator.force_encoding((@internal_encoding || self.external_encoding))
    record_separator << (@internal_record_separator || ($\).to_s)
  else
    io_channel = :external
    record_separator.force_encoding(self.external_encoding)
    record_separator << (@external_record_separator || ($\).to_s)
  end
  if record_separator.size > 0
    record_separator
  else
    nil
  end
end
transcode_to_external(the_string="") click to toggle source

TODO: GxG::StringIO : transcoding methods : tie into conversion-options-set-selector supports (dst-encoding,src-encoding). Hash deep-merge method needed.

# File lib/gxg/gxg_transcode.rb, line 287
def transcode_to_external(the_string="")
  # return the supplied string, or supported object string data, or UTF_8 codepoint, transcoded
  unless self.instance_variable_defined?(:@conversion_options)
    @conversion_options = {:internal => {}, :external => {}}
  end
  unless self.instance_variable_defined?(:@internal_encoding)
    @internal_encoding = nil
  end
  #
  unless the_string.is_a?(::String)
    # External conversion options will have to be dynamically generated upon transcode_to_external as *any* encoding is possible, not just internal_encoding
    the_string = self.convert_to_string(the_string,self.external_encoding,@conversion_options[:external])
  end
  if the_string.size > 0
    if self.binmode?()
      the_string.force_encoding(::Encoding::ASCII_8BIT)
    else
      if (the_string.encoding != self.external_encoding)
        if the_string.encoding == @internal_encoding
          options = ::String::transcode_options(self.external_encoding,the_string.encoding,@conversion_options[:external])
        else
          # External conversion options will have to be dynamically generated upon transcode_to_external as *any* encoding is possible, not just internal_encoding
          nl_op = self.newline_option_used(:external)
          options = {}
          if nl_op
            options[(nl_op)] = true
          end
          options = ::String::transcode_options(self.external_encoding,the_string.encoding,options)
        end
        the_string.transcode!(self.external_encoding,options)
      end
    end
  end
  #
  the_string
end
transcode_to_internal(the_string="") click to toggle source
# File lib/gxg/gxg_transcode.rb, line 324
def transcode_to_internal(the_string="")
  # return the supplied string, or supported object string data, or UTF_8 codepoint, transcoded
  unless self.instance_variable_defined?(:@conversion_options)
    @conversion_options = {:internal => {}, :external => {}}
  end
  unless self.instance_variable_defined?(:@internal_encoding)
    @internal_encoding = nil
  end
  #
  if (@internal_encoding && ! self.binmode?())
    unless the_string.is_a?(::String)
      the_string = self.convert_to_string(the_string,@internal_encoding,@conversion_options[:internal])
    end
    if the_string.size > 0
      if @internal_encoding == ::Encoding::ASCII_8BIT
        # for cases where the external encoding is anything but binary, but the internal is set to BINARY.
        # instead of actually transcoding something char by char into binary - just sets the encoding and filters for newline settings.
        #
        the_string.force_encoding(::Encoding::ASCII_8BIT)
        nl_op = self.newline_option_used(:internal)
        options = {}
        if nl_op
          options[(nl_op)] = true
        end
        the_string = the_string.encode(::Encoding::ASCII_8BIT,::Encoding::ASCII_8BIT,options)
      else
        if (the_string.encoding != @internal_encoding)
          if the_string.encoding == self.external_encoding
            options = ::String::transcode_options(@internal_encoding,the_string.encoding,@conversion_options[:internal])
          else
            nl_op = self.newline_option_used(:internal)
            options = {}
            if nl_op
              options[(nl_op)] = true
            end
            options = ::String::transcode_options(@internal_encoding,the_string.encoding,options)
          end
          the_string.transcode!(@internal_encoding,options)
        end
      end
    end
  else
    the_string = self.transcode_to_external(the_string)
  end
  #
  the_string
end