Revision: 23096
Updated Code
at February 10, 2010 10:49 by jimfred
Updated Code
/// <summary>
/// Convert a double-null terminated string into an array of strings
/// Example usage:
/// char [] buff = new char[];
/// // fill Buff with data calling an API.
/// string[] a = MultistringToStringArray(ref buff); // Find first double-null.
/// </summary>
/// <param name="arg">double-null terminated string</param>
/// <returns>array of strings</returns>
/// Gracefully handle fringe conditions: missing double-null, missing trailing single null,
private static string [] MultistringToStringArray(ref char[] arg)
{
// Search an array of bytes for a double-null before converting to string.
int qty, j;
for ( qty = 0, j = 1; ; qty++, j++)
{
bool done = qty > (arg.Length - 1) || (arg[qty] == 0 && j < arg.Length && arg[j] == 0);
if (done)
{
break;
} // if
} // for
string b = new string(arg, 0, qty);
return b.Split(new char[] { '\0' }, 9, StringSplitOptions.RemoveEmptyEntries);
} // lengthDoubleNull
// More concise but less efficient variation.
private static string [] MultistringToStringArray(ref char[] arg)
{
string s2 = new string(arg); // convert to string - even bytes after \0\0.
int x = s2.IndexOf("\0\0"); // find double-null.
if (x != -1) { s2 = s2.Remove(x); } // remove if found.
return s2.Split(new char[] { '\0' }, StringSplitOptions.RemoveEmptyEntries);
}
// test this function. Use Enumerable.SequenceEqual to deep-compare array of strings.
[Conditional("DEBUG")]
private static void MultistringToStringArrayTest()
{
char[] b;
// fringe scenario. missing double-null.
b = new char[] { 'a', 'b', 'c' };
Debug.Assert( Enumerable.SequenceEqual(new string[] { "abc" }, MultistringToStringArray(ref b)));
// fringe scenario. missing double-null.
b = new char[] { 'a', 'b', 'c', '\0' };
Debug.Assert( Enumerable.SequenceEqual(new string[] { "abc" }, MultistringToStringArray(ref b)));
// fringe scenario. missing single-null.
b = new char[] { 'a', 'b', 'c', '\0', '\0', 'a', 'b', 'c' };
Debug.Assert( Enumerable.SequenceEqual(new string[] { "abc" }, MultistringToStringArray(ref b)));
// Most common scenario - embedded nulls with a terminating double-null and junk after that.
b = new char[] { 'a', 'b', 'c', '\0', '1', '2', '3', '\0', '\0', 'a', 'b', 'c' };
Debug.Assert( Enumerable.SequenceEqual(new string[] { "abc", "123" }, MultistringToStringArray(ref b)));
// fringe scenario. missing double-null.
b = new char[] { 'a', 'b', 'c', '\0', '1', '2', '3', '4', '\0' };
Debug.Assert(Enumerable.SequenceEqual(new string[] { "abc", "1234" }, MultistringToStringArray(ref b)));
// common scenario.
b = new char[] { 'a', 'b', 'c', '\0', '1', '2', '3', '4', '\0', 'A', 'B', 'C', '\0' };
Debug.Assert(Enumerable.SequenceEqual(new string[] { "abc", "1234", "ABC" }, MultistringToStringArray(ref b)));
}
Revision: 23095
Updated Code
at January 29, 2010 18:18 by jimfred
Updated Code
/// <summary>
/// Determine the length of a double-null terminated string.
/// Example usage:
/// char [] buff = new char[];
/// // fill Buff with data calling an API.
/// string[] a = MultistringToStringArray(ref buff); // Find first double-null.
/// </summary>
/// <param name="arg">double-null terminated string</param>
/// <returns>array of strings</returns>
/// Gracefully handle fringe conditions: missing double-null, missing trailing single null,
private static string [] MultistringToStringArray(ref char[] arg)
{
// Search an array of bytes for a double-null before converting to string.
int qty, j;
for ( qty = 0, j = 1; ; qty++, j++)
{
bool done = qty > (arg.Length - 1) || (arg[qty] == 0 && j < arg.Length && arg[j] == 0);
if (done)
{
break;
} // if
} // for
string b = new string(arg, 0, qty);
return b.Split(new char[] { '\0' }, 9, StringSplitOptions.RemoveEmptyEntries);
} // lengthDoubleNull
// More concise but less efficient variation.
private static string [] MultistringToStringArray(ref char[] arg)
{
string s2 = new string(arg); // convert to string - even bytes after \0\0.
int x = s2.IndexOf("\0\0"); // find double-null.
if (x != -1) { s2 = s2.Remove(x); } // remove if found.
return s2.Split(new char[] { '\0' }, StringSplitOptions.RemoveEmptyEntries);
}
// test this function. Use Enumerable.SequenceEqual to deep-compare array of strings.
[Conditional("DEBUG")]
private static void MultistringToStringArrayTest()
{
char[] b;
// fringe scenario. missing double-null.
b = new char[] { 'a', 'b', 'c' };
Debug.Assert( Enumerable.SequenceEqual(new string[] { "abc" }, MultistringToStringArray(ref b)));
// fringe scenario. missing double-null.
b = new char[] { 'a', 'b', 'c', '\0' };
Debug.Assert( Enumerable.SequenceEqual(new string[] { "abc" }, MultistringToStringArray(ref b)));
// fringe scenario. missing single-null.
b = new char[] { 'a', 'b', 'c', '\0', '\0', 'a', 'b', 'c' };
Debug.Assert( Enumerable.SequenceEqual(new string[] { "abc" }, MultistringToStringArray(ref b)));
// Most common scenario - embedded nulls with a terminating double-null and junk after that.
b = new char[] { 'a', 'b', 'c', '\0', '1', '2', '3', '\0', '\0', 'a', 'b', 'c' };
Debug.Assert( Enumerable.SequenceEqual(new string[] { "abc", "123" }, MultistringToStringArray(ref b)));
// fringe scenario. missing double-null.
b = new char[] { 'a', 'b', 'c', '\0', '1', '2', '3', '4', '\0' };
Debug.Assert(Enumerable.SequenceEqual(new string[] { "abc", "1234" }, MultistringToStringArray(ref b)));
// common scenario.
b = new char[] { 'a', 'b', 'c', '\0', '1', '2', '3', '4', '\0', 'A', 'B', 'C', '\0' };
Debug.Assert(Enumerable.SequenceEqual(new string[] { "abc", "1234", "ABC" }, MultistringToStringArray(ref b)));
}
Revision: 23094
Updated Code
at January 29, 2010 18:11 by jimfred
Updated Code
/// <summary>
/// Determine the length of a double-null terminated string.
/// Example usage:
/// char [] buff = new char[];
/// // fill Buff with data calling an API.
/// string[] a = DoubleNullToStringArray(ref buff); // Find first double-null.
/// </summary>
/// <param name="arg">double-null terminated string</param>
/// <returns>array of strings</returns>
/// Gracefully handle fringe conditions: missing double-null, missing trailing single null,
private static string [] DoubleNullToStringArray(ref char[] arg)
{
// Search an array of bytes for a double-null before converting to string.
int qty, j;
for ( qty = 0, j = 1; ; qty++, j++)
{
bool done = qty > (arg.Length - 1) || (arg[qty] == 0 && j < arg.Length && arg[j] == 0);
if (done)
{
break;
} // if
} // for
string b = new string(arg, 0, qty);
return b.Split(new char[] { '\0' }, 9, StringSplitOptions.RemoveEmptyEntries);
} // lengthDoubleNull
// More concise but less efficient variation.
private static string [] DoubleNullToStringArray(ref char[] arg)
{
string s2 = new string(arg); // convert to string - even bytes after \0\0.
int x = s2.IndexOf("\0\0"); // find double-null.
if (x != -1) { s2 = s2.Remove(x); } // remove if found.
return s2.Split('\0', StringSplitOptions.RemoveEmptyEntries);
}
// test this function. Use Enumerable.SequenceEqual to deep-compare array of strings.
[Conditional("DEBUG")]
private static void lengthDoubleNullTest()
{
char[] b;
// fringe scenario. missing double-null.
b = new char[] { 'a', 'b', 'c' };
Debug.Assert( Enumerable.SequenceEqual(new string[] { "abc" }, DoubleNullToStringArray(ref b)));
// fringe scenario. missing double-null.
b = new char[] { 'a', 'b', 'c', '\0' };
Debug.Assert( Enumerable.SequenceEqual(new string[] { "abc" }, DoubleNullToStringArray(ref b)));
// fringe scenario. missing single-null.
b = new char[] { 'a', 'b', 'c', '\0', '\0', 'a', 'b', 'c' };
Debug.Assert( Enumerable.SequenceEqual(new string[] { "abc" }, DoubleNullToStringArray(ref b)));
// Most common scenario - embedded nulls with a terminating double-null and junk after that.
b = new char[] { 'a', 'b', 'c', '\0', '1', '2', '3', '\0', '\0', 'a', 'b', 'c' };
Debug.Assert( Enumerable.SequenceEqual(new string[] { "abc", "123" }, DoubleNullToStringArray(ref b)));
// fringe scenario. missing double-null.
b = new char[] { 'a', 'b', 'c', '\0', '1', '2', '3', '4', '\0' };
Debug.Assert(Enumerable.SequenceEqual(new string[] { "abc", "1234" }, DoubleNullToStringArray(ref b)));
// common scenario.
b = new char[] { 'a', 'b', 'c', '\0', '1', '2', '3', '4', '\0', 'A', 'B', 'C', '\0' };
Debug.Assert(Enumerable.SequenceEqual(new string[] { "abc", "1234", "ABC" }, DoubleNullToStringArray(ref b)));
}
Revision: 23093
Updated Code
at January 29, 2010 17:35 by jimfred
Updated Code
/// <summary>
/// Determine the length of a double-null terminated string.
/// Example usage:
/// char [] buff = new char[];
/// // fill Buff with data calling an API.
/// string[] a = DoubleNullToStringArray(ref buff); // Find first double-null.
/// </summary>
/// <param name="arg">double-null terminated string</param>
/// <returns>array of strings</returns>
/// Gracefully handle fringe conditions: missing double-null, missing trailing single null,
private static string [] DoubleNullToStringArray(ref char[] arg)
{
// Search an array of bytes for a double-null.
int qty, j;
for ( qty = 0, j = 1; ; qty++, j++)
{
bool done = qty > (arg.Length - 1) || (arg[qty] == 0 && j < arg.Length && arg[j] == 0);
if (done)
{
break;
} // if
} // for
string b = new string(arg, 0, qty);
return b.Split(new char[] { '\0' }, 9, StringSplitOptions.RemoveEmptyEntries);
} // lengthDoubleNull
// test this function. Use Enumerable.SequenceEqual to deep-compare array of strings.
[Conditional("DEBUG")]
private static void lengthDoubleNullTest()
{
char[] b;
// fringe scenario. missing double-null.
b = new char[] { 'a', 'b', 'c' };
Debug.Assert( Enumerable.SequenceEqual(new string[] { "abc" }, DoubleNullToStringArray(ref b)));
// fringe scenario. missing double-null.
b = new char[] { 'a', 'b', 'c', '\0' };
Debug.Assert( Enumerable.SequenceEqual(new string[] { "abc" }, DoubleNullToStringArray(ref b)));
// fringe scenario. missing single-null.
b = new char[] { 'a', 'b', 'c', '\0', '\0', 'a', 'b', 'c' };
Debug.Assert( Enumerable.SequenceEqual(new string[] { "abc" }, DoubleNullToStringArray(ref b)));
// Most common scenario - embedded nulls with a terminating double-null and junk after that.
b = new char[] { 'a', 'b', 'c', '\0', '1', '2', '3', '\0', '\0', 'a', 'b', 'c' };
Debug.Assert( Enumerable.SequenceEqual(new string[] { "abc", "123" }, DoubleNullToStringArray(ref b)));
// fringe scenario. missing double-null.
b = new char[] { 'a', 'b', 'c', '\0', '1', '2', '3', '4', '\0' };
Debug.Assert(Enumerable.SequenceEqual(new string[] { "abc", "1234" }, DoubleNullToStringArray(ref b)));
// common scenario.
b = new char[] { 'a', 'b', 'c', '\0', '1', '2', '3', '4', '\0', 'A', 'B', 'C', '\0' };
Debug.Assert(Enumerable.SequenceEqual(new string[] { "abc", "1234", "ABC" }, DoubleNullToStringArray(ref b)));
}
Revision: 23092
Initial Code
Initial URL
Initial Description
Initial Title
Initial Tags
Initial Language
at January 29, 2010 17:32 by jimfred
Initial Code
/// <summary>
/// Determine the length of a double-null terminated string.
/// Example usage:
/// char [] buff = new char[];
/// // fill Buff with data calling an API.
/// string[] a = DoubleNullToStringArray(ref buff); // Find first double-null.
/// </summary>
/// <param name="arg">double-null terminated string</param>
/// <returns>array of strings</returns>
private static string [] DoubleNullToStringArray(ref char[] arg)
{
// Search an array of bytes for a double-null.
int qty, j;
for ( qty = 0, j = 1; ; qty++, j++)
{
bool done = qty > (arg.Length - 1) || (arg[qty] == 0 && j < arg.Length && arg[j] == 0);
if (done)
{
break;
} // if
} // for
string b = new string(arg, 0, qty);
return b.Split(new char[] { '\0' }, 9, StringSplitOptions.RemoveEmptyEntries);
} // lengthDoubleNull
// test this function. Use Enumerable.SequenceEqual to deep-compare array of strings.
[Conditional("DEBUG")]
private static void lengthDoubleNullTest()
{
char[] b;
// fringe scenario. missing double-null.
b = new char[] { 'a', 'b', 'c' };
Debug.Assert( Enumerable.SequenceEqual(new string[] { "abc" }, DoubleNullToStringArray(ref b)));
// fringe scenario. missing double-null.
b = new char[] { 'a', 'b', 'c', '\0' };
Debug.Assert( Enumerable.SequenceEqual(new string[] { "abc" }, DoubleNullToStringArray(ref b)));
// fringe scenario. missing single-null.
b = new char[] { 'a', 'b', 'c', '\0', '\0', 'a', 'b', 'c' };
Debug.Assert( Enumerable.SequenceEqual(new string[] { "abc" }, DoubleNullToStringArray(ref b)));
// Most common scenario - embedded nulls with a terminating double-null and junk after that.
b = new char[] { 'a', 'b', 'c', '\0', '1', '2', '3', '\0', '\0', 'a', 'b', 'c' };
Debug.Assert( Enumerable.SequenceEqual(new string[] { "abc", "123" }, DoubleNullToStringArray(ref b)));
// fringe scenario. missing double-null.
b = new char[] { 'a', 'b', 'c', '\0', '1', '2', '3', '4', '\0' };
Debug.Assert(Enumerable.SequenceEqual(new string[] { "abc", "1234" }, DoubleNullToStringArray(ref b)));
// common scenario.
b = new char[] { 'a', 'b', 'c', '\0', '1', '2', '3', '4', '\0', 'A', 'B', 'C', '\0' };
Debug.Assert(Enumerable.SequenceEqual(new string[] { "abc", "1234", "ABC" }, DoubleNullToStringArray(ref b)));
}
Initial URL
Initial Description
Double-null-terminated strings are sometimes referred to as multistrings - \r\nhttp://stackoverflow.com/questions/268899/how-do-you-convert-multistring-to-from-c-string-collection\r\n\r\nmultistrings used in...\r\nOPENFILENAME::lpstrFilter in common dialogs\r\nRegQueryStringValue\r\nChangeServiceConfig\r\n\r\nThis works somewhat...\r\nstring[] a2 = (new string(Buff)).TrimEnd(\'\\0\').Split(\'\\0\');\r\n...but includes junk after a double-null.
Initial Title
C#, convert a double-null-terminated string to an array of strings.
Initial Tags
Initial Language
C#