public static bool Unpack(SpStream input, SpStream output) { int src_size = input.Tail; int src_offset = input.Offset; byte[] src = input.Buffer; while (src_offset < src_size) { byte header = src[src_offset]; src_offset++; if (header == 0xff) { if (src_offset > src_size) { return(false); } int n = (src[src_offset] + 1) * 8; if (src_size - src_offset < n + 1) { return(false); } src_offset++; output.Write(src, src_offset, n); src_offset += n; } else { for (int i = 0; i < 8; i++) { int nz = (header >> i) & 1; if (nz != 0) { if (src_offset > src_size) { return(false); } output.Write(src[src_offset]); src_offset++; } else { output.Write((byte)0); } } } } return(output.IsOverflow() == false); }
public static void WriteFF(byte[] src, int src_offset, SpStream output, int n, int correctPos) { int align8_n = (n + 7) & (~7); output.Write((byte)0xff); output.Write((byte)(align8_n / 8 - 1)); output.Write(src, src_offset, n); for (int i = 0; i < align8_n - n; i++) { output.Write((byte)0); } output.CorrectLength(correctPos); }
private static int PackSeg(byte[] src, int src_offset, SpStream output, int n) { byte header = 0; int notzero = 0; int dest_begin = output.Position; output.Position++; for (int i = 0; i < 8; i++) { if (src[src_offset + i] != 0) { notzero++; header |= (byte)(1 << i); output.Write(src[src_offset + i]); } } if ((notzero == 7 || notzero == 6) && n > 0) { notzero = 8; } if (notzero == 8) { if (n > 0) { return(8); } else { return(10); } } int dest_end = output.Position; output.Position = dest_begin; output.Write(header); output.Position = dest_end; return(notzero + 1); }
public static bool Pack(SpStream input, SpStream output) { int src_size = input.Length; if (src_size % 8 != 0) { int new_size = ((src_size + 7) / 8) * 8; if (input.Capacity < new_size) { SpStream new_input = new SpStream(new_size); Array.Copy(input.Buffer, input.Offset, new_input.Buffer, new_input.Offset, input.Length); new_input.Position = new_input.Offset; input = new_input; src_size = new_size; } else { int pos = input.Position; input.Position = input.Tail; for (int i = src_size; i < new_size; i++) { input.Write((byte)0); } input.Position = pos; } } int src_start = input.Offset; int src_offset = input.Offset; byte[] src = input.Buffer; int ff_n = 0; int ff_src_start = 0; int ff_dest_start = 0; for (; src_offset < src_size; src_offset += 8) { int pos = output.Position; int n = PackSeg(src, src_offset, output, ff_n); if (n == 10) { ff_src_start = src_offset; ff_dest_start = pos; ff_n = 1; } else if (n == 8 && ff_n > 0) { ff_n++; if (ff_n == 256) { output.Position = ff_dest_start; WriteFF(src, ff_src_start, output, 256 * 8, n); ff_n = 0; } } else { if (ff_n > 0) { output.Position = ff_dest_start; WriteFF(src, ff_src_start, output, ff_n * 8, n); ff_n = 0; } } output.Position = pos + n; } if (ff_n == 1) { output.Position = ff_dest_start; WriteFF(src, ff_src_start, output, 8, 0); } else if (ff_n > 1) { output.Position = ff_dest_start; WriteFF(src, ff_src_start, output, src_size - (ff_src_start - src_start), 0); } return(output.IsOverflow() == false); }
private bool EncodeInternal(SpType type, SpObject obj) { if (mStream == null || type == null || obj == null) { return(false); } // buildin type decoding should not be here if (mTypeManager.IsBuildinType(type)) { return(false); } int begin = mStream.Position; // fn. will be update later short fn = 0; mStream.Write(fn); List <KeyValuePair <SpObject, SpField> > objs = new List <KeyValuePair <SpObject, SpField> >(); int current_tag = -1; Dictionary <int, SpField> .ValueCollection.Enumerator en = type.Fields.Values.GetEnumerator(); while (en.MoveNext()) { SpField f = en.Current; if (f == null) { return(false); } SpObject o = obj[f.Name]; if (o == null || IsTypeMatch(f, o) == false) { continue; } if (f.Tag <= current_tag) { return(false); } if (f.Tag - current_tag > 1) { mStream.Write((short)(2 * (f.Tag - current_tag - 1) - 1)); fn++; } bool standalone = true; if (f.IsTable == false) { if (f.Type == mTypeManager.Boolean) { int value = o.AsBoolean() ? 1 : 0; mStream.Write((short)((value + 1) * 2)); standalone = false; } else if (f.Type == mTypeManager.Integer) { int value = o.AsInt(); if (value >= 0 && value < 0x7fff) { mStream.Write((short)((value + 1) * 2)); standalone = false; } } } if (standalone) { objs.Add(new KeyValuePair <SpObject, SpField>(o, f)); mStream.Write((short)0); } fn++; current_tag = f.Tag; } List <KeyValuePair <SpObject, SpField> > .Enumerator e = objs.GetEnumerator(); while (e.MoveNext()) { KeyValuePair <SpObject, SpField> entry = e.Current; if (entry.Value.IsTable) { int array_begin = mStream.Position; int size = 0; mStream.Write(size); if (entry.Value.Type == mTypeManager.Integer) { byte len = 4; Dictionary <object, SpObject> .Enumerator enumerator = entry.Key.AsTable().GetEnumerator(); while (enumerator.MoveNext()) { SpObject o = enumerator.Current.Value; if (o.IsLong()) { len = 8; break; } } mStream.Write(len); enumerator = entry.Key.AsTable().GetEnumerator(); while (enumerator.MoveNext()) { SpObject o = enumerator.Current.Value; if (len == 4) { mStream.Write(o.AsInt()); } else { mStream.Write(o.AsLong()); } } } else if (entry.Value.Type == mTypeManager.Boolean) { Dictionary <object, SpObject> .Enumerator enumerator = entry.Key.AsTable().GetEnumerator(); while (enumerator.MoveNext()) { SpObject o = enumerator.Current.Value; mStream.Write((byte)(o.AsBoolean() ? 1 : 0)); } } else if (entry.Value.Type == mTypeManager.String) { Dictionary <object, SpObject> .Enumerator enumerator = entry.Key.AsTable().GetEnumerator(); while (enumerator.MoveNext()) { SpObject o = enumerator.Current.Value; byte[] b = Encoding.UTF8.GetBytes(o.AsString()); mStream.Write(b.Length); mStream.Write(b); } } else { Dictionary <object, SpObject> .Enumerator enumerator = entry.Key.AsTable().GetEnumerator(); while (enumerator.MoveNext()) { SpObject o = enumerator.Current.Value; int obj_begin = mStream.Position; int obj_size = 0; mStream.Write(obj_size); if (EncodeInternal(entry.Value.Type, o) == false) { return(false); } int obj_end = mStream.Position; obj_size = (int)(obj_end - obj_begin - 4); mStream.Position = obj_begin; mStream.Write(obj_size); mStream.Position = obj_end; } } int array_end = mStream.Position; size = (int)(array_end - array_begin - 4); mStream.Position = array_begin; mStream.Write(size); mStream.Position = array_end; } else { if (entry.Key.IsString()) { byte[] b = Encoding.UTF8.GetBytes(entry.Key.AsString()); mStream.Write(b.Length); mStream.Write(b); } else if (entry.Key.IsInt()) { mStream.Write((int)4); mStream.Write(entry.Key.AsInt()); } else if (entry.Key.IsLong()) { mStream.Write((int)8); mStream.Write(entry.Key.AsLong()); } else if (entry.Key.IsBoolean()) { // boolean should not be here return(false); } else { int obj_begin = mStream.Position; int obj_size = 0; mStream.Write(obj_size); if (EncodeInternal(entry.Value.Type, entry.Key) == false) { return(false); } int obj_end = mStream.Position; obj_size = (int)(obj_end - obj_begin - 4); mStream.Position = obj_begin; mStream.Write(obj_size); mStream.Position = obj_end; } } } int end = mStream.Position; mStream.Position = begin; mStream.Write(fn); mStream.Position = end; return(true); }