Class: Cosmos::ConfigParser
- Defined in:
- lib/cosmos/config/config_parser.rb,
ext/cosmos/ext/config_parser/config_parser.c
Overview
Reads COSMOS style configuration data which consists of keywords followed by 0 or more comma delimited parameters. Parameters with spaces must be enclosed in quotes. Quotes should also be used to indicate a parameter is a string. Keywords are case-insensitive and will be returned in uppercase.
Defined Under Namespace
Classes: Error
Constant Summary collapse
- PARSING_REGEX =
Regular expression used to break up an individual line into a keyword and comma delimited parameters. Handles parameters in single or double quotes.
%r{ (?:"(?:[^\\"]|\\.)*") | (?:'(?:[^\\']|\\.)*') | \S+ }x
- @@message_callback =
nil
- @@progress_callback =
nil
- @@splash =
Holds the current splash screen
nil
Instance Attribute Summary collapse
-
#filename ⇒ String
The name of the configuration file being parsed.
-
#keyword ⇒ String
The current keyword being parsed.
-
#line ⇒ String
The current line being parsed.
-
#line_number ⇒ Integer
The current line number being parsed.
-
#parameters ⇒ Array<String>
The parameters found after the keyword.
-
#url ⇒ String
The default URL to use in errors.
Class Method Summary collapse
-
.handle_defined_constants(value, data_type = nil, bit_size = nil) ⇒ Numeric
Converts a string representing a defined constant into its value.
-
.handle_nil(value) ⇒ nil|Object
Converts a String containing ”, ‘NIL’ or ‘NULL’ to nil Ruby primitive.
-
.handle_true_false(value) ⇒ true|false|Object
Converts a String containing ‘TRUE’ or ‘FALSE’ to true or false Ruby primitive.
-
.handle_true_false_nil(value) ⇒ true|false|nil|Object
Converts a String containing ”, ‘NIL’, ‘NULL’, ‘TRUE’ or ‘FALSE’ to nil, true or false Ruby primitives.
- .message_callback=(message_callback) ⇒ Object
- .progress_callback=(progress_callback) ⇒ Object
-
.splash ⇒ Object
Returns the current splash screen if present.
- .splash=(splash) ⇒ Object
Instance Method Summary collapse
-
#error(message, usage = "", url = @url) ⇒ Error
Creates an Error.
-
#initialize(url = "http://cosmosc2.com/docs/v5") ⇒ ConfigParser
constructor
A new instance of ConfigParser.
-
#parse_file(filename, yield_non_keyword_lines = false, remove_quotes = true, run_erb = true, variables = {}, &block) {|keyword, parameters| ... } ⇒ Object
Processes a file and yields |config| to the given block.
-
#parse_loop(io, yield_non_keyword_lines, remove_quotes, size, rx) ⇒ Object
Iterates over each line of the io object and yields the keyword and parameters.
-
#render(template_name, options = {}) ⇒ Object
Called by the ERB template to render a partial.
-
#verify_num_parameters(min_num_params, max_num_params, usage = "") ⇒ Object
Verifies the parameters in the config parameter have the specified number of parameter and raises an Error if not.
-
#verify_parameter_naming(index, usage = "") ⇒ Object
Verifies the indicated parameter in the config doesn’t start or end with an underscore, doesn’t contain a double underscore, doesn’t contain spaces and doesn’t start with a close bracket.
Constructor Details
#initialize(url = "http://cosmosc2.com/docs/v5") ⇒ ConfigParser
Returns a new instance of ConfigParser.
142 143 144 |
# File 'lib/cosmos/config/config_parser.rb', line 142 def initialize(url = "http://cosmosc2.com/docs/v5") @url = url end |
Instance Attribute Details
#filename ⇒ String
Returns The name of the configuration file being parsed. This will be an empty string if the parse_string class method is used.
38 39 40 |
# File 'lib/cosmos/config/config_parser.rb', line 38 def filename @filename end |
#keyword ⇒ String
Returns The current keyword being parsed.
31 32 33 |
# File 'lib/cosmos/config/config_parser.rb', line 31 def keyword @keyword end |
#line ⇒ String
Returns The current line being parsed. This is the raw string which is useful when printing errors.
42 43 44 |
# File 'lib/cosmos/config/config_parser.rb', line 42 def line @line end |
#line_number ⇒ Integer
Returns The current line number being parsed. This will still be populated when using parse_string because lines still must be delimited by newline characters.
47 48 49 |
# File 'lib/cosmos/config/config_parser.rb', line 47 def line_number @line_number end |
#parameters ⇒ Array<String>
Returns The parameters found after the keyword.
34 35 36 |
# File 'lib/cosmos/config/config_parser.rb', line 34 def parameters @parameters end |
#url ⇒ String
Returns The default URL to use in errors. The URL can still be overridden by directly passing it to the error method.
51 52 53 |
# File 'lib/cosmos/config/config_parser.rb', line 51 def url @url end |
Class Method Details
.handle_defined_constants(value, data_type = nil, bit_size = nil) ⇒ Numeric
Converts a string representing a defined constant into its value. The defined constants are the minimum and maximum values for all the allowable data types. [MIN/MAX]_[U]INT and [MIN/MAX]_FLOAT. Thus MIN_UINT8, MAX_INT32, and MIN_FLOAT64 are all allowable values. Any other strings raise ArgumentError but all other types are simply returned.
322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 |
# File 'lib/cosmos/config/config_parser.rb', line 322 def self.handle_defined_constants(value, data_type = nil, bit_size = nil) if value.class == String case value.upcase when 'MIN', 'MAX' return self.calculate_range_value(value.upcase, data_type, bit_size) when 'MIN_INT8' return -128 when 'MAX_INT8' return 127 when 'MIN_INT16' return -32768 when 'MAX_INT16' return 32767 when 'MIN_INT32' return -2147483648 when 'MAX_INT32' return 2147483647 when 'MIN_INT64' return -9223372036854775808 when 'MAX_INT64' return 9223372036854775807 when 'MIN_UINT8', 'MIN_UINT16', 'MIN_UINT32', 'MIN_UINT64' return 0 when 'MAX_UINT8' return 255 when 'MAX_UINT16' return 65535 when 'MAX_UINT32' return 4294967295 when 'MAX_UINT64' return 18446744073709551615 when 'MIN_FLOAT64' return -Float::MAX when 'MAX_FLOAT64' return Float::MAX when 'MIN_FLOAT32' return -3.402823e38 when 'MAX_FLOAT32' return 3.402823e38 when 'POS_INFINITY' return Float::INFINITY when 'NEG_INFINITY' return -Float::INFINITY else raise ArgumentError, "Could not convert constant: #{value}" end end return value end |
.handle_nil(value) ⇒ nil|Object
Converts a String containing ”, ‘NIL’ or ‘NULL’ to nil Ruby primitive. All other arguments are simply returned.
267 268 269 270 271 272 273 274 275 |
# File 'lib/cosmos/config/config_parser.rb', line 267 def self.handle_nil(value) if String === value case value.upcase when '', 'NIL', 'NULL' return nil end end return value end |
.handle_true_false(value) ⇒ true|false|Object
Converts a String containing ‘TRUE’ or ‘FALSE’ to true or false Ruby primitive. All other values are simply returned.
282 283 284 285 286 287 288 289 290 291 292 |
# File 'lib/cosmos/config/config_parser.rb', line 282 def self.handle_true_false(value) if String === value case value.upcase when 'TRUE' return true when 'FALSE' return false end end return value end |
.handle_true_false_nil(value) ⇒ true|false|nil|Object
Converts a String containing ”, ‘NIL’, ‘NULL’, ‘TRUE’ or ‘FALSE’ to nil, true or false Ruby primitives. All other values are simply returned.
299 300 301 302 303 304 305 306 307 308 309 310 311 |
# File 'lib/cosmos/config/config_parser.rb', line 299 def self.handle_true_false_nil(value) if String === value case value.upcase when 'TRUE' return true when 'FALSE' return false when '', 'NIL', 'NULL' return nil end end return value end |
.message_callback=(message_callback) ⇒ Object
58 59 60 |
# File 'lib/cosmos/config/config_parser.rb', line 58 def self.() @@message_callback = end |
.progress_callback=(progress_callback) ⇒ Object
68 69 70 |
# File 'lib/cosmos/config/config_parser.rb', line 68 def self.progress_callback=(progress_callback) @@progress_callback = progress_callback end |
.splash ⇒ Object
Returns the current splash screen if present
90 91 92 |
# File 'lib/cosmos/config/config_parser.rb', line 90 def self.splash @@splash end |
.splash=(splash) ⇒ Object
77 78 79 80 81 82 83 84 85 86 87 |
# File 'lib/cosmos/config/config_parser.rb', line 77 def self.splash=(splash) if splash @@splash = splash @@progress_callback = splash.progress_callback @@message_callback = splash. else @@splash = nil @@progress_callback = nil @@message_callback = nil end end |
Instance Method Details
#error(message, usage = "", url = @url) ⇒ Error
Creates an Error
152 153 154 |
# File 'lib/cosmos/config/config_parser.rb', line 152 def error(, usage = "", url = @url) return Error.new(self, , usage, url) end |
#parse_file(filename, yield_non_keyword_lines = false, remove_quotes = true, run_erb = true, variables = {}, &block) {|keyword, parameters| ... } ⇒ Object
Processes a file and yields |config| to the given block
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 |
# File 'lib/cosmos/config/config_parser.rb', line 187 def parse_file(filename, yield_non_keyword_lines = false, remove_quotes = true, run_erb = true, variables = {}, &block) raise Error.new(self, "Configuration file #{filename} does not exist.") unless filename && File.exist?(filename) @filename = filename # Create a temp file where we write the ERB parsed output file = create_parsed_output_file(filename, run_erb, variables) size = file.stat.size.to_f # Callbacks for beginning of parsing @@message_callback.call("Parsing #{size} bytes of #{filename}") if @@message_callback @@progress_callback.call(0.0) if @@progress_callback begin # Loop through each line of the data parse_loop(file, yield_non_keyword_lines, remove_quotes, size, PARSING_REGEX, &block) rescue Exception => e # Catch EVERYTHING so we can re-raise with additional info raise e, "#{e}\n\nParsed output in #{file.path}", e.backtrace ensure file.close unless file.closed? end end |
#parse_loop(io, yield_non_keyword_lines, remove_quotes, size, rx) ⇒ Object
Iterates over each line of the io object and yields the keyword and parameters
442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 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 513 514 515 516 517 518 519 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 |
# File 'lib/cosmos/config/config_parser.rb', line 442 def parse_loop(io, yield_non_keyword_lines, remove_quotes, size, rx) line_continuation = false @line_number = 0 @keyword = nil @parameters = [] @line = nil while true @line_number += 1 if @@progress_callback && ((@line_number % 10) == 0) @@progress_callback.call(io.pos / size) if size > 0.0 end begin line = io.readline rescue Exception break end line.strip! data = line.scan(rx) first_item = data[0].to_s if line_continuation @line << line # Carry over keyword and parameters else @line = line if (first_item.length == 0) || (first_item[0] == '#') @keyword = nil else @keyword = first_item.upcase end @parameters = [] end # Ignore comments and blank lines if @keyword.nil? if (yield_non_keyword_lines) && (!line_continuation) yield(@keyword, @parameters) end next end if line_continuation if remove_quotes @parameters << first_item.remove_quotes else @parameters << first_item end line_continuation = false end length = data.length if length > 1 (1..(length - 1)).each do |index| string = data[index] # Don't process trailing comments such as: # KEYWORD PARAM #This is a comment # But still process Ruby string interpolations such as: # KEYWORD PARAM #{var} if (string.length > 0) && (string[0] == '#') if !((string.length > 1) && (string[1] == '{')) break end end # If the string is simply '&' and its the last string then its a line continuation so break the loop if (string.length == 1) && (string[0] == '&') && (index == (length - 1)) line_continuation = true next end line_continuation = false if remove_quotes @parameters << string.remove_quotes else @parameters << string end end end # If we detected a line continuation while going through all the # strings on the line then we strip off the continuation character and # return to the top of the loop to continue processing the line. if line_continuation # Strip the continuation character if @line.length >= 1 @line = @line[0..-2] else @line = "" end next end yield(@keyword, @parameters) end @@progress_callback.call(1.0) if @@progress_callback return nil end |
#render(template_name, options = {}) ⇒ Object
Called by the ERB template to render a partial
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 |
# File 'lib/cosmos/config/config_parser.rb', line 157 def render(template_name, = {}) raise Error.new(self, "Partial name '#{template_name}' must begin with an underscore.") if File.basename(template_name)[0] != '_' b = binding if [:locals] [:locals].each { |key, value| b.local_variable_set(key, value) } end # Assume the file is there. If not we raise a pretty obvious error if File.(template_name) == template_name # absolute path path = template_name else # relative to the current @filename path = File.join(File.dirname(@filename), template_name) end Cosmos.set_working_dir(File.dirname(path)) do return ERB.new(File.read(path)).result(b) end end |
#verify_num_parameters(min_num_params, max_num_params, usage = "") ⇒ Object
Verifies the parameters in the config parameter have the specified number of parameter and raises an Error if not.
226 227 228 229 230 231 232 233 234 235 236 237 238 239 |
# File 'lib/cosmos/config/config_parser.rb', line 226 def verify_num_parameters(min_num_params, max_num_params, usage = "") # This syntax works with 0 because each doesn't return any values # for a backwards range (1..min_num_params).each do |index| # If the parameter is nil (0 based) then we have a problem if @parameters[index - 1].nil? raise Error.new(self, "Not enough parameters for #{@keyword}.", usage, @url) end end # If they pass nil for max_params we don't check for a maximum number if max_num_params && !@parameters[max_num_params].nil? raise Error.new(self, "Too many parameters for #{@keyword}.", usage, @url) end end |
#verify_parameter_naming(index, usage = "") ⇒ Object
Verifies the indicated parameter in the config doesn’t start or end with an underscore, doesn’t contain a double underscore, doesn’t contain spaces and doesn’t start with a close bracket.
246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 |
# File 'lib/cosmos/config/config_parser.rb', line 246 def verify_parameter_naming(index, usage = "") param = @parameters[index - 1] if param.end_with? '_' raise Error.new(self, "Parameter #{index} (#{param}) for #{@keyword} cannot end with an underscore ('_').", usage, @url) end if param.include? '__' raise Error.new(self, "Parameter #{index} (#{param}) for #{@keyword} cannot contain a double underscore ('__').", usage, @url) end if param.include? ' ' raise Error.new(self, "Parameter #{index} (#{param}) for #{@keyword} cannot contain a space (' ').", usage, @url) end if param.start_with?('}') raise Error.new(self, "Parameter #{index} (#{param}) for #{@keyword} cannot start with a close bracket ('}').", usage, @url) end end |