September 13, 2017

CSV Files with Linq

An example of using Linq to parse a CSV file and write data to a TSV file. The beauty of the approach shown here is the file is read one line at a time when parsing, you do not have to load the whole file to process the data, and written one line at a time when writing. Here is a sample piece of the CSV file (note the first line is a header line not a data line):
id,edsm_id,name,x,y,z,population,is_populated,government_id,government,allegiance_id,allegiance,state_id,state,security_id,security,primary_economy_id,primary_economy,power,power_state,power_state_id,needs_permit,updated_at,simbad_ref,controlling_minor_faction_id,controlling_minor_faction,reserve_type_id,reserve_type
17,60,"10 Ursae Majoris",0.03125,34.90625,-39.09375,0,0,176,None,5,None,80,None,16,Low,10,None,,,,0,1497906646,"10 Ursae Majoris",,,,
24,12009,"11 Bootis",-49.40625,285.25,65.21875,0,0,176,None,5,None,80,None,16,Low,10,None,,,,0,1474116394,"11 Bootis",,,,
26,13308,"11 Mu Aurigae",-30,0.75,-150.03125,0,0,176,None,5,None,80,None,16,Low,10,None,,,,0,1497806946,,,,,


Want to parse some of these lines into this structure:
public class BaseSystemRaw
{
    public int id { get; set; }
    public string name { get; set; }
    public float x { get; set; }
    public float y { get; set; }
    public float z { get; set; }

    public override string ToString()
    {
        return "id=" + id + ", name=" + name + 
               ", location=( " + x + ", " + y + ", " + z + " )";
    }
}
Here is a test harness:
[ TestFixture ]
class ParseCsvFilesWithLinqTests
{
    [ Test ]
    public void ParseCsvFileTest()
    {
        // Skip(1) will skip the header line
        // This commented out version will only use the first 10 lines,
        // great for debugging
        // var baseSystemRaws = File.ReadLines(TestFilePaths.SystemsFilePath).
        //     Take(10).Skip(1).Select(line => ExtractBaseSystemRaw(line));
        var baseSystemRaws = File.ReadLines( TestFilePaths.SystemsFilePath ).
                Skip( 1 ).Select( line => ExtractBaseSystemRaw( line ) );
        DoSomethingWith( baseSystemRaws );
    }

    BaseSystemRaw ExtractBaseSystemRaw(
        string line )
    {
        var parts = line.Split( ',' );
        var sysRaw = new BaseSystemRaw();
        int tmp;
        if ( int.TryParse( parts[ 0 ], out tmp ) )
        {
            sysRaw.id = tmp;
        }
        // Ignore parts[1] edsm_id
        sysRaw.name = parts[ 2 ].Trim().Replace( "\"", "" );
        float ftmp;
        if ( float.TryParse( parts[ 3 ], out ftmp ) )
        {
            sysRaw.x = ftmp;
        }
        if ( float.TryParse( parts[ 4 ], out ftmp ) )
        {
            sysRaw.y = ftmp;
        }
        if ( float.TryParse( parts[ 5 ], out ftmp ) )
        {
            sysRaw.z = ftmp;
        }
        // Ignore other parts
        return sysRaw;
    }

    private void DoSomethingWith(
        IEnumerable<BaseSystemRaw> baseSystemRaws )
    {
        foreach ( var entry in baseSystemRaws )
        {
            Trace.WriteLine( entry );
        }
    }
}
Now write the data to a TSV file.
[ TestFixture ]
class WriteTsvFilesWithLinqTests
{
    [ Test ]
    public void WriteTsvFileTest()
    {
        const string separator = "\t";
        var headers = new[] { "Id", "System", "x", "y", "z" };
        // Skip(1) will skip the header line
        // This version will only use the first 4 lines, great for debugging, 
        // remove the Take(4) to process the whole file
        var baseSystemRaws = File.ReadLines( TestFilePaths.SystemsFilePath ).
            Take(4).Skip(1).Select( line => ExtractBaseSystemRaw( line ) );
        
        // Use Enumerable.Concat to add the header string
        File.WriteAllLines( TestFilePaths.BaseSystemsTsvFilePath,
            Enumerable.Concat( new[] { string.Join( separator, headers ) },
                baseSystemRaws.Select(sys => sys != null ? 
                    CoreSystemRawToTsv( separator, sys ) : "")));
    }

