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#