From 09f9bafa52aeea992b6c9557a05ed85789b52148 Mon Sep 17 00:00:00 2001 From: Gabe McArthur Date: Tue, 17 May 2011 21:01:02 -0700 Subject: [PATCH] Adding documentation to scanf.rb --- lib/scanf.rb | 281 ++++++++++++++++++++++++++++++++++++---------------------- 1 files changed, 175 insertions(+), 106 deletions(-) diff --git a/lib/scanf.rb b/lib/scanf.rb index 50eefbc..34d4987 100644 --- a/lib/scanf.rb +++ b/lib/scanf.rb @@ -1,59 +1,58 @@ -# 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 -format, 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 +format, 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 conversion specifiers, which tell scanf +the format may contain conversion specifiers, 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 @@ -211,7 +210,53 @@ has not been exhaustive, and that they should exercise some caution 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 @@ -258,49 +303,8 @@ As soon as a regular expression fragment fails to match the string, or 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 @@ -575,38 +579,58 @@ module Scanf 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 @@ -684,9 +708,31 @@ class IO 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 @@ -700,7 +746,23 @@ class String 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 = [] @@ -713,9 +775,16 @@ class String 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.7.3.4