public static string ReadString(MemBlock b, int offset, out int bytelength) { int null_idx = b.IndexOf(0, offset); int raw_length = null_idx - offset; bytelength = raw_length + 1; //One for the null Encoding e; /* * Benchmarks of mono show this to be about twice as fast as just * using UTF8. That really means UTF8 could be optimized in mono */ if( b.IsAscii(offset, raw_length) ) { e = Encoding.ASCII; } else { e = Encoding.UTF8; } return b.GetString(e, offset, raw_length); }
/** * Parse the PType starting at mb, and return all of mb <b>after</b> * the PType. */ public static PType Parse(MemBlock mb, out MemBlock rest) { PType result = null; byte fb = mb[0]; bool is_v_n = IsValidNumeric( (int)fb ); /** * Since ptypes must be valid UTF8 strings, * if the second byte is null, the first byte is an ascii character * and hence has a value less than ASCII_UPPER_BOUND */ bool store_in_tbl = ( is_v_n || (mb[1] == 0) ); if( store_in_tbl ) { //This is stored in our table: result = _table[ fb ]; if( result != null ) { if( is_v_n ) { //There is no null rest = mb.Slice(1); } else { //Skip the null rest = mb.Slice(2); } return result; } } //Otherwise we have to make it: MemBlock raw_data = null; result = new PType(); if( is_v_n ) { /* * Don't set the raw_data since it is only one byte and we may not need * it */ rest = mb.Slice(1); result._type_num = (int)fb; } else { int null_pos = mb.IndexOf(0); if( null_pos > 0 ) { //Include the "null", but make a copy so we don't keep some data in //scope for ever raw_data = MemBlock.Copy( (ICopyable)mb.Slice(0, null_pos + 1) ); rest = mb.Slice(null_pos + 1); } else { //There is no terminating Null, panic!! throw new ParseException( System.String.Format("PType not null terminated: {0}", mb.ToBase16String())); } result._type_num = -2; result._raw_data = raw_data; } if( store_in_tbl ) { //Make sure we don't have to create an object like this again _table[ fb ] = result; } return result; }