HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Initialization File Parser

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
parserinitializationfile

Problem

For my game I decided to incorporate .ini Initialization Files to store game data. Items like: Weapons, Armor, Potions, Enemies, Actors, Loot Drops, and so much more. All of these things can be easily expressed as simple .ini files with the header-based schema, as I will show later. This design decision also came about with the desire for performance. Naturally I could have used XML or JSON, but I feel as though it would have been overkill, and slower than my own custom parser which does as little as possible.

I wanted to show you guys my implementation of a .ini parser, to see if you could suggest any changes, or things that could possibly increase the performance of it. Out of everything, performance is my number one concern.

```
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

namespace GrimoireEngine.Framework.Utilities
{
public class InitializationFile
{
public Dictionary> Data { get; set; }

public const string Extension = ".ini";

private string _fileName;

public string FileName
{
get
{
return _fileName;
}
}

private string _source;

public string Source
{
get { return _source; }
set
{
if (value.EndsWith(Extension))
{
this._source = value;
}
else
{
throw new FileLoadException(Path.GetExtension(value) + " is not a valid " + Extension + " file Extension!");
}
}
}

private string _mountedHeader;

public string MountedHeader
{
get
{
return _mountedHeader;
}
set
{
if (HasHeader(value))
{
this._mountedHeader = value;
}

Solution

The HasKey(string,string) can be simplified like so

public bool HasKey(string header, string key)
{
    return HasHeader(header) && this.Data[header].ContainsKey(key);
}


because if you have an if construct like

if (condition)
{
    return true;
}
return false;


you can simply return the condition.

The GetValue(string,string) is calling HasHeader() although this is done by the hasKey() method as well. So we can clean it like so

public string GetValue(string header, string key)
    {
        if (HasKey(header, key))
        {
            return this.Data[header][key];
        }
        throw new KeyNotFoundException();
    }


throw new Exception("No Header is Mounted!");


This screems for a custom exception, maybe named NoHeaderException. You should always throw a specific exception, this has the advantage that if you enclose a call to a method in a try..catch method you can catch more distinctly and you don't have the need for catching a System.Exception.

See also why-are-we-not-to-throw-these-exceptions

Code Snippets

public bool HasKey(string header, string key)
{
    return HasHeader(header) && this.Data[header].ContainsKey(key);
}
if (condition)
{
    return true;
}
return false;
public string GetValue(string header, string key)
    {
        if (HasKey(header, key))
        {
            return this.Data[header][key];
        }
        throw new KeyNotFoundException();
    }
throw new Exception("No Header is Mounted!");

Context

StackExchange Code Review Q#152211, answer score: 8

Revisions (0)

No revisions yet.