    private string CoreSystemRawToTsv(
        BaseSystemRaw sys )
    {
        string line = string.Join( "\t", sys.id, sys.name, sys.x.ToString( "0.0000" ),
            sys.y.ToString( "0.0000" ), sys.z.ToString( "0.0000" ) );
        return line;
    }
}

September 5, 2017

C# HashSet

Best to demonstrate what some of the methods do with some unit tests. In particular what does 'SymmetricExceptWith' do?
[ TestFixture ]
public class HashSetTests
{
    private HashSet<int> integerSet1;
    private HashSet<int> integerSet1Copy;
    private HashSet<int> integerSet2;

    [ SetUp ]
    public void Setup()
    {
        integerSet1 = new HashSet<int> { 1, 2, 3 };
        integerSet2 = new HashSet<int> { 2, 3, 4 };
        integerSet1Copy = new HashSet<int> { 2, 3, 1 };
    }

    [ Test ]
    // The SetEquals method ignores duplicate entries and 
    // the order of elements in the other parameter.
    public void SetEqualsTest()
    {
        var integerList = new List<int> { 2, 3, 1, 3, 2 };

        Assert.That( !integerSet1.SetEquals( integerSet2 ) );
        Assert.That( integerSet1.SetEquals( integerSet1Copy ) );
        Assert.That( integerSet1.SetEquals( integerList ) );
    }

    [ Test ]
    public void IntersectWithTest() // All elements common to both sets
    {
        integerSet1.IntersectWith( integerSet2 );
        Assert.That( !integerSet1.Contains( 1 ) );
        Assert.That( integerSet1.Contains( 2 ) );
        Assert.That( integerSet1.Contains( 3 ) );
        Assert.That( !integerSet1.Contains( 4 ) );
    }

    [ Test ]
    public void UnionWithTest() // All elements in both sets
    {
        integerSet1.UnionWith( integerSet2 );
        Assert.That( integerSet1.Contains( 1 ) );
        Assert.That( integerSet1.Contains( 2 ) );
        Assert.That( integerSet1.Contains( 3 ) );
        Assert.That( integerSet1.Contains( 4 ) );
    }

    [ Test ]
    public void SymmetricExceptWithTest() // All elements not common to both sets
    {
        integerSet1.SymmetricExceptWith( integerSet2 );
        Assert.That( integerSet1.Contains( 1 ) );
        Assert.That( !integerSet1.Contains( 2 ) );
        Assert.That( !integerSet1.Contains( 3 ) );
        Assert.That( integerSet1.Contains( 4 ) );
    }
}

July 28, 2017

An Alternative Queue Class

Here is an alternative generic Queue class. I created it as I constantly found when using a queue class that Enqueue and Dequeue were never enough. There was always a need for a remove an item and a need to iterate through all the items in a queue. The original basic source for the queue class is here.
public class Node< T >
{
    public T Data { get; set; }
    public Node<T> Next { get; set; }

    public Node( T data )
    {
        this.Data = data;
    }
}

public class Queue2< T >
{
    private Node<T> _head;
    private Node<T> _tail;
    private int _count;
    private readonly IEqualityComparer<T> _comparator;

    public Queue2()
    {
        _comparator = EqualityComparer<T>.Default;
    }

    public Queue2( IEqualityComparer<T> comparator )
    {
        _comparator = comparator;
    }

    public void Enqueue(
        T data )
    {
        Node<T> _newNode = new Node<T>( data );
        if ( _head == null )
        {
            _head = _newNode;
            _tail = _head;
        }
        else
        {
            _tail.Next = _newNode;
            _tail = _tail.Next;
        }
        _count++;
    }

    public T Dequeue()
    {
        if ( _head == null )
        {
            throw new Exception( "Queue is Empty" );
        }
        T _result = _head.Data;
        _head = _head.Next;
        return _result;
    }

