Advertisement
aaaaaa123456789

IntegerSerializer C# implementation (uses UnlimitedMatrix)

Jul 16th, 2015
239
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2.    This code is hereby released to the public domain.
  3.    ~aaaaaa123456789, 2015-07-16
  4. */
  5.  
  6. using System;
  7. using System.Collections.Generic;
  8.  
  9. public static class IntegerSerializer<T> {
  10.   public static byte[] serialize (UnlimitedMatrix<T> data) {
  11.     List<byte[]> contents = new List<byte[]>();
  12.     ulong size = 0;
  13.     long value;
  14.     long current_value = 0;
  15.     List<long[]> current_stack = new List<long[]>();
  16.     long[] previous = new long[] {64, 64};
  17.     foreach (long[] coords in data) {
  18.       value = convert_from(data[coords[0], coords[1]]);
  19.       if (value == current_value) {
  20.         current_stack.Add(coords);
  21.         continue;
  22.       }
  23.       if (current_value != 0) write_stack(contents, ref size, current_stack, current_value, ref previous);
  24.       current_value = value;
  25.       current_stack = new List<long[]>();
  26.       current_stack.Add(coords);
  27.     }
  28.     if (current_value != 0) write_stack(contents, ref size, current_stack, current_value, ref previous);
  29.     current_stack = null;
  30.     byte[] result = new byte[size + 1];
  31.     ulong current, pointer = 0;
  32.     for (current = 0; current < (ulong) contents.Count; current ++) {
  33.       Array.Copy(contents[(int) current], 0L, result, (long) pointer, contents[(int) current].LongLength);
  34.       pointer += (ulong) contents[(int) current].LongLength;
  35.     }
  36.     result[pointer] = 0;
  37.     return result;
  38.   }
  39.  
  40.  
  41.   private static void write_stack (List<byte[]> contents, ref ulong size, List<long[]> stack, long value, ref long[] prev) {
  42.     if (stack.Count < 4)
  43.       write_stack_single(contents, ref size, stack, value, ref prev);
  44.     else
  45.       write_stack_run(contents, ref size, stack, value, ref prev);
  46.   }
  47.  
  48.   private static void write_stack_single (List<byte[]> contents, ref ulong size, List<long[]> stack, long value, ref long[] prev) {
  49.     byte[] serialized_value = encode_number(value, false);
  50.     foreach(long[] coords in stack) {
  51.       push(contents, ref size, serialized_value);
  52.       push_coordinates(contents, ref size, coords, ref prev);
  53.     }
  54.   }
  55.  
  56.   private static void write_stack_run (List<byte[]> contents, ref ulong size, List<long[]> stack, long value, ref long[] prev) {
  57.     push(contents, ref size, encode_number(value, true));
  58.     foreach (long[] coords in stack) push_coordinates(contents, ref size, coords, ref prev);
  59.     push(contents, ref size, new byte[] {0x40, 0x40});
  60.   }
  61.  
  62.   private static void push_coordinates (List<byte[]> contents, ref ulong size, long[] coordinates, ref long[] previous) {
  63.     push(contents, ref size, create_coordinate(coordinates[0], ref previous[0]));
  64.     push(contents, ref size, create_coordinate(coordinates[1], ref previous[1]));
  65.   }
  66.  
  67.   private static byte[] create_coordinate (long coordinate, ref long reference) {
  68.     byte[] absolute = encode_number(coordinate);
  69.     byte[] relative = encode_number(coordinate, reference);
  70.     reference = coordinate;
  71.     if (relative.Length < absolute.Length) return relative;
  72.     return absolute;
  73.   }
  74.  
  75.   private static void push (List<byte[]> contents, ref ulong size, byte[] item) {
  76.     contents.Add(item);
  77.     size += (ulong) item.LongLength;
  78.   }
  79.  
  80.   public static UnlimitedMatrix<T> unserialize (byte[] data, ref ulong pointer) {
  81.     UnlimitedMatrix<T> result = new UnlimitedMatrix<T>();
  82.     long[] previous_coordinates = new long[] {64, 64};
  83.     while (data[pointer] != 0)
  84.       if ((data[pointer] & 0x40) != 0)
  85.         read_run(result, data, ref pointer, ref previous_coordinates);
  86.       else
  87.         read_single(result, data, ref pointer, ref previous_coordinates);
  88.     pointer ++;
  89.     return result;
  90.   }
  91.  
  92.   private static void read_single (UnlimitedMatrix<T> dst, byte[] src, ref ulong pointer, ref long[] previous) {
  93.     bool kind;
  94.     int advance;
  95.     long value = decode_number(src, pointer, out kind, out advance);
  96.     if (kind) throw new InvalidOperationException();
  97.     pointer += (ulong) advance;
  98.     long[] coordinates = read_coordinates(src, ref pointer, ref previous);
  99.     dst[coordinates[0], coordinates[1]] = convert_to(value);
  100.   }
  101.  
  102.   private static void read_run (UnlimitedMatrix<T> dst, byte[] src, ref ulong pointer, ref long[] previous) {
  103.     bool kind;
  104.     int advance;
  105.     long value = decode_number(src, pointer, out kind, out advance);
  106.     T converted = convert_to(value);
  107.     if (!kind) throw new InvalidOperationException();
  108.     pointer += (ulong) advance;
  109.     long[] coordinates;
  110.     while ((src[pointer] != 0x40) || (src[pointer + 1] != 0x40)) {
  111.       coordinates = read_coordinates(src, ref pointer, ref previous);
  112.       dst[coordinates[0], coordinates[1]] = converted;
  113.     }
  114.     pointer += 2;
  115.   }
  116.  
  117.   private static long[] read_coordinates (byte[] src, ref ulong pointer, ref long[] previous) {
  118.     long[] result = new long[2];
  119.     result[0] = read_coordinate(src, ref pointer, ref previous[0]);
  120.     result[1] = read_coordinate(src, ref pointer, ref previous[1]);
  121.     return result;
  122.   }
  123.  
  124.   private static long read_coordinate (byte[] src, ref ulong pointer, ref long previous) {
  125.     bool relative;
  126.     int advance;
  127.     long coordinate = decode_number(src, pointer, out relative, out advance);
  128.     pointer += (ulong) advance;
  129.     if (relative) coordinate += previous;
  130.     previous = coordinate;
  131.     return coordinate;
  132.   }
  133.  
  134.   public static UnlimitedMatrix<T> unserialize (byte[] data, ulong pointer) {
  135.     return unserialize(data, ref pointer);
  136.   }
  137.  
  138.   public static UnlimitedMatrix<T> unserialize (byte[] data) {
  139.     ulong pointer = 0;
  140.     return unserialize(data, ref pointer);
  141.   }
  142.  
  143.   private static byte[] encode_number (long number, bool kind) {
  144.     bool sign = number < 0;
  145.     if (sign) number = ~number;
  146.     int length;
  147.     if (number < 0x20L)
  148.       length = 1;
  149.     else if (number < 0x1000L)
  150.       length = 2;
  151.     else if (number < 0x80000L)
  152.       length = 3;
  153.     else if (number < 0x4000000L)
  154.       length = 4;
  155.     else if (number < 0x200000000L)
  156.       length = 5;
  157.     else if (number < 0x10000000000L)
  158.       length = 6;
  159.     else if (number < 0x800000000000L)
  160.       length = 7;
  161.     else
  162.       length = 9;
  163.     byte[] result = new byte[length];
  164.     long available_bits = 0x887777775L;
  165.     int current, bits;
  166.     for (current = 0; current < length; current ++) {
  167.       bits = (int) (available_bits & 15);
  168.       available_bits >>= 4;
  169.       result[current] = (byte) ((((bits == 8) || (length == (current + 1))) ? 0 : 0x80) | ((byte) number & ((1 << bits) - 1)));
  170.       number >>= bits;
  171.     }
  172.     if (kind) result[0] |= 0x40;
  173.     if (sign) result[0] |= 0x20;
  174.     return result;
  175.   }
  176.  
  177.   private static byte[] encode_number (long number, long reference) {
  178.     return encode_number(number - reference, true);
  179.   }
  180.  
  181.   private static byte[] encode_number (long number) {
  182.     return encode_number(number, false);
  183.   }
  184.  
  185.   private static long decode_number (byte[] data, ulong position, out bool kind, out int length) {
  186.     for (length = 0; length < 7; length ++) if ((data[position + (ulong) length] & 0x80) == 0) break;
  187.     if (length == 7)
  188.       length = 9;
  189.     else
  190.       length ++;
  191.     if ((ulong) data.Length < (position + (ulong) length)) throw new IndexOutOfRangeException();
  192.     long available_bits = 0x887777775L;
  193.     int current, bits, shift_state = 0;
  194.     long result = 0;
  195.     for (current = 0; current < length; current ++) {
  196.       bits = (int) (available_bits & 15);
  197.       available_bits >>= 4;
  198.       result |= (((long) data[position + (ulong) current]) & ((1L << bits) - 1)) << shift_state;
  199.       shift_state += bits;
  200.     }
  201.     kind = (data[position] & 0x40) != 0;
  202.     if ((data[position] & 0x20) != 0) result = ~result;
  203.     return result;
  204.   }
  205.  
  206.   private static long decode_number (byte[] data, ulong position, long reference, out int length) {
  207.     bool relative;
  208.     long rv = decode_number(data, position, out relative, out length);
  209.     if (relative) rv += reference;
  210.     return rv;
  211.   }
  212.  
  213.   private static long convert_from (T value) {
  214.     return (long) Convert.ChangeType(value, typeof(long));
  215.   }
  216.  
  217.   private static T convert_to (long value) {
  218.     return (T) Convert.ChangeType(value, typeof(T));
  219.   }
  220. }
Advertisement
RAW Paste Data Copied
Advertisement