Haxe: Simplistic .properties parser

If you have ever been using Java, you may already be familiar with .properties file format. This is a simplistic configuration file format, somewhat similar to INI:

# Comment
key = Value

For ones not liking that, there's also alternative syntax:

! Comment
key: Value

Where leading/trailing spaces are optional and are trimmed in parsing process.

Since I've seen people ask about this kind of thing, and also have seen people invent ridiculous (and non-functional) regular expressions to parse this file format, I thought that I may as well make an implementation that works "just right".

Ideas are reasonable:

  • Regular expressions are cool [citation needed], but implementations may vary, and they may perform well, not so well, or outright awful (especially when it comes to multi-line splitting).
  • Splitting file into separate strings (a common thing to do) is a bit faster (in terms of lines of code taken), but unnecessary - that way you do no better than allocating a bunch of strings (input worth of strings, to be precise) just to throw them away in a moment.

Thus, what I've came up with, are some minimally tricky String.indexOf manipulations, which split the input string without any extra trouble, while keeping performance and memory healthy.

Code is as following:

static function parseProperties(text:String):Map<String, String> {
	var map:Map<String, String> = new Map(),
		ofs:Int = 0,
		len:Int = text.length,
		i:Int, j:Int,
		endl:Int;
	while (ofs < len) {
		// find line end offset:
		endl = text.indexOf("\n", ofs);
		if (endl < 0) endl = len; // last line
		// do not process comment lines:
		i = text.charCodeAt(ofs);
		if (i != "#".code && i != "!".code) {
			// find key-value delimiter:
			i = text.indexOf("=", ofs);
			j = text.indexOf(":", ofs);
			if (j != -1 && (i == -1 || j < i)) i = j;
			//
			if (i >= ofs && i < endl) {
				// key-value pair "key: value\n"
				map.set(StringTools.trim(text.substring(ofs, i)),
					StringTools.trim(text.substring(i + 1, endl)));
			} else {
				// value-less declaration "key\n"
				map.set(StringTools.trim(text.substring(ofs, endl)), "");
			}
		}
		// move on to next line:
		ofs = endl + 1;
	}
	return map;
}

You can also get the fucntion and example of usage from Github:

Gist (function + example)

Few things to note:

  • For the sake of not doing an extra useless operation, function assumes that linebreaks are \n. If they are not, use StringTools.replace before calling.
  • For reason similar to above, escape characters are not being handled. You can still post-process values in outcoming Map structure though.

Well, that's it. Hopefully, this was useful 🙂

Related posts:

One thought on “Haxe: Simplistic .properties parser

Leave a Reply

Your email address will not be published. Required fields are marked *