    public void Remove(
        T item )
    {
        Node<T> previous = null, cursor = _head;
        bool found = false;
        while ( ( cursor != null ) && !found )
        {
            found = _comparator.Equals( cursor.Data, item );
            if ( found )
            {
                if ( previous == null )
                {
                    _head = cursor.Next;
                }
                else
                {
                    previous.Next = cursor.Next;
                }
            }
            else
            {
                previous = cursor;
                cursor = cursor.Next;
            }
        }
    }

    public void Clear()
    {
        _head = _tail = null;
    }

    public IEnumerable<T> GetEnumerator()
    {
        Node<T> cursor = _head;
        while ( cursor != null )
        {
            yield return cursor.Data;
            cursor = cursor.Next;
        }
    }

    public int Count
    {
        get { return this._count; }
    }
}

July 20, 2017

A String.Split() That Returns An IEnumerable

A version of Split string that returns an IEnumerable<string> rather than an array. Only single separate string is allowed, it is very rare that an array of separator strings is required.
  
public static class StringSplitExtensions
{
  
  public static IEnumerable<string> Split2(
    this string targetStr,
    string separator )
  {
    if ( targetStr == null )
      yield break;

    if ( string.IsNullOrEmpty( separator ) )
    {
      yield return targetStr;
    }
    else
    {
      string str = targetStr;
      bool finished = false;
      int startIx = 0;
      int sepLength = separator.Length;
      while ( !finished )
      {
        var ix = str.IndexOf( separator, 
            StringComparison.OrdinalIgnoreCase );
        if ( ix == -1 )
        {
          finished = true;
          yield return str;
        }
        else
        {
          string res = str.Substring( 0, ix );
          yield return res;
          startIx = ix + sepLength;
          str = str.Substring( startIx, str.Length - startIx );
        }
      }
    }
  }
}



[ Test ]
public void SplitTest()
{
  string test = "012 3456\t7890\ta  aaa\tbbbb\t";

  var res2 = test.Split2( "\t" ).ToArray();
  var norm2 = test.Split( '\t' );
  Assert.IsTrue( AreTheSame( res2, norm2 ) );

  var res3 = "".Split2( "\t" ).ToArray();
  var norm3 = "".Split( '\t' );
  Assert.IsTrue( AreTheSame( res3, norm3 ) );

  var res4 = "\t".Split2( "\t" ).ToArray();
  var norm4 = "\t".Split( '\t' );
  Assert.IsTrue( AreTheSame( res4, norm4 ) );

  var res5 = "\t\t".Split2( "\t" ).ToArray();
  var norm5 = "\t\t".Split( '\t' );
  Assert.IsTrue( AreTheSame( res5, norm5 ) );

  var res6 = "a\t".Split2( "\t" ).ToArray();
  var norm6 = "a\t".Split( '\t' );
  Assert.IsTrue( AreTheSame( res6, norm6 ) );

  var res7 = "\ta".Split2( "\t" ).ToArray();
  var norm7 = "\ta".Split( '\t' );
  Assert.IsTrue( AreTheSame( res7, norm7 ) );

  // Works the same as a standard Split string except in 
  // the case where the Splitter string is an empty string
  var norm8 = test.Split();
  var res8 = test.Split2( "" ).ToArray();
  Assert.IsFalse( AreTheSame( res8, norm8 ) );
}


// Checks whether 2 string arrays are exactly the same, ie. they have
// the same length and the same values at each array entry
public static bool AreTheSame(
string[] stringArray1,
string[] stringArray2)
{
  bool areTheSame = (stringArray1.Length == stringArray2.Length);
  for (int ix = 0; (ix < stringArray1.Length) && areTheSame; ix++)
  {
    areTheSame = stringArray1[ix].Equals(stringArray2[ix], StringComparison.CurrentCulture);
  }
  return areTheSame;
}

June 29, 2017

Case Insensitive Dictionary


