Class: Puppet::Provider::MysqlLoginPath::IniFile::Parser

Inherits:
Object
  • Object
show all
Defined in:
lib/puppet/provider/mysql_login_path/inifile.rb

Overview

The IniFile::Parser has the responsibility of reading the contents of an .ini file and storing that information into a ruby Hash. The object being parsed must respond to ‘each_line` - this includes Strings and any IO object.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(hash, param, comment, default) ⇒ Parser

Create a new IniFile::Parser that can be used to parse the contents of an .ini file.

hash - The Hash where parsed information will be stored param - String used to separate parameter and value comment - String containing the comment character(s) default - The String name of the default global section



428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
# File 'lib/puppet/provider/mysql_login_path/inifile.rb', line 428

def initialize(hash, param, comment, default)
  @hash = hash
  @default = default

  comment = comment.to_s.empty? ? '\\z' : "\\s*(?:[#{comment}].*)?\\z"

  @section_regexp  = %r{\A\s*\[([^\]]+)\]#{comment}}
  @ignore_regexp   = %r{\A#{comment}}
  @property_regexp = %r{\A(.*?)(?<!\\)#{param}(.*)\z}

  @open_quote      = %r{\A\s*(".*)\z}
  @close_quote     = %r{\A(.*(?<!\\)")#{comment}}
  @full_quote      = %r{\A\s*(".*(?<!\\)")#{comment}}
  @trailing_slash  = %r{\A(.*)(?<!\\)\\#{comment}}
  @normal_value    = %r{\A(.*?)#{comment}}
end

Instance Attribute Details

#propertyObject

Returns the value of attribute property.



418
419
420
# File 'lib/puppet/provider/mysql_login_path/inifile.rb', line 418

def property
  @property
end

#sectionObject

Returns the current section Hash.



581
582
583
# File 'lib/puppet/provider/mysql_login_path/inifile.rb', line 581

def section
  @section ||= @hash[@default]
end

#valueObject

Returns the value of attribute value.



418
419
420
# File 'lib/puppet/provider/mysql_login_path/inifile.rb', line 418

def value
  @value
end

Instance Method Details

#error(msg = 'Could not parse line') ⇒ Object

Raise a parse error using the given message and appending the current line being parsed.

msg - The message String to use.

Raises IniFile::Error

Raises:



591
592
593
# File 'lib/puppet/provider/mysql_login_path/inifile.rb', line 591

def error(msg = 'Could not parse line')
  raise Error, "#{msg}: #{@line.inspect}"
end

#leading_quote?Boolean

Returns ‘true` if the current value starts with a leading double quote. Otherwise returns false.

Returns:

  • (Boolean)


447
448
449
# File 'lib/puppet/provider/mysql_login_path/inifile.rb', line 447

def leading_quote?
  value&.start_with?('"')
end

#parse(content) ⇒ Object

Parse the ini file contents. This will clear any values currently stored in the ini hash.

content - Any object that responds to ‘each_line`

Returns nil.



520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
# File 'lib/puppet/provider/mysql_login_path/inifile.rb', line 520

def parse(content)
  return unless content

  continuation = false

  @hash.clear
  @line = nil
  self.section = nil

  content.each_line do |line|
    @line = line.chomp

    if continuation
      continuation = parse_value @line
    else
      case @line
      when @ignore_regexp
        nil
      when @section_regexp
        self.section = @hash[Regexp.last_match(1)]
      when @property_regexp
        self.property = Regexp.last_match(1).strip
        error if property.empty?

        continuation = parse_value Regexp.last_match(2)
      else
        error
      end
    end
  end

  # check here if we have a dangling value ... usually means we have an
  # unmatched open quote
  if leading_quote?
    error 'Unmatched open quote'
  elsif property && value
    process_property
  elsif value
    error
  end

  nil
end

#parse_value(string) ⇒ Object

Given a string, attempt to parse out a value from that string. This value might be continued on the following line. So this method returns ‘true` if it is expecting more data.

string - String to parse

Returns ‘true` if the next line is also part of the current value. Returns `fase` if the string contained a complete value.



459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
# File 'lib/puppet/provider/mysql_login_path/inifile.rb', line 459

def parse_value(string)
  continuation = false

  # if our value starts with a double quote, then we are in a
  # line continuation situation
  if leading_quote?
    # check for a closing quote at the end of the string
    if string =~ @close_quote
      self.value += Regexp.last_match(1)

      # otherwise just append the string to the value
    else
      self.value += string
      continuation = true
    end

    # not currently processing a continuation line
  else
    case string
    when @full_quote
      self.value = Regexp.last_match(1)

    when @open_quote
      self.value = Regexp.last_match(1)
      continuation = true

    when @trailing_slash
      if self.value
        self.value += Regexp.last_match(1)
      else
        self.value = Regexp.last_match(1)
      end
      continuation = true

    when @normal_value
      if self.value
        self.value += Regexp.last_match(1)
      else
        self.value = Regexp.last_match(1)
      end

    else
      error
    end
  end

  if continuation
    self.value += $INPUT_RECORD_SEPARATOR if leading_quote?
  else
    process_property
  end

  continuation
end

#process_propertyObject

Store the property/value pair in the currently active section. This method checks for continuation of the value to the next line.

Returns nil.



568
569
570
571
572
573
574
575
576
577
578
# File 'lib/puppet/provider/mysql_login_path/inifile.rb', line 568

def process_property
  property.strip!
  value.strip!

  self.value = Regexp.last_match(1) if value =~ %r{\A"(.*)(?<!\\)"\z}m

  section[property] = typecast(value)

  self.property = nil
  self.value = nil
end

#typecast(value) ⇒ Object

Attempt to typecast the value string. We are looking for boolean values, integers, floats, and empty strings. Below is how each gets cast, but it is pretty logical and straightforward.

"true"  -->  true
"false" -->  false
""      -->  nil
"42"    -->  42
"3.14"  -->  3.14
"foo"   -->  "foo"

Returns the typecast value.



607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
# File 'lib/puppet/provider/mysql_login_path/inifile.rb', line 607

def typecast(value)
  case value
  when %r{\Atrue\z}i then  true
  when %r{\Afalse\z}i then false
  when %r{\A\s*\z}i then   nil
  else
    begin
      begin
        Integer(value)
      rescue StandardError
        Float(value)
      end
    rescue StandardError
      unescape_value(value)
    end
  end
end

#unescape_value(value) ⇒ Object

Unescape special characters found in the value string. This will convert escaped null, tab, carriage return, newline, and backslash into their literal equivalents.

value - The String value to unescape.

Returns the unescaped value.



632
633
634
635
636
637
638
639
640
641
642
643
644
# File 'lib/puppet/provider/mysql_login_path/inifile.rb', line 632

def unescape_value(value)
  value = value.to_s
  value.gsub!(%r{\\[0nrt\\]}) do |char|
    case char
    when '\0' then   "\0"
    when '\n' then   "\n"
    when '\r' then   "\r"
    when '\t' then   "\t"
    when '\\\\' then '\\'
    end
  end
  value
end