You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

619 lines
20 KiB

using System;
using System.Text;
using System.Linq;
using System.Collections.Generic;
using LitJson;
using Newtonsoft.Json.Linq;
namespace Sog
{
public class TabBinFile
{
private string FileName;
private string[] Titles;
private string[] Types;
private Dictionary<string, int> m_titleIndex;
private int LineLength;
private int LineCount;
private int[] LinePosList;
private int[] ColPosList;
private int ColCount;
private byte[] m_bodyBlock; // 除去头部的两行的 content;
private List<byte> m_stringBlock;
private string m_splitFlag = "*$*";
private int headerLength;
private int CurrentColIndex = 0;
public int CurrentLine { get; private set; }
public TabBinFile(string strFileName, byte[] content)
{
FileName = strFileName;
GetHeader(content);
int bodyLen = LineCount * LineLength;
m_bodyBlock = content.Skip(4 + headerLength).Take(bodyLen).ToArray();
m_stringBlock = content.Skip(4 + headerLength + bodyLen).Take(content.Length - (4 + headerLength + bodyLen))
.ToArray().ToList();
ColCount = Titles.Length;
SetPos();
Begin();
}
public void Begin()
{
CurrentLine = -1;
}
public bool Next()
{
CurrentLine++;
if (CurrentLine >= LineCount)
return false;
return true;
}
public void SetCurrentLine(int currentLine)
{
CurrentLine = currentLine;
}
public void SetCurrentCol(int currentCol)
{
CurrentColIndex = currentCol;
}
private void SetPos()
{
int position = 0;
int flag = 0;
if (ColPosList == null)
{
ColPosList = new int[Titles.Length];
}
foreach (var item in Types)
{
ColPosList[flag] = position;
switch (item)
{
case "int":
case "uint":
case "uint_key":
case "int_group":
case "int_key":
position += 4;
flag++;
break;
case "long":
position += 8;
flag++;
break;
case "string":
case "json":
case "array":
case "string_lan":
case "string_key":
// 先长度后位置
position += 4;
position += 4;
flag++;
break;
default:
break;
}
}
if (LinePosList == null)
{
LinePosList = new int[LineCount];
}
for (int i = 0; i < LineCount; i++)
{
LinePosList[i] = i * LineLength;
}
}
private void GetHeader(byte[] content)
{
int titlesLen = (int)((content[0] & 0xFF)
| ((content[1] & 0xFF) << 8)
| ((content[2] & 0xFF) << 16)
| ((content[3] & 0xFF) << 24));
headerLength += 4;
byte[] titles = content.Skip(headerLength).Take(titlesLen).ToArray();
headerLength += titlesLen;
string strTitle = Encoding.UTF8.GetString(titles);
Titles = strTitle.Split(m_splitFlag.ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
if (m_titleIndex == null)
{
m_titleIndex = new Dictionary<string, int>();
for (int i = 0; i < Titles.Count(); i++)
{
m_titleIndex.Add(Titles[i], i);
}
}
int typesLen = (int)((content[headerLength] & 0xFF)
| ((content[headerLength + 1] & 0xFF) << 8)
| ((content[headerLength + 2] & 0xFF) << 16)
| ((content[headerLength + 3] & 0xFF) << 24));
headerLength += 4;
byte[] types = content.Skip(headerLength).Take(typesLen).ToArray();
headerLength += typesLen;
string strTypes = Encoding.UTF8.GetString(types);
Types = strTypes.Split(m_splitFlag.ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
LineLength = (int)((content[headerLength] & 0xFF)
| ((content[headerLength + 1] & 0xFF) << 8)
| ((content[headerLength + 2] & 0xFF) << 16)
| ((content[headerLength + 3] & 0xFF) << 24));
headerLength += 4;
LineCount = (int)((content[headerLength] & 0xFF)
| ((content[headerLength + 1] & 0xFF) << 8)
| ((content[headerLength + 2] & 0xFF) << 16)
| ((content[headerLength + 3] & 0xFF) << 24));
}
public uint GetuintByIndex(string key = null)
{
int colIndex = CurrentColIndex;
if (key != null)
{
if (!m_titleIndex.ContainsKey(key))
{
return 0;
}
colIndex = m_titleIndex[key];
}
int valuePos = ColPosList[colIndex] + LinePosList[CurrentLine];
if (CurrentColIndex >= ColCount - 1)
{
CurrentColIndex = 0;
}
else
{
CurrentColIndex++;
}
return (uint)((m_bodyBlock[valuePos] & 0xFF)
| ((m_bodyBlock[valuePos + 1] & 0xFF) << 8)
| ((m_bodyBlock[valuePos + 2] & 0xFF) << 16)
| ((m_bodyBlock[valuePos + 3] & 0xFF) << 24));
}
public int GetintByIndex(string key = null)
{
int colIndex = CurrentColIndex;
if (key != null)
{
if (!m_titleIndex.ContainsKey(key))
{
return 0;
}
colIndex = m_titleIndex[key];
}
int valuePos = ColPosList[colIndex] + LinePosList[CurrentLine];
if (CurrentColIndex >= ColCount - 1)
{
CurrentColIndex = 0;
}
else
{
CurrentColIndex++;
}
return (int)((m_bodyBlock[valuePos] & 0xFF)
| ((m_bodyBlock[valuePos + 1] & 0xFF) << 8)
| ((m_bodyBlock[valuePos + 2] & 0xFF) << 16)
| ((m_bodyBlock[valuePos + 3] & 0xFF) << 24));
}
public long GetlongByIndex(string key = null)
{
int colIndex = CurrentColIndex;
if (key != null)
{
if (!m_titleIndex.ContainsKey(key))
{
return 0;
}
colIndex = m_titleIndex[key];
}
int valuePos = ColPosList[colIndex] + LinePosList[CurrentLine];
if (CurrentColIndex >= ColCount - 1)
{
CurrentColIndex = 0;
}
else
{
CurrentColIndex++;
}
return (long)((m_bodyBlock[valuePos] & (long)0xFF)
| ((m_bodyBlock[valuePos + 1] & (long)0xFF) << 8)
| ((m_bodyBlock[valuePos + 2] & (long)0xFF) << 16)
| ((m_bodyBlock[valuePos + 3] & (long)0xFF) << 24)
| ((m_bodyBlock[valuePos + 4] & (long)0xFF) << 32)
| ((m_bodyBlock[valuePos + 5] & (long)0xFF) << 40)
| ((m_bodyBlock[valuePos + 6] & (long)0xFF) << 48)
| ((m_bodyBlock[valuePos + 7] & (long)0xFF) << 56));
}
public long[] GetlongArrayByIndex(string key = null)
{
int colIndex = CurrentColIndex;
if (key != null)
{
if (!m_titleIndex.ContainsKey(key))
{
return Array.Empty<long>();
}
colIndex = m_titleIndex[key];
}
int valuePos = ColPosList[colIndex] + LinePosList[CurrentLine];
int strlen = (int)((m_bodyBlock[valuePos] & 0xFF)
| ((m_bodyBlock[valuePos + 1] & 0xFF) << 8)
| ((m_bodyBlock[valuePos + 2] & 0xFF) << 16)
| ((m_bodyBlock[valuePos + 3] & 0xFF) << 24));
valuePos += 4;
int strpos = (int)((m_bodyBlock[valuePos] & 0xFF)
| ((m_bodyBlock[valuePos + 1] & 0xFF) << 8)
| ((m_bodyBlock[valuePos + 2] & 0xFF) << 16)
| ((m_bodyBlock[valuePos + 3] & 0xFF) << 24));
if (CurrentColIndex >= ColCount - 1)
{
CurrentColIndex = 0;
}
else
{
CurrentColIndex++;
}
var bytes = m_stringBlock.Skip(strpos).Take(strlen).ToArray();
var length = bytes.Length / 8;
var result = new long[length];
for (var i = 0; i < length; i++)
{
long value = 0;
value |= ((long)bytes[i * 8 + 0] & 0xFF);
value |= ((long)bytes[i * 8 + 1] & 0xFF) << 8;
value |= ((long)bytes[i * 8 + 2] & 0xFF) << 16;
value |= ((long)bytes[i * 8 + 3] & 0xFF) << 24;
value |= ((long)bytes[i * 8 + 4] & 0xFF) << 32;
value |= ((long)bytes[i * 8 + 5] & 0xFF) << 40;
value |= ((long)bytes[i * 8 + 6] & 0xFF) << 48;
value |= ((long)bytes[i * 8 + 7] & 0xFF) << 56;
result[i] = value;
}
return result;
}
public int[] GetintArrayByIndex(string key = null)
{
int colIndex = CurrentColIndex;
if (key != null)
{
if (!m_titleIndex.ContainsKey(key))
{
return Array.Empty<int>();
}
colIndex = m_titleIndex[key];
}
int valuePos = ColPosList[colIndex] + LinePosList[CurrentLine];
int strlen = (int)((m_bodyBlock[valuePos] & 0xFF)
| ((m_bodyBlock[valuePos + 1] & 0xFF) << 8)
| ((m_bodyBlock[valuePos + 2] & 0xFF) << 16)
| ((m_bodyBlock[valuePos + 3] & 0xFF) << 24));
valuePos += 4;
int strpos = (int)((m_bodyBlock[valuePos] & 0xFF)
| ((m_bodyBlock[valuePos + 1] & 0xFF) << 8)
| ((m_bodyBlock[valuePos + 2] & 0xFF) << 16)
| ((m_bodyBlock[valuePos + 3] & 0xFF) << 24));
if (CurrentColIndex >= ColCount - 1)
{
CurrentColIndex = 0;
}
else
{
CurrentColIndex++;
}
var bytes = m_stringBlock.Skip(strpos).Take(strlen).ToArray();
int length = bytes.Length / 4;
var result = new int[length];
for (int i = 0; i < length; i++)
{
int value = 0;
value |= (bytes[i * 4 + 0] & 0xFF);
value |= (bytes[i * 4 + 1] & 0xFF) << 8;
value |= (bytes[i * 4 + 2] & 0xFF) << 16;
value |= (bytes[i * 4 + 3] & 0xFF) << 24;
result[i] = value;
}
return result;
}
public uint[] GetuintArrayByIndex(string key = null)
{
int colIndex = CurrentColIndex;
if (key != null)
{
if (!m_titleIndex.ContainsKey(key))
{
return Array.Empty<uint>();
}
colIndex = m_titleIndex[key];
}
int valuePos = ColPosList[colIndex] + LinePosList[CurrentLine];
int strlen = (int)((m_bodyBlock[valuePos] & 0xFF)
| ((m_bodyBlock[valuePos + 1] & 0xFF) << 8)
| ((m_bodyBlock[valuePos + 2] & 0xFF) << 16)
| ((m_bodyBlock[valuePos + 3] & 0xFF) << 24));
valuePos += 4;
int strpos = (int)((m_bodyBlock[valuePos] & 0xFF)
| ((m_bodyBlock[valuePos + 1] & 0xFF) << 8)
| ((m_bodyBlock[valuePos + 2] & 0xFF) << 16)
| ((m_bodyBlock[valuePos + 3] & 0xFF) << 24));
if (CurrentColIndex >= ColCount - 1)
{
CurrentColIndex = 0;
}
else
{
CurrentColIndex++;
}
var bytes = m_stringBlock.Skip(strpos).Take(strlen).ToArray();
int length = bytes.Length / 4;
var result = new uint[length];
for (int i = 0; i < length; i++)
{
uint value = 0;
value |= ((uint)bytes[i * 4 + 0] & 0xFF);
value |= ((uint)bytes[i * 4 + 1] & 0xFF) << 8;
value |= ((uint)bytes[i * 4 + 2] & 0xFF) << 16;
value |= ((uint)bytes[i * 4 + 3] & 0xFF) << 24;
result[i] = value;
}
return result;
}
public string GetstringByIndex(string key = null)
{
int colIndex = CurrentColIndex;
if (key != null)
{
if (!m_titleIndex.ContainsKey(key))
{
return "";
}
colIndex = m_titleIndex[key];
}
int valuePos = ColPosList[colIndex] + LinePosList[CurrentLine];
int strlen = (int)((m_bodyBlock[valuePos] & 0xFF)
| ((m_bodyBlock[valuePos + 1] & 0xFF) << 8)
| ((m_bodyBlock[valuePos + 2] & 0xFF) << 16)
| ((m_bodyBlock[valuePos + 3] & 0xFF) << 24));
valuePos += 4;
int strpos = (int)((m_bodyBlock[valuePos] & 0xFF)
| ((m_bodyBlock[valuePos + 1] & 0xFF) << 8)
| ((m_bodyBlock[valuePos + 2] & 0xFF) << 16)
| ((m_bodyBlock[valuePos + 3] & 0xFF) << 24));
if (CurrentColIndex >= ColCount - 1)
{
CurrentColIndex = 0;
}
else
{
CurrentColIndex++;
}
return GetParseStringPos(strlen, strpos);
}
public string[] GetstringArrayByIndex(string key = null)
{
var str = GetstringByIndex(key);
if (string.IsNullOrEmpty(str) || str.Equals("0"))
{
return Array.Empty<string>();
}
var arr = new string[str.Length / 2 + 1];
var validCount = 0;
var sb = new StringBuilder();
foreach (var c in str)
{
if (c == ';')
{
if (sb.Length > 0)
{
arr[validCount++] = sb.ToString();
sb.Clear();
}
else
{
arr[validCount++] = "";
sb.Clear();
}
}
else
{
sb.Append(c);
}
}
if (sb.Length > 0)
{
arr[validCount++] = sb.ToString();
}
var ret = new string[validCount];
for (var i = 0; i < validCount; i++)
{
ret[i] = arr[i];
}
return ret;
}
public JObject GetJObjectByIndex(string key = null)
{
var str = GetstringByIndex(key);
if (string.IsNullOrEmpty(str)||string.IsNullOrEmpty(str.Trim()))
{
return null;
}
return JObject.Parse(str);
}
public JArray GetJArrayByIndex(string key = null)
{
var str = GetstringByIndex(key);
if (string.IsNullOrEmpty(str))
{
return null;
}
return JArray.Parse(str);
}
private string GetParseStringPos(int strLen, int postion)
{
return Encoding.UTF8.GetString(m_stringBlock.Skip(postion).Take(strLen).ToArray());
}
private int FromBinaryToInt(byte[] binaryBits, int offset = 0)
{
int value;
value = (int)((binaryBits[offset] & 0xFF)
| ((binaryBits[offset + 1] & 0xFF) << 8)
| ((binaryBits[offset + 2] & 0xFF) << 16)
| ((binaryBits[offset + 3] & 0xFF) << 24));
return value;
}
private long FromBinaryToLong(byte[] binaryBits, int offset = 0)
{
long value;
value = (long)((binaryBits[offset] & (long)0xFF)
| ((binaryBits[offset + 1] & (long)0xFF) << 8)
| ((binaryBits[offset + 2] & (long)0xFF) << 16)
| ((binaryBits[offset + 3] & (long)0xFF) << 24)
| ((binaryBits[offset + 4] & (long)0xFF) << 32)
| ((binaryBits[offset + 5] & (long)0xFF) << 40)
| ((binaryBits[offset + 6] & (long)0xFF) << 48)
| ((binaryBits[offset + 7] & (long)0xFF) << 56));
return value;
}
public uint Getuint(string strColName)
{
int nColIndex = Array.IndexOf(Titles, strColName);
if (nColIndex < 0)
{
TraceLog.Error("TabBinFile: read data error, file:{0}, colName:{1}", FileName, strColName);
return 0;
}
int valuePos = ColPosList[nColIndex] + LinePosList[CurrentLine];
return (uint)FromBinaryToInt(m_bodyBlock.Skip(valuePos).Take(4).ToArray());
}
public int Getint(string strColName)
{
int nColIndex = Array.IndexOf(Titles, strColName);
if (nColIndex < 0)
{
TraceLog.Error("TabBinFile: read data error, file:{0}, colName:{1}", FileName, strColName);
return 0;
}
int valuePos = ColPosList[nColIndex] + LinePosList[CurrentLine];
return FromBinaryToInt(m_bodyBlock.Skip(valuePos).Take(4).ToArray());
}
public long Getlong(string strColName)
{
int nColIndex = Array.IndexOf(Titles, strColName);
if (nColIndex < 0)
{
TraceLog.Error("TabBinFile: read data error, file:{0}, colName:{1}", FileName, strColName);
return 0;
}
int valuePos = ColPosList[nColIndex] + LinePosList[CurrentLine];
return FromBinaryToInt(m_bodyBlock.Skip(valuePos).Take(8).ToArray());
}
public string Getstring(string strColName)
{
int nColIndex = Array.IndexOf(Titles, strColName);
if (nColIndex < 0)
{
TraceLog.Error("TabBinFile: read data error, file:{0}, colName:{1}", FileName, strColName);
return "";
}
int valuePos = ColPosList[nColIndex] + LinePosList[CurrentLine];
int strlen = FromBinaryToInt(m_bodyBlock.Skip(valuePos).Take(4).ToArray());
valuePos += 4;
int strpos = FromBinaryToInt(m_bodyBlock.Skip(valuePos).Take(4).ToArray());
return GetParseStringPos(strlen, strpos);
}
}
}