Very easy to implement in C#, just pass 'StringComparer.OrdinalIgnoreCase' in the constructor, for example:
Dictionary nameToIdTable = new Dictionary(StringComparer.OrdinalIgnoreCase);
Here is an an example in action:
[ Test ]
public void CaseInsenstiveDictionaryTest()
{
  var dictionary = new Dictionary(StringComparer.OrdinalIgnoreCase)
  {
    { "Mbukuravi", 1 },
    { "Liaedin", 2 },
  };

  Assert.That( dictionary[ "Liaedin" ] == 2 );
  Assert.That( dictionary[ "LiAEdin" ] == 2 );
  Assert.That( dictionary[ "LiaeDIn" ] == 2 );
  Assert.That( dictionary[ "LIAEDIN" ] == 2 );
}

June 14, 2017

A ConcurrentStreamWriter Class

A class for writing to a stream from multiple threads:

public interface IConcurrentStreamWriter
{
    void WriteStream(
        string theStringToWrite);
}

/// <summary>
///     A concurrent stream writer. Allows concurrent/queued writes to a stream
/// </summary>
///
/// <seealso cref="T:ASM.DEK.Printer.Micron.PrintEngine.Timing.Timers.IConcurrentStreamWriter"/>
/// <seealso cref="T:System.IDisposable"/>
public class ConcurrentStreamWriter : IConcurrentStreamWriter, IDisposable
{
    private readonly Func<StreamWriter> _streamWriterProvider;
    private readonly ConcurrentQueue<string> queuedWrites = new ConcurrentQueue<string>();
    private readonly AutoResetEvent _autoResetEvent = new AutoResetEvent(false);

    private bool _exit;

    public ConcurrentStreamWriter(
        Func<StreamWriter> streamWriterProvider)
    {
        Contract.Requires<ArgumentNullException>(
            streamWriterProvider != null);

        _streamWriterProvider = streamWriterProvider;

        Task.Factory.StartNew(
            WriteQueueThreadRoutine, 
            TaskCreationOptions.LongRunning);
    }

    public void WriteStream(
        string theStringToWrite)
    {
        if (!string.IsNullOrEmpty(theStringToWrite))
        {
            queuedWrites.Enqueue(theStringToWrite);
            _autoResetEvent.Set();
        }
    }

    #region private

    private void WriteQueueThreadRoutine()
    {
        using (var stream = _streamWriterProvider())
        {
            while (!_exit)
            {
                _autoResetEvent.WaitOne();
                if (queuedWrites.Count > 0)
                {
                    WriteQueueImpl(stream);
                }
            }
        }
        _autoResetEvent.Dispose();
    }

    private void WriteQueueImpl(
        StreamWriter stream)
    {
        try
        {
            string stringToWrite = "";
            do
            {
                if (queuedWrites.TryDequeue(out stringToWrite))
                {
                    stream.WriteLine(stringToWrite);
                }
            } while (queuedWrites.Count > 0);
            stream.Flush();
        }
        catch (IOException ioex)
        {
            Trace.WriteLine("IOException caught: " + ioex);
        }
    }

    #endregion private

    #region Dispose Implementation

    // Use C# destructor syntax for finalization code.
    ~ConcurrentStreamWriter()
    {
        Dispose(false);
        Debug.Assert(false, "Detected ConcurrentStreamWriter object was undisposed");
    }

    private bool _isDisposed;

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(
        bool disposing)
    {
        if (_isDisposed)
            return;

        if (disposing)
        {
            _exit = true;
            _autoResetEvent.Set();
        }

        _isDisposed = true;
    }

    #endregion Dispose Implementation
}
It uses a ConcurrentQueue object to queue the stream requests up and an AutoResetEvent to release a writer on a separate thread to actually output the stream contents.

May 25, 2017

Fluent Builder Template

Fluent interfaces Create a more simplified language style approach to coding.
Here is a template for an object builder class that gives a fluent interface for the construction of objects:
[ ExcludeFromCodeCoverage ]
public class $XXX$Builder
{
    private $IYYY$ _mock$IYYY$ = Substitute.For<$IYYY$>();

    public $XXX$Builder With$IYYY$(
        $IYYY$ param )
    {
        _mock$IYYY$ = param;
        return this;
    }

    public static implicit operator $XXX$( $XXX$Builder builder )
    {
        return builder.Build();
    }

    public $XXX$ Build()
    {
        return new $XXX$( _mock$IYYY$ );
    }
}
Replace $XXX$ with your concrete builder target type
For each service replace $IYYY$ with the service name