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.
 
 
 

365 lines
13 KiB

using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.Linq;
using Newtonsoft.Json;
namespace LTEMvcApp.Models
{
/// <summary>
/// ASN1解析器,用于解析GSER格式的ASN1数据
/// </summary>
public class ASN1Parser
{
private static readonly Regex RegExpOpen = new Regex(@"((?! )[\w-\s]+(?<! ))?:?\s*{", RegexOptions.Compiled);
private static readonly Regex RegExpClose = new Regex(@"}", RegexOptions.Compiled);
private static readonly Regex RegExpValueNum = new Regex(@"([\w-]+)\s+(\d+),?$", RegexOptions.Compiled);
private static readonly Regex RegExpValueEnumerated = new Regex(@"([\w-]+)\s+([\w-']+)\s*,?$", RegexOptions.Compiled);
private static readonly Regex RegExpValueChoice = new Regex(@"([\w-]+) ([\w-]+):\s+([\w-']+)\s*,?$", RegexOptions.Compiled);
private static readonly Regex RegExpValueListNum = new Regex(@"\s+(\d+),?$", RegexOptions.Compiled);
private static readonly Regex RegExpValueListMisc = new Regex(@"\s+([\w-]+),?$", RegexOptions.Compiled);
private static readonly Regex RegExpHexDump = new Regex(@"^[0-9A-Fa-f\s]+$", RegexOptions.Compiled);
/// <summary>
/// 从GSER格式的字符串数组解析ASN1数据
/// </summary>
/// <param name="data">GSER格式的字符串数组</param>
/// <returns>解析后的ASN1对象</returns>
public static Dictionary<string, object> FromGSER(string[] data)
{
if (data == null || data.Length == 0)
return null;
var root = (ASN1Node)null;
var stack = new Stack<ASN1Node>();
try
{
int i = 0;
// 移除十六进制转储
for (; i < data.Length; i++)
{
var d = data[i];
if (!RegExpHexDump.IsMatch(d))
break;
}
for (; i < data.Length; i++)
{
var d = data[i];
// 移除注释
for (int j = 0; j < 10; j++) // 最多10次迭代
{
var c0 = d.IndexOf("/*");
if (c0 < 0) break;
var c1 = d.IndexOf("*/");
if (c1 >= 0)
{
d = d.Remove(c0, c1 + 2 - c0);
}
else
{
d = d.Substring(0, c0);
for (i++; i < data.Length; i++)
{
var d1 = data[i];
var c2 = d1.IndexOf("*/");
if (c2 >= 0)
{
d += d1.Substring(c2 + 2);
break;
}
}
}
}
var match = RegExpOpen.Match(d);
if (match.Success)
{
var node = new ASN1Node { Name = match.Groups[1].Success ? match.Groups[1].Value.Trim() : null };
if (root == null) root = node;
stack.Push(node);
continue;
}
if (stack.Count == 0) continue;
match = RegExpClose.Match(d);
if (match.Success)
{
var node = stack.Pop();
if (stack.Count == 0) // 结束
break;
AddProperty(stack.Peek(), node.Name, node.Obj ?? new Dictionary<string, object>());
continue;
}
// 数值常量
match = RegExpValueNum.Match(d);
if (match.Success)
{
AddProperty(stack.Peek(), match.Groups[1].Value, int.Parse(match.Groups[2].Value));
}
// 通用字符串
else if ((match = RegExpValueEnumerated.Match(d)).Success)
{
var value = match.Groups[2].Value;
switch (value)
{
case "TRUE":
AddProperty(stack.Peek(), match.Groups[1].Value, true);
break;
case "FALSE":
AddProperty(stack.Peek(), match.Groups[1].Value, false);
break;
default:
AddProperty(stack.Peek(), match.Groups[1].Value, value);
break;
}
}
// 带基本值的Choice
else if ((match = RegExpValueChoice.Match(d)).Success)
{
AddProperty(stack.Peek(), match.Groups[1].Value,
new Dictionary<string, object>
{
["choice"] = match.Groups[2].Value,
["value"] = match.Groups[3].Value
});
}
else if ((match = RegExpValueListNum.Match(d)).Success)
{
AddProperty(stack.Peek(), null, int.Parse(match.Groups[1].Value));
}
else if ((match = RegExpValueListMisc.Match(d)).Success)
{
AddProperty(stack.Peek(), null, match.Groups[1].Value);
}
}
// 验证解析结果
if (root == null)
return null;
if (stack.Count != 0)
{
// 栈不为空说明解析不完整,返回null
return null;
}
// 确保返回的是Dictionary<string, object>类型
if (root.Obj is Dictionary<string, object> dict)
{
return dict;
}
else if (root.Obj is List<object> list)
{
// 如果是列表,包装成字典
return new Dictionary<string, object> { ["items"] = list };
}
else if (root.Obj != null)
{
// 如果是其他类型,包装成字典
return new Dictionary<string, object> { ["value"] = root.Obj };
}
else
{
// 如果root.Obj为null,返回空字典
return new Dictionary<string, object>();
}
}
catch (Exception ex)
{
// 记录异常信息(在实际应用中可以使用日志框架)
throw new InvalidOperationException($"解析GSER数据时发生错误: {ex.Message}", ex);
}
}
/// <summary>
/// 添加属性到节点
/// </summary>
private static void AddProperty(ASN1Node node, string name, object value)
{
if (string.IsNullOrEmpty(name))
{
if (node.Obj == null) node.Obj = new List<object>();
((List<object>)node.Obj).Add(value);
}
else
{
if (node.Obj == null) node.Obj = new Dictionary<string, object>();
var dict = (Dictionary<string, object>)node.Obj;
if (!dict.ContainsKey(name))
{
dict[name] = value;
}
else
{
var cur = dict[name];
if (cur is List<object> list)
{
list.Add(value);
}
else
{
dict[name] = new List<object> { cur, value };
}
}
}
}
/// <summary>
/// 深度访问ASN1对象
/// </summary>
/// <param name="asn1">ASN1对象</param>
/// <param name="path">访问路径</param>
/// <returns>访问到的值</returns>
public static object Dig(Dictionary<string, object> asn1, params object[] path)
{
if (asn1 == null)
return null;
var current = (object)asn1;
var count = 1;
for (int i = 0; i < path.Length;)
{
var arg = path[i];
if (arg is int intArg)
{
count = intArg;
i++;
}
else
{
if (current is Dictionary<string, object> dict)
{
var key = arg.ToString();
if (!dict.ContainsKey(key))
return null;
current = dict[key];
}
else if (current is List<object> list)
{
var index = int.Parse(arg.ToString());
if (index >= list.Count)
return null;
current = list[index];
}
else
{
return null;
}
if (--count == 0)
{
i++;
count = 1;
}
}
}
return current;
}
/// <summary>
/// 映射ASN1数组
/// </summary>
/// <typeparam name="T">返回类型</typeparam>
/// <param name="asn1">ASN1对象</param>
/// <param name="callback">映射函数</param>
/// <returns>映射结果</returns>
public static List<T> Map<T>(object asn1, Func<object, T> callback)
{
// 参数验证
if (callback == null)
throw new ArgumentNullException(nameof(callback), "回调函数不能为空");
// 如果asn1为null,返回空列表
if (asn1 == null)
return new List<T>();
try
{
if (asn1 is List<object> list)
{
// 处理列表类型,过滤掉null值并应用映射
return list.Where(item => item != null)
.Select(callback)
.ToList<T>();
}
else
{
// 处理单个对象
return new List<T> { callback(asn1) };
}
}
catch (Exception ex)
{
// 记录异常信息(在实际应用中可以使用日志框架)
throw new InvalidOperationException($"映射ASN1数据时发生错误: {ex.Message}", ex);
}
}
/// <summary>
/// 映射ASN1数组(带索引)
/// </summary>
/// <typeparam name="T">返回类型</typeparam>
/// <param name="asn1">ASN1对象</param>
/// <param name="callback">带索引的映射函数</param>
/// <returns>映射结果</returns>
public static List<T> Map<T>(object asn1, Func<object, int, T> callback)
{
// 参数验证
if (callback == null)
throw new ArgumentNullException(nameof(callback), "回调函数不能为空");
// 如果asn1为null,返回空列表
if (asn1 == null)
return new List<T>();
try
{
if (asn1 is List<object> list)
{
// 处理列表类型,过滤掉null值并应用带索引的映射
var result = new List<T>();
int index = 0;
foreach (var item in list)
{
if (item != null)
{
result.Add(callback(item, index));
}
index++;
}
return result;
}
else
{
// 处理单个对象
return new List<T> { callback(asn1, 0) };
}
}
catch (Exception ex)
{
// 记录异常信息(在实际应用中可以使用日志框架)
throw new InvalidOperationException($"映射ASN1数据时发生错误: {ex.Message}", ex);
}
}
}
/// <summary>
/// ASN1节点
/// </summary>
public class ASN1Node
{
public string Name { get; set; }
public object Obj { get; set; }
}
}