Advertisement
tolikpunkoff

Unpacking class (for SxGeo "Universal packing data" format)

Sep 23rd, 2018
465
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 14.52 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.Globalization;
  5.  
  6. namespace SxGeoReader
  7. {
  8.     public class SxGeoUnpack
  9.     {
  10.         private Dictionary<string, object> RecordData = null;
  11.         private Dictionary<string, Type> RecordTypes = null;
  12.         private Dictionary<string, string> SxTypeCodes = null;
  13.  
  14.         private Encoding StringsEncoding = null;
  15.  
  16.         public bool RevBO { get; set; }
  17.  
  18.         public SxGeoUnpack(string Format, SxGeoEncoding DBEncoding)
  19.         {
  20.             RevBO = !BitConverter.IsLittleEndian;
  21.            
  22.             RecordData = new Dictionary<string,object>();
  23.             RecordTypes = new Dictionary<string,Type>();
  24.             SxTypeCodes = new Dictionary<string,string>();
  25.  
  26.             //разбираем строку формата
  27.             string[] fields = Format.Split('/');      
  28.             foreach (string field in fields)
  29.             {
  30.                 string[] buf = field.Split(':');
  31.                 if (buf.Length < 2) break;
  32.                 string SxTypeCode = buf[0];
  33.                 string FieldName = buf[1];
  34.  
  35.                 //подгатавливаем Dictionary'и
  36.                 RecordData.Add(FieldName, null);
  37.                 SxTypeCodes.Add(FieldName, SxTypeCode);
  38.                 RecordTypes.Add(FieldName,SxTypeToType(SxTypeCode));
  39.             }
  40.  
  41.             switch (DBEncoding)
  42.             {
  43.                 case SxGeoEncoding.CP1251: StringsEncoding = Encoding.GetEncoding(1251); break;
  44.                 case SxGeoEncoding.UTF8: StringsEncoding = Encoding.UTF8; break;
  45.                 case SxGeoEncoding.Latin1: StringsEncoding = Encoding.GetEncoding(1252); break;
  46.             }
  47.         }
  48.        
  49.  
  50.         private static Type SxTypeToType(string SxTypeCode)
  51.         {
  52.             if (string.IsNullOrEmpty(SxTypeCode)) return null;
  53.            
  54.             //mediumint - такого типа в C# нет, приведем к int/uint
  55.             switch (SxTypeCode[0])
  56.             {
  57.                 case 't': return typeof(sbyte); //tinyint signed - 1 - > sbyte
  58.                 case 'T': return typeof(byte); //tinyint unsigned - 1 - > byte
  59.                 case 's': return typeof(short); //smallint signed - 2 - > short
  60.                 case 'S': return typeof(ushort); //smallint unsigned - 2 - > ushort
  61.                 case 'm': return typeof(int); //mediumint signed - 3 - > int
  62.                 case 'M': return typeof(uint); //mediumint unsigned - 3 - > uint
  63.                 case 'i': return typeof(int); //integer signed - 4 - > int
  64.                 case 'I': return typeof(uint); //integer unsigned - 4 - > uint
  65.                 case 'f': return typeof(float); //float - 4 - > float
  66.                 case 'd': return typeof(double); //double - 8 - > double
  67.                 case 'n':                       //number 16bit - 2
  68.                 case 'N': return typeof(double); //number 32bit - 4 - > float
  69.                 case 'c':                       //char - fixed size string
  70.                 case 'b': return typeof(string); //blob - string with \0 end
  71.             }
  72.  
  73.             return null;
  74.         }
  75.        
  76.         public Dictionary<string, object> Unpack(byte[] Record, out int RealLength)
  77.         {
  78.             int Counter = 0;            
  79.             object buf = null;
  80.  
  81.             //перебираем сгенерированный ранее словарь с данными
  82.             foreach (string SxRecordName in SxTypeCodes.Keys)
  83.             {
  84.                 //вытаскиваем код типа данных
  85.                 string SxTypeCode = SxTypeCodes[SxRecordName];
  86.                
  87.                 //вытаскиваем данные в object buf
  88.                 switch (SxTypeCode[0])
  89.                 {
  90.                     case 't':
  91.                         {
  92.                             buf = GetTinuintSigned(Record, Counter);
  93.                             Counter++;
  94.                         }; break;
  95.                     case 'T':
  96.                         {
  97.                             buf = GetTinuintUnsigned(Record, Counter);
  98.                             Counter++;
  99.                         }; break;
  100.                     case 's':
  101.                         {
  102.                             buf = GetSmallintSigned(Record, Counter);
  103.                             Counter+=2;
  104.                         }; break;
  105.                     case 'S':
  106.                         {
  107.                             buf = GetSmallintUnsigned(Record, Counter);
  108.                             Counter+=2;
  109.                         }; break;
  110.                     case 'm':
  111.                         {
  112.                             buf = GetMediumintSigned(Record, Counter);
  113.                             Counter += 3;
  114.                         }; break;
  115.                     case 'M':
  116.                         {
  117.                             buf = GetMediumintUnsigned(Record, Counter);
  118.                             Counter += 3;
  119.                         }; break;
  120.                     case 'i':
  121.                         {
  122.                             buf = GetIntSigned(Record, Counter);
  123.                             Counter += 4;
  124.                         }; break;
  125.                     case 'I':
  126.                         {
  127.                             buf = GetIntUnsigned(Record, Counter);
  128.                             Counter += 4;
  129.                         }; break;
  130.                     case 'f':
  131.                         {
  132.                             buf = GetFloat(Record, Counter);
  133.                             Counter += 4;
  134.                         }; break;
  135.                     case 'd':
  136.                         {
  137.                             buf = GetDouble(Record, Counter);
  138.                             Counter += 8;
  139.                         }; break;
  140.                     case 'n':
  141.                         {
  142.                             string signs = SxTypeCode.Substring(1);
  143.                             int isigns = Convert.ToInt32(signs);
  144.                             buf = GetN16(Record, Counter, isigns);
  145.                             Counter += 2;
  146.                         }; break;
  147.                     case 'N':
  148.                         {
  149.                             string signs = SxTypeCode.Substring(1);
  150.                             int isigns = Convert.ToInt32(signs);
  151.                             buf = GetN32(Record, Counter, isigns);
  152.                             Counter += 4;
  153.                         }; break;
  154.                     case 'c':
  155.                         {
  156.                             int length = Convert.ToInt32(SxTypeCode.Substring(1));
  157.                             buf = GetFixedString(Record, Counter, length);
  158.                             Counter += length;
  159.                         }; break;
  160.                     case 'b':
  161.                         {
  162.                             string Result = "";
  163.                             Counter = GetBlob(Record, Counter ,out Result);
  164.                             buf = Result;
  165.                         }; break;
  166.                     default:
  167.                         {
  168.                             buf = null;
  169.                         }; break;
  170.                 }
  171.  
  172.                 //записываем полученный объект в соотв. место RecordData
  173.                 RecordData[SxRecordName] = buf;
  174.             }
  175.  
  176.             RealLength = Counter;
  177.             return RecordData;
  178.         }
  179.        
  180.         public Dictionary<string, object> Unpack(byte[] Record)
  181.         {
  182.             int tmp = 0;
  183.             Unpack(Record, out tmp);
  184.             return RecordData;
  185.         }
  186.  
  187.         private sbyte GetTinuintSigned(byte[] DataArray, int StartPosition)
  188.         {
  189.             if (StartPosition >= DataArray.Length)
  190.             {
  191.                 return 0;
  192.             }
  193.             else return (sbyte)DataArray[StartPosition];
  194.         }
  195.  
  196.         private byte GetTinuintUnsigned(byte[] DataArray, int StartPosition)
  197.         {
  198.             if (StartPosition >= DataArray.Length)
  199.             {
  200.                 return 0;
  201.             }
  202.             else return DataArray[StartPosition];
  203.         }
  204.  
  205.         private short GetSmallintSigned(byte[] DataArray, int StartPosition)
  206.         {
  207.             if (StartPosition >= DataArray.Length + 1)
  208.             {
  209.                 return 0;
  210.             }
  211.  
  212.             byte[] buf = new byte[2];
  213.             Array.Copy(DataArray, StartPosition, buf, 0, 2);
  214.             if (RevBO)
  215.             {
  216.                 Array.Reverse(buf);
  217.             }
  218.  
  219.             return BitConverter.ToInt16(buf,0);
  220.         }
  221.  
  222.         private ushort GetSmallintUnsigned(byte[] DataArray, int StartPosition)
  223.         {
  224.             if (StartPosition >= DataArray.Length + 1)
  225.             {
  226.                 return 0;
  227.             }
  228.  
  229.             byte[] buf = new byte[2];
  230.             Array.Copy(DataArray, StartPosition, buf, 0, 2);
  231.             if (RevBO)
  232.             {
  233.                 Array.Reverse(buf);
  234.             }
  235.  
  236.             return BitConverter.ToUInt16(buf, 0);
  237.         }
  238.  
  239.        
  240.         private int GetMediumintSigned (byte[] DataArray, int StartPosition)
  241.         {
  242.             if (StartPosition >= DataArray.Length + 2)
  243.             {
  244.                 return 0;
  245.             }
  246.  
  247.             byte[] buf = new byte[4];
  248.  
  249.             Array.Copy(DataArray, StartPosition, buf, 0, 3);
  250.  
  251.             if (RevBO)
  252.             {
  253.                 Array.Copy(DataArray, StartPosition, buf, 1, 3);
  254.                 Array.Reverse(buf);
  255.             }
  256.             else
  257.             {
  258.                 Array.Copy(DataArray, StartPosition, buf, 0, 3);
  259.             }
  260.  
  261.             return BitConverter.ToInt32(buf, 0);
  262.         }
  263.  
  264.         private uint GetMediumintUnsigned(byte[] DataArray, int StartPosition)
  265.         {
  266.             if (StartPosition >= DataArray.Length + 2)
  267.             {
  268.                 return 0;
  269.             }
  270.  
  271.             byte[] buf = new byte[4];
  272.  
  273.  
  274.             if (RevBO)
  275.             {
  276.                 Array.Copy(DataArray, StartPosition, buf, 1, 3);
  277.                 Array.Reverse(buf);
  278.             }
  279.             else
  280.             {
  281.                 Array.Copy(DataArray, StartPosition, buf, 0, 3);
  282.             }
  283.  
  284.             return BitConverter.ToUInt32(buf, 0);
  285.         }
  286.  
  287.         private int GetIntSigned(byte[] DataArray, int StartPosition)
  288.         {
  289.             if (StartPosition >= DataArray.Length + 3)
  290.             {
  291.                 return 0;
  292.             }
  293.  
  294.             byte[] buf = new byte[4];
  295.  
  296.             Array.Copy(DataArray, StartPosition, buf, 0, 4);
  297.  
  298.             if (RevBO)
  299.             {
  300.                 Array.Reverse(buf);
  301.             }
  302.  
  303.             return BitConverter.ToInt32(buf, 0);
  304.         }
  305.  
  306.         private uint GetIntUnsigned(byte[] DataArray, int StartPosition)
  307.         {
  308.             if (StartPosition >= DataArray.Length + 3)
  309.             {
  310.                 return 0;
  311.             }
  312.  
  313.             byte[] buf = new byte[4];
  314.  
  315.             Array.Copy(DataArray, StartPosition, buf, 0, 4);
  316.  
  317.             if (RevBO)
  318.             {
  319.                 Array.Reverse(buf);
  320.             }
  321.  
  322.             return BitConverter.ToUInt32(buf, 0);
  323.         }
  324.  
  325.         private float GetFloat(byte[] DataArray, int StartPosition)
  326.         {
  327.             if (StartPosition >= DataArray.Length + 3)
  328.             {
  329.                 return 0;
  330.             }
  331.  
  332.             byte[] buf = new byte[4];
  333.  
  334.             Array.Copy(DataArray, StartPosition, buf, 0, 4);
  335.  
  336.             if (RevBO)
  337.             {
  338.                 Array.Reverse(buf);
  339.             }
  340.  
  341.             return BitConverter.ToSingle(buf, 0);
  342.         }
  343.  
  344.         private double GetDouble(byte[] DataArray, int StartPosition)
  345.         {
  346.             if (StartPosition >= DataArray.Length + 7)
  347.             {
  348.                 return 0;
  349.             }
  350.  
  351.             byte[] buf = new byte[8];
  352.  
  353.             Array.Copy(DataArray, StartPosition, buf, 0, 8);
  354.  
  355.             if (RevBO)
  356.             {
  357.                 Array.Reverse(buf);
  358.             }
  359.  
  360.             return BitConverter.ToDouble(buf, 0);
  361.         }
  362.  
  363.         private double GetN16(byte[] DataArray, int StartPosition, int Signs)
  364.         {
  365.             short tmpShort = GetSmallintSigned(DataArray, StartPosition);
  366.             return tmpShort / Math.Pow(10, Signs);            
  367.         }
  368.  
  369.         private double GetN32(byte[] DataArray, int StartPosition, int Signs)
  370.         {
  371.             int tmpInt = GetIntSigned(DataArray, StartPosition);
  372.             return tmpInt / Math.Pow(10, Signs);        
  373.         }
  374.  
  375.         private string GetFixedString(byte[] DataArray, int StartPosition, int Count)
  376.         {
  377.             if (StartPosition >= DataArray.Length + Count - 1)
  378.             {
  379.                 return null;
  380.             }
  381.            
  382.             //кириллица UTF8 для строк ограниченной длины не поддерживается
  383.             //делаем буфер
  384.             byte[] buf = new byte[Count];
  385.  
  386.             //копируем нужное количество байт в буфер
  387.             Array.Copy(DataArray, StartPosition, buf, 0, Count);
  388.  
  389.             return StringsEncoding.GetString(buf);            
  390.         }
  391.  
  392.         private int GetBlob(byte[] DataArray, int StartPosition, out string Result)
  393.         {            
  394.             int i = StartPosition;            
  395.             List<byte> tmpl = new List<byte>();
  396.             while (DataArray[i] != '\0')
  397.             {                
  398.                 tmpl.Add(DataArray[i]);
  399.                 i++;                
  400.             }
  401.             i++;
  402.             byte[] buf = tmpl.ToArray();
  403.             Result = StringsEncoding.GetString(buf);
  404.             return i;
  405.         }        
  406.  
  407.         //--------------------------------
  408.         public Dictionary<string, Type> GetRecordTypes()
  409.         {
  410.             return RecordTypes;
  411.         }
  412.         public Dictionary<string, string> GetSxTypeCodes()
  413.         {
  414.             return SxTypeCodes;
  415.         }
  416.         public static Dictionary<string, Type> GetRecordTypes(string Format)
  417.         {
  418.             Dictionary<string, Type> tmpTypes = new Dictionary<string, Type>();
  419.             string[] fields = Format.Split('/');
  420.             foreach (string field in fields)
  421.             {
  422.                 string[] buf = field.Split(':');
  423.                 if (buf.Length < 2) break;
  424.                 string SxTypeCode = buf[0];
  425.                 string FieldName = buf[1];
  426.  
  427.                 //формируем Dictionary
  428.                 tmpTypes.Add(FieldName, SxTypeToType(SxTypeCode));
  429.             }
  430.             return tmpTypes;
  431.         }
  432.  
  433.     }
  434. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement