diff --git a/lib/puppet/parser/functions/scanf.rb b/lib/puppet/parser/functions/scanf.rb index c9677c86b..8872ae2a0 100644 --- a/lib/puppet/parser/functions/scanf.rb +++ b/lib/puppet/parser/functions/scanf.rb @@ -1,35 +1,44 @@ +require 'scanf' + Puppet::Parser::Functions::newfunction( :scanf, :type => :rvalue, :arity => 2, :doc => <<-DOC Scans a string and returns an array of one or more converted values as directed by a given format string.args See the documenation of Ruby's String::scanf method for details about the supported formats (which are similar but not identical to the formats used in Puppet's `sprintf` function. -This function takes two mandatory arguments: the first is the String to convert, and the second -the format String. A parameterized block may optionally be given, which is called with the result -that is produced by scanf if no block is present, the result of the block is then returned by -the function. +This function takes two mandatory arguments: the first is the String to +convert, and the second the format String. The result of the scan is an Array, +with each sucessfully scanned and transformed value.args The scanning stops if +a scan is unsuccesful and the scanned result up to that point is returned. If +there was no succesful scan at all, the result is an empty Array. + + scanf("42", "%i")[0] == 42 + -The result of the scan is an Array, with each sucessfully scanned and transformed value.args The scanning -stops if a scan is unsuccesful and the scanned result up to that point is returned. If there was no -succesful scan at all, the result is an empty Array. The optional code block is typically used to -assert that the scan was succesful, and either produce the same input, or perform unwrapping of -the result +When used with the future parser, an optional parameterized block may be given. +The block is called with the result that is produced by scanf if no block is +present, the result of the block is then returned by the function. +The optional code block is typically used to assert that the scan was +succesful, and either produce the same input, or perform unwrapping of +the result: "42".scanf("%i") "42".scanf("%i") |$x| { unless $x[0] =~ Integer { fail "Expected a well formed integer value, got '$x[0]'" } $x[0] } -- since 3.7.4 -- note requires `parser = future` +- since 3.7.4 with `parser = future` +- since 3.7.5 with classic parser DOC ) do |args| - function_fail(["scanf() is only available when parser/evaluator future is in effect"]) + data = args[0] + format = args[1] + result = data.scanf(format) end diff --git a/spec/unit/parser/functions/scanf_spec.rb b/spec/unit/parser/functions/scanf_spec.rb new file mode 100755 index 000000000..45bb4a990 --- /dev/null +++ b/spec/unit/parser/functions/scanf_spec.rb @@ -0,0 +1,30 @@ +#! /usr/bin/env ruby +require 'spec_helper' + +describe "the scanf function" do + before :all do + Puppet::Parser::Functions.autoloader.loadall + end + + let(:node) { Puppet::Node.new('localhost') } + let(:compiler) { Puppet::Parser::Compiler.new(node) } + let(:scope) { Puppet::Parser::Scope.new(compiler) } + + it 'scans a value and returns an array' do + expect(scope.function_scanf(['42', '%i'])[0] == 42) + end + + it 'returns empty array if nothing was scanned' do + expect(scope.function_scanf(['no', '%i']) == []) + end + + it 'produces result up to first unsuccessful scan' do + expect(scope.function_scanf(['42 no', '%i'])[0] == 42) + end + + it 'errors when not given enough arguments' do + expect do + scope.function_scanf(['42']) + end.to raise_error(/.*scanf\(\): Wrong number of arguments given/m) + end +end