# Scanf::FormatSpecifier (Class)

In: | scanf.rb
Parent: | Object

## Methods

count_space? letter match mid_match? new to_re to_s width

## Attributes

conversion | [R] |
matched | [R] |
matched_string | [R] |
re_string | [R] |

## Classes and Modules

Class Scanf::FormatSpecifier::FormatString

## Public Class methods

new(str)

[Source]

    # File scanf.rb, line 332
        def initialize(str)
          @spec_string = str

          h = '[A-Fa-f0-9]'

          @re_string, @handler =
            case @spec_string

              # %[[:...:]]

            when /%\*?(\[\[:[a-z]+:\]\])/
              [ "(#{$1}+)", :extract_plain ]

              # %5[[:...:]]

            when /%\*?(\d+)(\[\[:[a-z]+:\]\])/
              [ "(#{$2}{1,#{$1}})", :extract_plain ]

              # %[...]

            when /%\*?\[([^\]]*)\]/
              yes = $1
              if /^\^^/.match(yes) then no = yes[1..-1] else no = '^' + yes end
              [ "([#{yes}]+)(?=[#{no}]|\\z)", :extract_plain ]

              # %5[...]
            when /%\*?(\d+)\[([^\]]*)\]/
              yes = $2
              w = $1
              [ "([#{yes}]{1,#{w}})", :extract_plain ]

              # %i

            when /%\*?i/
              [ "([-+]?(?:(?:0[0-7]+)|(?:0[Xx]#{h}+)|(?:[1-9]\\d+)))", :extract_integer ]

              # %5i

            when /%\*?(\d+)i/
              n = $1.to_i
              s = "("
              if n > 1 then s += "[1-9]\\d{1,#{n-1}}|" end
              if n > 1 then s += "0[0-7]{1,#{n-1}}|" end
              if n > 2 then s += "[-+]0[0-7]{1,#{n-2}}|" end
              if n > 2 then s += "[-+][1-9]\\d{1,#{n-2}}|" end
              if n > 2 then s += "0[Xx]#{h}{1,#{n-2}}|" end
              if n > 3 then s += "[-+]0[Xx]#{h}{1,#{n-3}}|" end
              s += "\\d"
              s += ")"
              [ s, :extract_integer ]

              # %d, %u

            when /%\*?[du]/
              [ '([-+]?\d+)', :extract_decimal ]

              # %5d, %5u

            when /%\*?(\d+)[du]/
              n = $1.to_i
              s = "("
              if n > 1 then s += "[-+]\\d{1,#{n-1}}|" end
              s += "\\d{1,#{$1}})"
              [ s, :extract_decimal ]

              # %x

            when /%\*?[Xx]/
              [ "([-+]?(?:0[Xx])?#{h}+)", :extract_hex ]

              # %5x

            when /%\*?(\d+)[Xx]/
              n = $1.to_i
              s = "("
              if n > 3 then s += "[-+]0[Xx]#{h}{1,#{n-3}}|" end
              if n > 2 then s += "0[Xx]#{h}{1,#{n-2}}|" end
              if n > 1 then s += "[-+]#{h}{1,#{n-1}}|" end
              s += "#{h}{1,#{n}}"
              s += ")"
              [ s, :extract_hex ]

              # %o

            when /%\*?o/
              [ '([-+]?[0-7]+)', :extract_octal ]

              # %5o

            when /%\*?(\d+)o/
              [ "([-+][0-7]{1,#{$1.to_i-1}}|[0-7]{1,#{$1}})", :extract_octal ]

              # %f

            when /%\*?f/
              [ '([-+]?((\d+(?>(?=[^\d.]|$)))|(\d*(\.(\d*([eE][-+]?\d+)?)))))', :extract_float ]

              # %5f

            when /%\*?(\d+)f/
              [ "(\\S{1,#{$1}})", :extract_float ]

              # %5s

            when /%\*?(\d+)s/
              [ "(\\S{1,#{$1}})", :extract_plain ]

              # %s

            when /%\*?s/
              [ '(\S+)', :extract_plain ]

              # %c

            when /\s%\*?c/
              [ "\\s*(.)", :extract_plain ]

              # %c

            when /%\*?c/
              [ "(.)", :extract_plain ]

              # %5c (whitespace issues are handled by the count_*_space? methods)

            when /%\*?(\d+)c/
              [ "(.{1,#{$1}})", :extract_plain ]

              # %%

            when /%%/
              [ '(\s*%)', :nil_proc ]

              # literal characters

            else
              [ "(#{Regexp.escape(@spec_string)})", :nil_proc ]
            end

          @re_string = '\A' + @re_string
        end

        def to_re
          Regexp.new(@re_string,Regexp::MULTILINE)
        end

        def match(str)
          @matched = false
          s = str.dup
          s.sub!(/\A\s+/,'') unless count_space?
          res = to_re.match(s)
          if res
            @conversion = send(@handler, res[1])
            @matched_string = @conversion.to_s
            @matched = true
          end
          res
        end

        def letter
          /%\*?\d*([a-z\[])/.match(@spec_string).to_a[1]
        end

        def width
          w = /%\*?(\d+)/.match(@spec_string).to_a[1]
          w && w.to_i
        end

        def mid_match?
          return false unless @matched
          cc_no_width    = letter == '[' &&! width
          c_or_cc_width  = (letter == 'c' || letter == '[') && width
          width_left     = c_or_cc_width && (matched_string.size < width)

          return width_left || cc_no_width
        end

      end

## Public Instance methods

to_s()

[Source]

    # File scanf.rb, line 324
        def to_s
          @spec_string
        end

count_space?()

[Source]

    # File scanf.rb, line 328
        def count_space?
          /(?:\A|\S)%\*?\d*c|\[/.match(@spec_string)
        end

to_re()

[Source]

    # File scanf.rb, line 453
        def to_re
          Regexp.new(@re_string,Regexp::MULTILINE)
        end

match(str)

[Source]

    # File scanf.rb, line 457
        def match(str)
          @matched = false
          s = str.dup
          s.sub!(/\A\s+/,'') unless count_space?
          res = to_re.match(s)
          if res
            @conversion = send(@handler, res[1])
            @matched_string = @conversion.to_s
            @matched = true
          end
          res
        end

letter()

[Source]

    # File scanf.rb, line 470
        def letter
          /%\*?\d*([a-z\[])/.match(@spec_string).to_a[1]
        end

width()

[Source]

    # File scanf.rb, line 474
        def width
          w = /%\*?(\d+)/.match(@spec_string).to_a[1]
          w && w.to_i
        end

mid_match?()

[Source]

    # File scanf.rb, line 479
        def mid_match?
          return false unless @matched
          cc_no_width    = letter == '[' &&! width
          c_or_cc_width  = (letter == 'c' || letter == '[') && width
          width_left     = c_or_cc_width && (matched_string.size < width)

          return width_left || cc_no_width
        end

[Validate]