Project

General

Profile

Bug #4735 ยป 0001-Adding-documentation-to-scanf.rb.patch

gabemc (Gabe McArthur), 05/19/2011 09:06 AM

View differences:

lib/scanf.rb
# scanf for Ruby
#
# $Release Version: 1.1.2 $
# $Revision$
# $Id$
# $Author$
#
# A product of the Austin Ruby Codefest (Austin, Texas, August 2002)
=begin
scanf for Ruby
$Release Version: 1.1.2 $
$Revision$
$Id$
$Author$
=scanf for Ruby
A product of the Austin Ruby Codefest (Austin, Texas, August 2002)
==Description
=scanf for ruby
scanf for Ruby is an implementation of the C function scanf(3),
modified as necessary for Ruby compatibility.
==description
The methods provided are String#scanf, IO#scanf, and
Kernel#scanf. Kernel#scanf is a wrapper around STDIN.scanf. IO#scanf
can be used on any IO stream, including file handles and sockets.
scanf for ruby is an implementation of the c function scanf(3),
modified as necessary for ruby compatibility.
the methods provided are string#scanf, io#scanf, and
kernel#scanf. kernel#scanf is a wrapper around stdin.scanf. io#scanf
can be used on any io stream, including file handles and sockets.
scanf can be called either with or without a block.
scanf for Ruby scans an input string or stream according to a
<b>format</b>, as described below ("Conversions"), and returns an
array of matches between the format and the input. The format is
scanf for ruby scans an input string or stream according to a
<b>format</b>, as described below ("conversions"), and returns an
array of matches between the format and the input. the format is
defined in a string, and is similar (though not identical) to the
formats used in Kernel#printf and Kernel#sprintf.
formats used in kernel#printf and kernel#sprintf.
The format may contain <b>conversion specifiers</b>, which tell scanf
the format may contain <b>conversion specifiers</b>, which tell scanf
what form (type) each particular matched substring should be converted
to (e.g., decimal integer, floating point number, literal string,
etc.) The matches and conversions take place from left to right, and
etc.) the matches and conversions take place from left to right, and
the conversions themselves are returned as an array.
The format string may also contain characters other than those in the
conversion specifiers. White space (blanks, tabs, or newlines) in the
the format string may also contain characters other than those in the
conversion specifiers. white space (blanks, tabs, or newlines) in the
format string matches any amount of white space, including none, in
the input. Everything else matches only itself.
the input. everything else matches only itself.
Scanning stops, and scanf returns, when any input character fails to
scanning stops, and scanf returns, when any input character fails to
match the specifications in the format string, or when input is
exhausted, or when everything in the format string has been
matched. All matches found up to the stopping point are returned in
matched. all matches found up to the stopping point are returned in
the return array (or yielded to the block, if a block was given).
==Basic usage
==basic usage
require 'scanf.rb'
# String#scanf and IO#scanf take a single argument (a format string)
array = aString.scanf("%d%s")
array = anIO.scanf("%d%s")
# string#scanf and io#scanf take a single argument (a format string)
array = astring.scanf("%d%s")
array = anio.scanf("%d%s")
# Kernel#scanf reads from STDIN
# kernel#scanf reads from stdin
array = scanf("%d%s")
==Block usage
......
in using any of the more complex and/or arcane character class
idioms.
==License and copyright
Copyright:: (c) 2002-2003 David Alan Black
License:: Distributed on the same licensing terms as Ruby itself
==Warranty disclaimer
This software is provided "as is" and without any express or implied
warranties, including, without limitation, the implied warranties of
merchantibility and fitness for a particular purpose.
==Credits and acknowledgements
scanf for Ruby was developed as the major activity of the Austin
Ruby Codefest (Austin, Texas, August 2002).
Principal author:: David Alan Black (mailto:dblack@superlink.net)
Co-author:: Hal Fulton (mailto:hal9000@hypermetrics.com)
Project contributors:: Nolan Darilek, Jason Johnston
Thanks to Hal Fulton for hosting the Codefest.
Thanks to Matz for suggestions about the class design.
Thanks to Gavin Sinclair for some feedback on the documentation.
The text for parts of this document, especially the Description and
Conversions sections, above, were adapted from the Linux Programmer's
Manual manpage for scanf(3), dated 1995-11-01.
==Bugs and bug reports
scanf for Ruby is based on something of an amalgam of C scanf
implementations and documentation, rather than on a single canonical
description. Suggestions for features and behaviors which appear in
other scanfs, and would be meaningful in Ruby, are welcome, as are
reports of suspicious behaviors and/or bugs. (Please see "Credits and
acknowledgements", above, for email addresses.)
=end
#:stopdoc:
module Scanf
=begin
==Technical notes
===Rationale behind scanf for Ruby
......
when the FormatString object runs out of FormatSpecifiers, scanning
stops and results accumulated so far are returned in an array.
==License and copyright
Copyright:: (c) 2002-2003 David Alan Black
License:: Distributed on the same licensing terms as Ruby itself
==Warranty disclaimer
This software is provided "as is" and without any express or implied
warranties, including, without limitation, the implied warranties of
merchantibility and fitness for a particular purpose.
==Credits and acknowledgements
scanf for Ruby was developed as the major activity of the Austin
Ruby Codefest (Austin, Texas, August 2002).
Principal author:: David Alan Black (mailto:dblack@superlink.net)
Co-author:: Hal Fulton (mailto:hal9000@hypermetrics.com)
Project contributors:: Nolan Darilek, Jason Johnston
Thanks to Hal Fulton for hosting the Codefest.
Thanks to Matz for suggestions about the class design.
Thanks to Gavin Sinclair for some feedback on the documentation.
The text for parts of this document, especially the Description and
Conversions sections, above, were adapted from the Linux Programmer's
Manual manpage for scanf(3), dated 1995-11-01.
==Bugs and bug reports
scanf for Ruby is based on something of an amalgam of C scanf
implementations and documentation, rather than on a single canonical
description. Suggestions for features and behaviors which appear in
other scanfs, and would be meaningful in Ruby, are welcome, as are
reports of suspicious behaviors and/or bugs. (Please see "Credits and
acknowledgements", above, for email addresses.)
=end
module Scanf
class FormatSpecifier
attr_reader :re_string, :matched_string, :conversion, :matched
......
end
end
end
#:startdoc:
# When required, +scanf.rb+ adds the +scanf+ method to the +IO+
# class, for reading formatted strings from streams.
class IO
# The trick here is doing a match where you grab one *line*
# of input at a time. The linebreak may or may not occur
# at the boundary where the string matches a format specifier.
# And if it does, some rule about whitespace may or may not
# be in effect...
#
# That's why this is much more elaborate than the string
# version.
#
# For each line:
# Match succeeds (non-emptily)
# and the last attempted spec/string sub-match succeeded:
#
# could the last spec keep matching?
# yes: save interim results and continue (next line)
#
# The last attempted spec/string did not match:
#
# are we on the next-to-last spec in the string?
# yes:
# is fmt_string.string_left all spaces?
# yes: does current spec care about input space?
# yes: fatal failure
# no: save interim results and continue
# no: continue [this state could be analyzed further]
#
#
def scanf(str,&b)
#:stopdoc:
# The trick here is doing a match where you grab one *line*
# of input at a time. The linebreak may or may not occur
# at the boundary where the string matches a format specifier.
# And if it does, some rule about whitespace may or may not
# be in effect...
#
# That's why this is much more elaborate than the string
# version.
#
# For each line:
# Match succeeds (non-emptily)
# and the last attempted spec/string sub-match succeeded:
#
# could the last spec keep matching?
# yes: save interim results and continue (next line)
#
# The last attempted spec/string did not match:
#
# are we on the next-to-last spec in the string?
# yes:
# is fmt_string.string_left all spaces?
# yes: does current spec care about input space?
# yes: fatal failure
# no: save interim results and continue
# no: continue [this state could be analyzed further]
#
#:startdoc:
# Scans the current string until the match is exhausted,
# yielding each match as it is encountered in the string.
# A block is not necessary though, as the results will simply
# be aggregated into the final array.
#
# "123 456".block_scanf("%d")
# # => [123, 456]
#
# If a block is given, the value from that is returned from
# the yield is added to an output array.
#
# "123 456".block_scanf("%d) do |digit,| # Requires a ',' to unpack the Array
# digit + 100
# end
# # => [223, 556]
#
def scanf(str,&b) #:yield: +current_match+
return block_scanf(str,&b) if b
return [] unless str.size > 0
......
end
end
# String has two convenience methods for scanning the contents
# of a string object into an +Array+. The first is the standard
# +scanf+ function; the second is the +block_scanf+, which
# yields a match to the given block, accumulating the output.
#
# Note that the String#scanf method will perform in the exact
# same way as String#block_scanf if passed a block.
#
class String
def scanf(fstr,&b)
# Scans the current string. If a block is given, it
# functions exactly like +block_scanf+.
#
# arr = "123 456".scanf("%d%d")
# # => [123, 456]
#
# require 'pp'
#
# "this 123 read that 456 other".scanf("%s%d%s") {|m| pp m}
#
# # ["this", 123, "read"]
# # ["that", 456, "other"]
# # => [["this", 123, "read"], ["that", 456, "other"]]
#
def scanf(fstr,&b) #:yield: +current_match+ if block_given?
if b
block_scanf(fstr,&b)
else
......
end
end
def block_scanf(fstr,&b)
# Scans the current string until the match is exhausted,
# yielding each match as it is encountered in the string.
# A block is not necessary though, as the results will simply
# be aggregated into the final array.
#
# "123 456".block_scanf("%d")
# # => [123, 456]
#
# If a block is given, the value from that is returned from
# the yield is added to an output array.
#
# "123 456".block_scanf("%d) do |digit,| # Requires a ',' to unpack the Array
# digit + 100
# end
# # => [223, 556]
#
def block_scanf(fstr,&b) #:yield: +current_match+
fs = Scanf::FormatString.new(fstr)
str = self.dup
final = []
......
end
end
module Kernel
# The Kernel#scanf method is private by default, but because +Kernel+
# is mixed in the +Object+ inheritance heirarchy, it is thus
# available everywhere.
#
# It reads from +STDIN+.
#
module Kernel
private
def scanf(fs,&b)
# Queries +STDIN+ for input.
def scanf(fs,&b) #:doc:
STDIN.scanf(fs,&b)
end
end
    (1-1/1)