【优化】灵活并且统一了sep的用法

main
walon 2021-12-05 16:57:55 +08:00
parent 83f81ed463
commit 19656437cb
39 changed files with 520 additions and 249 deletions

View File

@ -11,7 +11,7 @@ using System.Threading.Tasks;
namespace Luban.Job.Cfg.DataConverts
{
public class FillSheetVisitor : IDataFuncVisitor<Title, int>
public class FillSheetVisitor : IDataFuncVisitor<TType, Title, int>
{
private readonly List<object[]> _cells;
@ -36,107 +36,107 @@ namespace Luban.Job.Cfg.DataConverts
_cells[_startRowIndex][title.FromIndex] = value;
}
public int Accept(DBool type, Title x)
public int Accept(DBool data, TType type, Title x)
{
SetTitleValue(x, type.Value);
SetTitleValue(x, data.Value);
return 1;
}
public int Accept(DByte type, Title x)
public int Accept(DByte data, TType type, Title x)
{
SetTitleValue(x, type.Value);
SetTitleValue(x, data.Value);
return 1;
}
public int Accept(DShort type, Title x)
public int Accept(DShort data, TType type, Title x)
{
SetTitleValue(x, type.Value);
SetTitleValue(x, data.Value);
return 1;
}
public int Accept(DFshort type, Title x)
public int Accept(DFshort data, TType type, Title x)
{
SetTitleValue(x, type.Value);
SetTitleValue(x, data.Value);
return 1;
}
public int Accept(DInt type, Title x)
public int Accept(DInt data, TType type, Title x)
{
SetTitleValue(x, type.Value);
SetTitleValue(x, data.Value);
return 1;
}
public int Accept(DFint type, Title x)
public int Accept(DFint data, TType type, Title x)
{
SetTitleValue(x, type.Value);
SetTitleValue(x, data.Value);
return 1;
}
public int Accept(DLong type, Title x)
public int Accept(DLong data, TType type, Title x)
{
SetTitleValue(x, type.Value);
SetTitleValue(x, data.Value);
return 1;
}
public int Accept(DFlong type, Title x)
public int Accept(DFlong data, TType type, Title x)
{
SetTitleValue(x, type.Value);
SetTitleValue(x, data.Value);
return 1;
}
public int Accept(DFloat type, Title x)
public int Accept(DFloat data, TType type, Title x)
{
SetTitleValue(x, type.Value);
SetTitleValue(x, data.Value);
return 1;
}
public int Accept(DDouble type, Title x)
public int Accept(DDouble data, TType type, Title x)
{
SetTitleValue(x, type.Value);
SetTitleValue(x, data.Value);
return 1;
}
public int Accept(DEnum type, Title x)
public int Accept(DEnum data, TType type, Title x)
{
SetTitleValue(x, type.StrValue);
SetTitleValue(x, data.StrValue);
return 1;
}
public int Accept(DString type, Title x)
public int Accept(DString data, TType type, Title x)
{
SetTitleValue(x, type.Value);
SetTitleValue(x, data.Value);
return 1;
}
public int Accept(DBytes type, Title x)
public int Accept(DBytes data, TType type, Title x)
{
throw new NotImplementedException();
}
public int Accept(DText type, Title x)
public int Accept(DText data, TType type, Title x)
{
//if (x.FromIndex == x.ToIndex)
//{
// throw new Exception($"title:{x.Name}为text类型至少要占两列");
//}
SetTitleValue(x, type.Apply(ToExcelStringVisitor.Ins, x.Sep));
SetTitleValue(x, data.Apply(ToExcelStringVisitor.Ins, type.OrTag("sep", "#")));
//(_cells[_startRowIndex, x.FromIndex + 1] as Range).Value = type.RawValue;
return 1;
}
public int Accept(DBean type, Title x)
public int Accept(DBean data, TType type, Title x)
{
if (x.SubTitleList.Count > 0)
{
if (type.Type.IsAbstractType)
if (data.Type.IsAbstractType)
{
if (!x.SubTitles.TryGetValue(DefBean.TYPE_NAME_KEY, out var typeTitle))
{
throw new Exception($"多态bean:{type.Type.FullName} 缺失 __type__ 标题列");
throw new Exception($"多态bean:{data.Type.FullName} 缺失 __type__ 标题列");
}
if (type.ImplType != null)
if (data.ImplType != null)
{
SetTitleValue(typeTitle, type.ImplType.Name);
SetTitleValue(typeTitle, data.ImplType.Name);
}
else
{
@ -145,7 +145,7 @@ namespace Luban.Job.Cfg.DataConverts
}
else
{
if (type.ImplType != null)
if (data.ImplType != null)
{
}
@ -156,22 +156,22 @@ namespace Luban.Job.Cfg.DataConverts
}
}
int rowCount = 1;
if (type.ImplType != null)
if (data.ImplType != null)
{
int index = 0;
foreach (var field in type.ImplType.HierarchyFields)
foreach (var field in data.ImplType.HierarchyFields)
{
var data = type.Fields[index++];
var fdata = data.Fields[index++];
if (!x.SubTitles.TryGetValue(field.Name, out var fieldTitle))
{
throw new Exception($"title:{x.Name} 子title:{field.Name} 缺失");
}
if (data != null)
if (fdata != null)
{
//if (fieldTitle.SubTitleList.Count > 0)
//{
rowCount = Math.Max(rowCount, data.Apply(this, fieldTitle));
rowCount = Math.Max(rowCount, fdata.Apply(this, field.CType, fieldTitle));
//}
//else
//{
@ -181,7 +181,7 @@ namespace Luban.Job.Cfg.DataConverts
}
else if (field.CType is TText)
{
SetTitleValue(fieldTitle, $"null{fieldTitle.Sep}null");
SetTitleValue(fieldTitle, $"null{(field.CType.HasTag("sep") ? field.CType.GetTag("sep") : "#")}null");
}
}
}
@ -189,12 +189,12 @@ namespace Luban.Job.Cfg.DataConverts
}
else
{
SetTitleValue(x, type.Apply(ToExcelStringVisitor.Ins, x.Sep));
SetTitleValue(x, data.Apply(ToExcelStringVisitor.Ins, type.GetTag("sep")));
return 1;
}
}
public int Accept(DArray type, Title x)
public int Accept(DArray data, TType type, Title x)
{
if (x.SelfMultiRows)
{
@ -202,9 +202,10 @@ namespace Luban.Job.Cfg.DataConverts
int totalRow = 0;
try
{
foreach (var ele in type.Datas)
var elementType = data.Type.ElementType;
foreach (var ele in data.Datas)
{
totalRow += ele.Apply(this, x);
totalRow += ele.Apply(this, elementType, x);
_startRowIndex = oldStartRow + totalRow;
}
return totalRow;
@ -216,12 +217,12 @@ namespace Luban.Job.Cfg.DataConverts
}
else
{
SetTitleValue(x, type.Apply(ToExcelStringVisitor.Ins, x.Sep));
SetTitleValue(x, data.Apply(ToExcelStringVisitor.Ins, type.GetTag("sep")));
return 1;
}
}
public int Accept(DList type, Title x)
public int Accept(DList data, TType type, Title x)
{
if (x.SelfMultiRows)
{
@ -229,9 +230,10 @@ namespace Luban.Job.Cfg.DataConverts
int totalRow = 0;
try
{
foreach (var ele in type.Datas)
var elementType = data.Type.ElementType;
foreach (var ele in data.Datas)
{
totalRow += ele.Apply(this, x);
totalRow += ele.Apply(this, elementType, x);
_startRowIndex = oldStartRow + totalRow;
}
return totalRow;
@ -243,47 +245,47 @@ namespace Luban.Job.Cfg.DataConverts
}
else
{
SetTitleValue(x, type.Apply(ToExcelStringVisitor.Ins, x.Sep));
SetTitleValue(x, data.Apply(ToExcelStringVisitor.Ins, type.GetTag("sep")));
return 1;
}
}
public int Accept(DSet type, Title x)
public int Accept(DSet data, TType type, Title x)
{
SetTitleValue(x, type.Apply(ToExcelStringVisitor.Ins, x.Sep));
SetTitleValue(x, data.Apply(ToExcelStringVisitor.Ins, type.GetTag("sep")));
return 1;
}
public int Accept(DMap type, Title x)
public int Accept(DMap data, TType type, Title x)
{
SetTitleValue(x, type.Apply(ToExcelStringVisitor.Ins, x.Sep));
SetTitleValue(x, data.Apply(ToExcelStringVisitor.Ins, type.GetTag("sep")));
return 1;
}
public int Accept(DVector2 type, Title x)
public int Accept(DVector2 data, TType type, Title x)
{
var v = type.Value;
var v = data.Value;
SetTitleValue(x, $"{v.X}, {v.Y}");
return 1;
}
public int Accept(DVector3 type, Title x)
public int Accept(DVector3 data, TType type, Title x)
{
var v = type.Value;
var v = data.Value;
SetTitleValue(x, $"{v.X},{v.Y},{v.Z}");
return 1;
}
public int Accept(DVector4 type, Title x)
public int Accept(DVector4 data, TType type, Title x)
{
var v = type.Value;
var v = data.Value;
SetTitleValue(x, $"{v.X},{v.Y},{v.Z},{v.W}");
return 1;
}
public int Accept(DDateTime type, Title x)
public int Accept(DDateTime data, TType type, Title x)
{
SetTitleValue(x, type.Time);
SetTitleValue(x, data.Time);
return 1;
}
}

View File

@ -281,6 +281,50 @@ namespace Luban.Job.Cfg.DataCreators
return new DText(key, text);
}
public DType Accept(TDateTime type, ExcelStream x)
{
var d = x.Read();
if (CheckNull(type.IsNullable, d))
{
return null;
}
if (d is System.DateTime datetime)
{
return new DDateTime(datetime);
}
return DataUtil.CreateDateTime(d.ToString());
}
public DType Accept(TVector2 type, ExcelStream x)
{
var d = x.Read();
if (CheckNull(type.IsNullable, d))
{
return null;
}
return DataUtil.CreateVector(type, d.ToString());
}
public DType Accept(TVector3 type, ExcelStream x)
{
var d = x.Read();
if (CheckNull(type.IsNullable, d))
{
return null;
}
return DataUtil.CreateVector(type, d.ToString());
}
public DType Accept(TVector4 type, ExcelStream x)
{
var d = x.Read();
if (CheckNull(type.IsNullable, d))
{
return null;
}
return DataUtil.CreateVector(type, d.ToString());
}
private List<DType> CreateBeanFields(DefBean bean, ExcelStream stream)
{
var list = new List<DType>();
@ -328,6 +372,7 @@ namespace Luban.Job.Cfg.DataCreators
public DType Accept(TBean type, ExcelStream x)
{
var originX = x;
var originBean = (DefBean)type.Bean;
if (!string.IsNullOrEmpty(originBean.Sep))
{
@ -376,10 +421,18 @@ namespace Luban.Job.Cfg.DataCreators
public List<DType> ReadList(TType type, ExcelStream stream)
{
var datas = new List<DType>();
string elementSep = type.GetTag("sep");
while (!stream.TryReadEOF())
{
if (string.IsNullOrEmpty(elementSep))
{
datas.Add(type.Apply(this, stream));
}
else
{
datas.Add(type.Apply(this, new ExcelStream(stream.ReadCell(), elementSep)));
}
}
return datas;
}
@ -414,49 +467,5 @@ namespace Luban.Job.Cfg.DataCreators
}
return new DMap(type, datas);
}
public DType Accept(TVector2 type, ExcelStream x)
{
var d = x.Read();
if (CheckNull(type.IsNullable, d))
{
return null;
}
return DataUtil.CreateVector(type, d.ToString());
}
public DType Accept(TVector3 type, ExcelStream x)
{
var d = x.Read();
if (CheckNull(type.IsNullable, d))
{
return null;
}
return DataUtil.CreateVector(type, d.ToString());
}
public DType Accept(TVector4 type, ExcelStream x)
{
var d = x.Read();
if (CheckNull(type.IsNullable, d))
{
return null;
}
return DataUtil.CreateVector(type, d.ToString());
}
public DType Accept(TDateTime type, ExcelStream x)
{
var d = x.Read();
if (CheckNull(type.IsNullable, d))
{
return null;
}
if (d is System.DateTime datetime)
{
return new DDateTime(datetime);
}
return DataUtil.CreateDateTime(d.ToString());
}
}
}

View File

@ -249,7 +249,7 @@ namespace Luban.Job.Cfg.DataCreators
public DType Accept(TText type, Sheet sheet, TitleRow row)
{
if (string.IsNullOrEmpty(row.SelfTitle.Sep))
if (!type.HasTag("sep"))
{
if (row.CellCount != 2)
{
@ -267,11 +267,70 @@ namespace Luban.Job.Cfg.DataCreators
}
else
{
var s = row.AsStream("");
var s = row.AsStream(type.GetTag("sep"));
return type.Apply(ExcelStreamDataCreator.Ins, s);
}
}
public DType Accept(TDateTime type, Sheet sheet, TitleRow row)
{
var d = row.Current;
if (CheckNull(type.IsNullable, d))
{
return null;
}
if (d is System.DateTime datetime)
{
return new DDateTime(datetime);
}
return DataUtil.CreateDateTime(d.ToString());
}
public DType Accept(TVector2 type, Sheet sheet, TitleRow row)
{
var d = row.Current;
if (CheckNull(type.IsNullable, d))
{
return null;
}
if (CheckDefault(d))
{
ThrowIfNonEmpty(row);
return DVector2.Default;
}
return DataUtil.CreateVector(type, d.ToString());
}
public DType Accept(TVector3 type, Sheet sheet, TitleRow row)
{
var d = row.Current;
if (CheckNull(type.IsNullable, d))
{
return null;
}
if (CheckDefault(d))
{
ThrowIfNonEmpty(row);
return DVector3.Default;
}
return DataUtil.CreateVector(type, d.ToString());
}
public DType Accept(TVector4 type, Sheet sheet, TitleRow row)
{
var d = row.Current;
if (CheckNull(type.IsNullable, d))
{
return null;
}
if (CheckDefault(d))
{
ThrowIfNonEmpty(row);
return DVector4.Default;
}
return DataUtil.CreateVector(type, d.ToString());
}
private List<DType> CreateBeanFields(DefBean bean, Sheet sheet, TitleRow row)
{
var list = new List<DType>();
@ -305,11 +364,16 @@ namespace Luban.Job.Cfg.DataCreators
public DType Accept(TBean type, Sheet sheet, TitleRow row)
{
//string sep = DataUtil.GetSep(type);
string sep = "";// type.GetBeanAs<DefBean>().Sep;
if (string.IsNullOrWhiteSpace(sep))
{
sep = row.SelfTitle.SepOr(type.GetTag("sep"));
}
if (row.Row != null)
{
var s = row.AsStream("");
var s = row.AsStream(sep);
if (type.IsNullable && s.TryReadEOF())
{
return null;
@ -318,7 +382,7 @@ namespace Luban.Job.Cfg.DataCreators
}
else if (row.Rows != null)
{
var s = row.AsMultiRowConcatStream("");
var s = row.AsMultiRowConcatStream(sep);
if (type.IsNullable && s.TryReadEOF())
{
return null;
@ -367,7 +431,7 @@ namespace Luban.Job.Cfg.DataCreators
}
else if (row.Elements != null)
{
var s = row.AsMultiRowConcatElements();
var s = row.AsMultiRowConcatElements(sep);
return type.Apply(ExcelStreamDataCreator.Ins, s);
}
else
@ -378,11 +442,19 @@ namespace Luban.Job.Cfg.DataCreators
public List<DType> ReadList(TType type, ExcelStream stream)
{
var sep = type.GetTag("sep");
var datas = new List<DType>();
while (!stream.TryReadEOF())
{
if (string.IsNullOrEmpty(sep))
{
datas.Add(type.Apply(ExcelStreamDataCreator.Ins, stream));
}
else
{
datas.Add(type.Apply(ExcelStreamDataCreator.Ins, new ExcelStream(stream.ReadCell(), sep)));
}
}
return datas;
}
@ -399,16 +471,16 @@ namespace Luban.Job.Cfg.DataCreators
return datas;
}
private List<DType> ReadCollectionDatas(TType elementType, Sheet sheet, TitleRow row)
private List<DType> ReadCollectionDatas(TType elementType, Sheet sheet, TitleRow row, string containerSep)
{
if (row.Row != null)
{
var s = row.AsStream(DataUtil.GetTypeSep(elementType));
return ReadList(elementType, s);
var s = row.AsStream(string.IsNullOrEmpty(containerSep) ? DataUtil.GetCollectionElementTypeSep(elementType) : containerSep);
return ExcelStreamDataCreator.Ins.ReadList(elementType, s);
}
else if (row.Rows != null)
{
var s = row.AsMultiRowStream(DataUtil.GetTypeSep(elementType));
var s = row.AsMultiRowStream(string.IsNullOrEmpty(containerSep) ? DataUtil.GetCollectionElementTypeSep(elementType) : containerSep);
return ReadList(elementType, s);
}
else if (row.Fields != null)
@ -441,22 +513,22 @@ namespace Luban.Job.Cfg.DataCreators
public DType Accept(TArray type, Sheet sheet, TitleRow row)
{
//string sep = DataUtil.GetSep(type);
return new DArray(type, ReadCollectionDatas(type.ElementType, sheet, row));
return new DArray(type, ReadCollectionDatas(type.ElementType, sheet, row, row.SelfTitle.SepOr(type.GetTag("sep"))));
}
public DType Accept(TList type, Sheet sheet, TitleRow row)
{
return new DList(type, ReadCollectionDatas(type.ElementType, sheet, row));
return new DList(type, ReadCollectionDatas(type.ElementType, sheet, row, row.SelfTitle.SepOr(type.GetTag("sep"))));
}
public DType Accept(TSet type, Sheet sheet, TitleRow row)
{
return new DSet(type, ReadCollectionDatas(type.ElementType, sheet, row));
return new DSet(type, ReadCollectionDatas(type.ElementType, sheet, row, row.SelfTitle.SepOr(type.GetTag("sep"))));
}
public DType Accept(TMap type, Sheet sheet, TitleRow row)
{
string sep = "";
string sep = row.SelfTitle.SepOr(type.GetTag("sep"));
if (row.Row != null)
{
@ -496,7 +568,7 @@ namespace Luban.Job.Cfg.DataCreators
{
continue;
}
var valueData = type.ValueType.Apply(ExcelStreamDataCreator.Ins, e.Value.AsStream(sep));
var valueData = type.ValueType.Apply(ExcelStreamDataCreator.Ins, e.Value.AsStream(""));
datas.Add(keyData, valueData);
}
return new DMap(type, datas);
@ -506,7 +578,7 @@ namespace Luban.Job.Cfg.DataCreators
var datas = new Dictionary<DType, DType>();
foreach (var e in row.Elements)
{
var stream = e.AsStream("");
var stream = e.AsStream(sep);
var keyData = type.KeyType.Apply(ExcelStreamDataCreator.Ins, stream);
var valueData = type.ValueType.Apply(ExcelStreamDataCreator.Ins, stream);
datas.Add(keyData, valueData);
@ -518,64 +590,5 @@ namespace Luban.Job.Cfg.DataCreators
throw new Exception();
}
}
public DType Accept(TVector2 type, Sheet sheet, TitleRow row)
{
var d = row.Current;
if (CheckNull(type.IsNullable, d))
{
return null;
}
if (CheckDefault(d))
{
ThrowIfNonEmpty(row);
return DVector2.Default;
}
return DataUtil.CreateVector(type, d.ToString());
}
public DType Accept(TVector3 type, Sheet sheet, TitleRow row)
{
var d = row.Current;
if (CheckNull(type.IsNullable, d))
{
return null;
}
if (CheckDefault(d))
{
ThrowIfNonEmpty(row);
return DVector3.Default;
}
return DataUtil.CreateVector(type, d.ToString());
}
public DType Accept(TVector4 type, Sheet sheet, TitleRow row)
{
var d = row.Current;
if (CheckNull(type.IsNullable, d))
{
return null;
}
if (CheckDefault(d))
{
ThrowIfNonEmpty(row);
return DVector4.Default;
}
return DataUtil.CreateVector(type, d.ToString());
}
public DType Accept(TDateTime type, Sheet sheet, TitleRow row)
{
var d = row.Current;
if (CheckNull(type.IsNullable, d))
{
return null;
}
if (d is System.DateTime datetime)
{
return new DDateTime(datetime);
}
return DataUtil.CreateDateTime(d.ToString());
}
}
}

View File

@ -2,6 +2,7 @@
using Luban.Job.Cfg.DataSources;
using Luban.Job.Cfg.DataVisitors;
using Luban.Job.Cfg.Defs;
using Luban.Job.Cfg.RawDefs;
using System;
using System.Collections.Generic;
using System.Text.Json;
@ -16,12 +17,12 @@ namespace Luban.Job.Cfg.DataExporters
{
switch (table.Mode)
{
case RawDefs.ETableMode.ONE:
case ETableMode.ONE:
{
this.Accept(datas[0].Data, x);
break;
}
case RawDefs.ETableMode.MAP:
case ETableMode.MAP:
{
x.WriteStartObject();
@ -37,6 +38,11 @@ namespace Luban.Job.Cfg.DataExporters
x.WriteEndObject();
break;
}
case ETableMode.LIST:
{
JsonExportor.Ins.WriteAsArray(datas, x);
break;
}
default:
{
throw new NotSupportedException($"not support table mode:{table.Mode}");

View File

@ -1,4 +1,5 @@
using ExcelDataReader;
using Luban.Job.Cfg.Defs;
using Luban.Job.Common.Utils;
using System;
using System.Collections.Generic;
@ -151,11 +152,21 @@ namespace Luban.Job.Cfg.DataSources.Excel
titleName = titleName.Substring(1);
tags.Add("multi_rows", "1");
}
//if (titleName.EndsWith("*"))
//{
// titleName = titleName.Substring(0, titleName.Length - 1);
// tags.Add("multi_rows", "1");
//}
if (titleName.StartsWith("!"))
{
titleName = titleName.Substring(1);
tags.Add("non_empty", "1");
}
//if (titleName.EndsWith("!"))
//{
// titleName = titleName.Substring(0, titleName.Length - 1);
// tags.Add("non_empty", "1");
//}
foreach (var attrPair in attrs.Skip(1))
{
var pairs = attrPair.Split('=');
@ -163,7 +174,7 @@ namespace Luban.Job.Cfg.DataSources.Excel
{
throw new Exception($"invalid title: {nameAndAttrs}");
}
tags.Add(pairs[0], pairs[1]);
tags.Add(pairs[0].Trim(), pairs[1].Trim());
}
return (titleName, tags);
}

View File

@ -28,7 +28,7 @@ namespace Luban.Job.Cfg.DataSources.Excel
public string SepOr(string sep)
{
return string.IsNullOrEmpty(Sep) ? sep : Sep;
return string.IsNullOrEmpty(sep) ? Sep : sep;
}
public bool NonEmpty { get; private set; }
@ -65,7 +65,11 @@ namespace Luban.Job.Cfg.DataSources.Excel
public void Init()
{
SortSubTitles();
Sep = Tags.TryGetValue("sep", out var v) && !string.IsNullOrWhiteSpace(v) ? v : null;
Sep = Tags.TryGetValue("sep", out var sep) ? sep : "";
//if (Tags.ContainsKey("sep"))
//{
// throw new Exception($"字段名现在不支持sep请移到##type行例如'int&sep=;'");
//}
NonEmpty = Tags.TryGetValue("non_empty", out var ne) && ne == "1";
SelfMultiRows = Tags.TryGetValue("multi_rows", out var v2) && (v2 == "1" || v2 == "true");
Default = Tags.TryGetValue("default", out var v3) ? v3 : null;

View File

@ -87,8 +87,6 @@ namespace Luban.Job.Cfg.DataSources.Excel
}
public ExcelStream AsStream(string sep)
{
if (string.IsNullOrEmpty(SelfTitle.Sep))
{
if (string.IsNullOrEmpty(sep))
{
@ -99,19 +97,6 @@ namespace Luban.Job.Cfg.DataSources.Excel
return new ExcelStream(Row, SelfTitle.FromIndex, SelfTitle.ToIndex, sep, SelfTitle.Default);
}
}
else
{
//if (string.IsNullOrEmpty(sep) || sep == SelfTitle.Sep)
//{
// return new ExcelStream(Row, SelfTitle.FromIndex, SelfTitle.ToIndex, sep);
//}
//else
//{
// SelfTitle.Sep 设置覆盖 bean的 sep设置只有这个可能
return new ExcelStream(Row, SelfTitle.FromIndex, SelfTitle.ToIndex, SelfTitle.Sep, SelfTitle.Default);
//}
}
}
public bool HasSubFields => Fields != null || Elements != null;
@ -171,13 +156,12 @@ namespace Luban.Job.Cfg.DataSources.Excel
public ExcelStream AsMultiRowConcatStream(string sep)
{
sep = string.IsNullOrEmpty(sep) ? SelfTitle.Sep : sep;
return new ExcelStream(Rows, SelfTitle.FromIndex, SelfTitle.ToIndex, sep, SelfTitle.Default);
}
public ExcelStream AsMultiRowConcatElements()
public ExcelStream AsMultiRowConcatElements(string sep)
{
return new ExcelStream(Elements.Select(e => e.Row).ToList(), SelfTitle.FromIndex, SelfTitle.ToIndex, SelfTitle.Sep, SelfTitle.Default);
return new ExcelStream(Elements.Select(e => e.Row).ToList(), SelfTitle.FromIndex, SelfTitle.ToIndex, sep, SelfTitle.Default);
}
}
}

View File

@ -99,4 +99,53 @@ namespace Luban.Job.Cfg.DataVisitors
TR Accept(DDateTime type, T x);
}
public interface IDataFuncVisitor<T1, T2, TR>
{
TR Accept(DBool type, T1 x, T2 y);
TR Accept(DByte type, T1 x, T2 y);
TR Accept(DShort type, T1 x, T2 y);
TR Accept(DFshort type, T1 x, T2 y);
TR Accept(DInt type, T1 x, T2 y);
TR Accept(DFint type, T1 x, T2 y);
TR Accept(DLong type, T1 x, T2 y);
TR Accept(DFlong type, T1 x, T2 y);
TR Accept(DFloat type, T1 x, T2 y);
TR Accept(DDouble type, T1 x, T2 y);
TR Accept(DEnum type, T1 x, T2 y);
TR Accept(DString type, T1 x, T2 y);
TR Accept(DBytes type, T1 x, T2 y);
TR Accept(DText type, T1 x, T2 y);
TR Accept(DBean type, T1 x, T2 y);
TR Accept(DArray type, T1 x, T2 y);
TR Accept(DList type, T1 x, T2 y);
TR Accept(DSet type, T1 x, T2 y);
TR Accept(DMap type, T1 x, T2 y);
TR Accept(DVector2 type, T1 x, T2 y);
TR Accept(DVector3 type, T1 x, T2 y);
TR Accept(DVector4 type, T1 x, T2 y);
TR Accept(DDateTime type, T1 x, T2 y);
}
}

View File

@ -52,5 +52,10 @@ namespace Luban.Job.Cfg.Datas
{
return visitor.Accept(this, x);
}
public override TR Apply<T1, T2, TR>(IDataFuncVisitor<T1, T2, TR> visitor, T1 x, T2 y)
{
return visitor.Accept(this, x, y);
}
}
}

View File

@ -71,5 +71,10 @@ namespace Luban.Job.Cfg.Datas
{
return visitor.Accept(this, x);
}
public override TR Apply<T1, T2, TR>(IDataFuncVisitor<T1, T2, TR> visitor, T1 x, T2 y)
{
return visitor.Accept(this, x, y);
}
}
}

View File

@ -39,6 +39,11 @@ namespace Luban.Job.Cfg.Datas
return visitor.Accept(this, x);
}
public override TR Apply<T1, T2, TR>(IDataFuncVisitor<T1, T2, TR> visitor, T1 x, T2 y)
{
return visitor.Accept(this, x, y);
}
public override bool Equals(object obj)
{
return obj is DBool o && o.Value == this.Value;

View File

@ -44,6 +44,11 @@ namespace Luban.Job.Cfg.Datas
return visitor.Accept(this, x);
}
public override TR Apply<T1, T2, TR>(IDataFuncVisitor<T1, T2, TR> visitor, T1 x, T2 y)
{
return visitor.Accept(this, x, y);
}
public override bool Equals(object obj)
{
return obj is DByte o && o.Value == this.Value;

View File

@ -40,5 +40,10 @@ namespace Luban.Job.Cfg.Datas
{
return visitor.Accept(this, x);
}
public override TR Apply<T1, T2, TR>(IDataFuncVisitor<T1, T2, TR> visitor, T1 x, T2 y)
{
return visitor.Accept(this, x, y);
}
}
}

View File

@ -79,5 +79,10 @@ namespace Luban.Job.Cfg.Datas
{
return visitor.Accept(this, x);
}
public override TR Apply<T1, T2, TR>(IDataFuncVisitor<T1, T2, TR> visitor, T1 x, T2 y)
{
return visitor.Accept(this, x, y);
}
}
}

View File

@ -37,6 +37,11 @@ namespace Luban.Job.Cfg.Datas
return visitor.Accept(this, x);
}
public override TR Apply<T1, T2, TR>(IDataFuncVisitor<T1, T2, TR> visitor, T1 x, T2 y)
{
return visitor.Accept(this, x, y);
}
public override bool Equals(object obj)
{
return obj is DDouble o && o.Value == this.Value;

View File

@ -41,6 +41,11 @@ namespace Luban.Job.Cfg.Datas
return visitor.Accept(this, x);
}
public override TR Apply<T1, T2, TR>(IDataFuncVisitor<T1, T2, TR> visitor, T1 x, T2 y)
{
return visitor.Accept(this, x, y);
}
public override string ToString()
{
return $"{StrValue}({Value})";

View File

@ -37,6 +37,11 @@ namespace Luban.Job.Cfg.Datas
return visitor.Accept(this, x);
}
public override TR Apply<T1, T2, TR>(IDataFuncVisitor<T1, T2, TR> visitor, T1 x, T2 y)
{
return visitor.Accept(this, x, y);
}
public override bool Equals(object obj)
{
switch (obj)

View File

@ -41,6 +41,11 @@ namespace Luban.Job.Cfg.Datas
return visitor.Accept(this, x);
}
public override TR Apply<T1, T2, TR>(IDataFuncVisitor<T1, T2, TR> visitor, T1 x, T2 y)
{
return visitor.Accept(this, x, y);
}
public override bool Equals(object obj)
{
return obj is DFloat o && o.Value == this.Value;

View File

@ -37,6 +37,11 @@ namespace Luban.Job.Cfg.Datas
return visitor.Accept(this, x);
}
public override TR Apply<T1, T2, TR>(IDataFuncVisitor<T1, T2, TR> visitor, T1 x, T2 y)
{
return visitor.Accept(this, x, y);
}
public override bool Equals(object obj)
{
return obj is DFlong o && o.Value == this.Value;

View File

@ -55,5 +55,10 @@ namespace Luban.Job.Cfg.Datas
{
return visitor.Accept(this, x);
}
public override TR Apply<T1, T2, TR>(IDataFuncVisitor<T1, T2, TR> visitor, T1 x, T2 y)
{
return visitor.Accept(this, x, y);
}
}
}

View File

@ -52,6 +52,11 @@ namespace Luban.Job.Cfg.Datas
return visitor.Accept(this, x);
}
public override TR Apply<T1, T2, TR>(IDataFuncVisitor<T1, T2, TR> visitor, T1 x, T2 y)
{
return visitor.Accept(this, x, y);
}
public override bool Equals(object obj)
{
switch (obj)

View File

@ -49,6 +49,11 @@ namespace Luban.Job.Cfg.Datas
return visitor.Accept(this, x);
}
public override TR Apply<T1, T2, TR>(IDataFuncVisitor<T1, T2, TR> visitor, T1 x, T2 y)
{
return visitor.Accept(this, x, y);
}
//public override bool Equals(object obj)
//{
// if (obj is DList o)

View File

@ -51,6 +51,11 @@ namespace Luban.Job.Cfg.Datas
return visitor.Accept(this, x);
}
public override TR Apply<T1, T2, TR>(IDataFuncVisitor<T1, T2, TR> visitor, T1 x, T2 y)
{
return visitor.Accept(this, x, y);
}
public override bool Equals(object obj)
{
return obj is DLong o && o.Value == this.Value;

View File

@ -58,5 +58,10 @@ namespace Luban.Job.Cfg.Datas
{
return visitor.Accept(this, x);
}
public override TR Apply<T1, T2, TR>(IDataFuncVisitor<T1, T2, TR> visitor, T1 x, T2 y)
{
return visitor.Accept(this, x, y);
}
}
}

View File

@ -57,5 +57,10 @@ namespace Luban.Job.Cfg.Datas
{
return visitor.Accept(this, x);
}
public override TR Apply<T1, T2, TR>(IDataFuncVisitor<T1, T2, TR> visitor, T1 x, T2 y)
{
return visitor.Accept(this, x, y);
}
}
}

View File

@ -37,6 +37,11 @@ namespace Luban.Job.Cfg.Datas
return visitor.Accept(this, x);
}
public override TR Apply<T1, T2, TR>(IDataFuncVisitor<T1, T2, TR> visitor, T1 x, T2 y)
{
return visitor.Accept(this, x, y);
}
public override bool Equals(object obj)
{
return obj is DShort o && o.Value == this.Value;

View File

@ -41,6 +41,11 @@ namespace Luban.Job.Cfg.Datas
return visitor.Accept(this, x);
}
public override TR Apply<T1, T2, TR>(IDataFuncVisitor<T1, T2, TR> visitor, T1 x, T2 y)
{
return visitor.Accept(this, x, y);
}
public override bool Equals(object obj)
{
return obj is DString o && o.Value == this.Value;

View File

@ -62,6 +62,11 @@ namespace Luban.Job.Cfg.Datas
return visitor.Accept(this, x);
}
public override TR Apply<T1, T2, TR>(IDataFuncVisitor<T1, T2, TR> visitor, T1 x, T2 y)
{
return visitor.Accept(this, x, y);
}
public override bool Equals(object obj)
{
return obj is DText o && o._rawValue == this._rawValue && o.Key == this.Key;

View File

@ -13,6 +13,8 @@ namespace Luban.Job.Cfg.Datas
public abstract TR Apply<T, TR>(IDataFuncVisitor<T, TR> visitor, T x);
public abstract TR Apply<T1, T2, TR>(IDataFuncVisitor<T1, T2, TR> visitor, T1 x, T2 y);
public abstract string TypeName { get; }
public override string ToString()

View File

@ -33,6 +33,11 @@ namespace Luban.Job.Cfg.Datas
return visitor.Accept(this, x);
}
public override TR Apply<T1, T2, TR>(IDataFuncVisitor<T1, T2, TR> visitor, T1 x, T2 y)
{
return visitor.Accept(this, x, y);
}
public override bool Equals(object obj)
{
return obj is DVector2 o && o.Value == this.Value;

View File

@ -33,6 +33,11 @@ namespace Luban.Job.Cfg.Datas
return visitor.Accept(this, x);
}
public override TR Apply<T1, T2, TR>(IDataFuncVisitor<T1, T2, TR> visitor, T1 x, T2 y)
{
return visitor.Accept(this, x, y);
}
public override bool Equals(object obj)
{
return obj is DVector3 o && o.Value == this.Value;

View File

@ -33,6 +33,11 @@ namespace Luban.Job.Cfg.Datas
return visitor.Accept(this, x);
}
public override TR Apply<T1, T2, TR>(IDataFuncVisitor<T1, T2, TR> visitor, T1 x, T2 y)
{
return visitor.Accept(this, x, y);
}
public override bool Equals(object obj)
{
return obj is DVector4 o && o.Value == this.Value;

View File

@ -360,8 +360,9 @@ namespace Luban.Job.Cfg.Defs
case "ref":
case "path":
case "range":
case "sep":
{
cf.Type = cf.Type + "&(" + attrs[i] + ")";
cf.Type = cf.Type + "#(" + attrs[i] + ")";
break;
}
case "group":
@ -431,7 +432,7 @@ namespace Luban.Job.Cfg.Defs
new CfgField() { Name = "mode", Type = "string" },
new CfgField() { Name = "group", Type = "string" },
new CfgField() { Name = "comment", Type = "string" },
new CfgField() { Name = "define_from_excel", Type = "bool" },
new CfgField() { Name = "define_from_file", Type = "bool" },
new CfgField() { Name = "input", Type = "string" },
new CfgField() { Name = "output", Type = "string" },
new CfgField() { Name = "patch_input", Type = "string" },
@ -467,7 +468,7 @@ namespace Luban.Job.Cfg.Defs
string mode = (data.GetField("mode") as DString).Value.Trim();
string group = (data.GetField("group") as DString).Value.Trim();
string comment = (data.GetField("comment") as DString).Value.Trim();
bool isDefineFromExcel = (data.GetField("define_from_excel") as DBool).Value;
bool isDefineFromExcel = (data.GetField("define_from_file") as DBool).Value;
string inputFile = (data.GetField("input") as DString).Value.Trim();
string patchInput = (data.GetField("patch_input") as DString).Value.Trim();
string tags = (data.GetField("tags") as DString).Value.Trim();
@ -726,12 +727,12 @@ namespace Luban.Job.Cfg.Defs
string refStr = XmlUtil.GetOptionalAttribute(e, "ref");
if (!string.IsNullOrWhiteSpace(refStr))
{
typeStr = typeStr + "&(ref=" + refStr + ")";
typeStr = typeStr + "#(ref=" + refStr + ")";
}
string pathStr = XmlUtil.GetOptionalAttribute(e, "path");
if (!string.IsNullOrWhiteSpace(pathStr))
{
typeStr = typeStr + "&(path=" + pathStr + ")";
typeStr = typeStr + "#(path=" + pathStr + ")";
}
return CreateField(defineFile, XmlUtil.GetRequiredAttribute(e, "name"),

View File

@ -8,6 +8,9 @@ namespace Luban.Job.Cfg
[Option('s', "service", Required = true, HelpText = "service")]
public string Service { get; set; }
[Option("gen_types", Required = true, HelpText = "code_cs_bin,code_cs_json,code_cs_unity_json,code_lua_bin,code_java_bin,code_java_json,code_go_bin,code_go_json,code_cpp_bin,code_python3_json,code_typescript_bin,code_typescript_json,code_rust_json,code_protobuf,code_template,data_bin,data_lua,data_json,data_json2,data_json_monolithic,data_resources,data_template,data_protobuf,convert_json,convert_lua,convert_xlsx . can be multi")]
public string GenType { get; set; }
[Option("input_data_dir", Required = true, HelpText = "input data dir")]
public string InputDataDir { get; set; }
@ -17,24 +20,15 @@ namespace Luban.Job.Cfg
[Option("output_data_dir", Required = false, HelpText = "output data directory")]
public string OutputDataDir { get; set; }
[Option("input_convert_data_dir", Required = false, HelpText = "override input data dir with convert data dir")]
[Option("input:convert_data_dir", Required = false, HelpText = "override input data dir with convert data dir")]
public string InputConvertDataDir { get; set; }
[Option("output_data_resource_list_file", Required = false, HelpText = "output resource list file")]
[Option("output:data:resource_list_file", Required = false, HelpText = "output resource list file")]
public string OutputDataResourceListFile { get; set; }
[Option("output_data_json_monolithic_file", Required = false, HelpText = "output monolithic json file")]
[Option("output:data:json_monolithic_file", Required = false, HelpText = "output monolithic json file")]
public string OutputDataJsonMonolithicFile { get; set; }
[Option("gen_types", Required = true, HelpText = "code_cs_bin,code_cs_json,code_cs_unity_json,code_lua_bin,code_java_bin,code_java_json,code_go_bin,code_go_json,code_cpp_bin,code_python3_json,code_typescript_bin,code_typescript_json,code_rust_json,code_protobuf,code_template,data_bin,data_lua,data_json,data_json2,data_json_monolithic,data_resources,data_template,data_protobuf,convert_json,convert_lua,convert_xlsx . can be multi")]
public string GenType { get; set; }
[Option("template:data:file", Required = false, HelpText = "template name. use with gen_types=data_template")]
public string TemplateDataFile { get; set; }
[Option("template:code:dir", Required = false, HelpText = "code template dir. use with gen_types=code_template")]
public string TemplateCodeDir { get; set; }
[Option("output:data:file_extension", Required = false, HelpText = "data file name extension. default choose by gen_type")]
public string OutputDataFileExtension { get; set; }
@ -44,6 +38,14 @@ namespace Luban.Job.Cfg
[Option("output:exclude_tags", Required = false, HelpText = "export exclude tags. default export all tags")]
public string OutputExcludeTags { get; set; } = "";
[Option("template:data:file", Required = false, HelpText = "template name. use with gen_types=data_template")]
public string TemplateDataFile { get; set; }
[Option("template:code:dir", Required = false, HelpText = "code template dir. use with gen_types=code_template")]
public string TemplateCodeDir { get; set; }
[Option("l10n:timezone", Required = false, HelpText = "timezone")]
public string L10nTimeZone { get; set; }

View File

@ -72,7 +72,7 @@ namespace Luban.Job.Cfg.Generate
foreach (var rec in records)
{
var fillVisitor = new FillSheetVisitor(dataRangeArray, title.ToIndex + 1, totalRowCount);
totalRowCount += rec.Data.Apply(fillVisitor, title);
totalRowCount += rec.Data.Apply(fillVisitor, TBean.Create(false, rec.Data.Type, null), title);
}
using var workbook = new XLWorkbook(XLEventTracking.Disabled);

View File

@ -157,7 +157,7 @@ namespace Luban.Job.Cfg.Utils
return ((DefBean)type.Bean).Sep;
}
public static string GetTypeSep(TType type)
public static string GetCollectionElementTypeSep(TType type)
{
if (type.Tags != null && type.Tags.TryGetValue("sep", out var s) && !string.IsNullOrWhiteSpace(s))
{

View File

@ -193,7 +193,7 @@ namespace Luban.Job.Common.Defs
public TType CreateType(string module, string type)
{
int sepIndex = DefUtil.IndexOfElementTypeSep(type);
int sepIndex = DefUtil.IndexOfBaseTypeEnd(type);
if (sepIndex > 0)
{
string containerTypeAndTags = DefUtil.TrimBracePairs(type.Substring(0, sepIndex));
@ -294,14 +294,8 @@ namespace Luban.Job.Common.Defs
{
case "array": return TArray.Create(false, containerTags, CreateNotContainerType(module, elementType));
case "list": return TList.Create(false, containerTags, CreateNotContainerType(module, elementType), true);
case "linkedlist": return TList.Create(false, containerTags, CreateNotContainerType(module, elementType), false);
case "arraylist": return TList.Create(false, containerTags, CreateNotContainerType(module, elementType), true);
case "set": return TSet.Create(false, containerTags, CreateNotContainerType(module, elementType), false);
case "hashset": return TSet.Create(false, containerTags, CreateNotContainerType(module, elementType), false);
case "treeset": return TSet.Create(false, containerTags, CreateNotContainerType(module, elementType), true);
case "map": return CreateMapType(module, containerTags, elementType, false);
case "treemap": return CreateMapType(module, containerTags, elementType, true);
case "hashmap": return CreateMapType(module, containerTags, elementType, false);
default:
{
throw new ArgumentException($"invalid container type. module:'{module}' container:'{containerType}' element:'{elementType}'");

View File

@ -30,6 +30,11 @@ namespace Luban.Job.Common.Types
return Tags != null && Tags.TryGetValue(attrName, out var value) ? value : null;
}
public string OrTag(string attrName, string defaultValue)
{
return Tags != null && Tags.TryGetValue(attrName, out var value) ? value : defaultValue;
}
public abstract bool TryParseFrom(string s);
public virtual void Compile(DefFieldBase field)

View File

@ -8,10 +8,28 @@ namespace Luban.Job.Common.Utils
{
public class DefUtil
{
private static readonly char[] s_attrSep = new char[] { '|', '#', '&' };
private static readonly char[] s_attrSep = new char[] { '#' };
private static readonly char[] s_attrKeyValueSep = new char[] { '=', ':' };
private static void AddAttr(Dictionary<string, string> attrs, string rawPair)
{
var pair = TrimBracePairs(rawPair);
int sepIndex = pair.IndexOfAny(s_attrKeyValueSep);
string key;
string value;
if (sepIndex >= 0)
{
key = pair.Substring(0, sepIndex).Trim();
value = pair.Substring(sepIndex + 1).Trim();
}
else
{
key = value = pair.Trim();
}
attrs.Add(key, value);
}
public static Dictionary<string, string> ParseAttrs(string tags)
{
var am = new Dictionary<string, string>();
@ -19,29 +37,43 @@ namespace Luban.Job.Common.Utils
{
return am;
}
foreach (var rawPair in tags.Split(s_attrSep))
int braceDepth = 0;
int pairStart = 0;
for (int i = 0; i < tags.Length; i++)
{
var pair = TrimBracePairs(rawPair);
int sepIndex = pair.IndexOfAny(s_attrKeyValueSep);
if (sepIndex >= 0)
var c = tags[i];
if (c == '(' || c == '[' || c == '{')
{
#if !LUBAN_LITE
am.Add(pair[..sepIndex].Trim(), pair[(sepIndex + 1)..].Trim());
#else
am.Add(pair.Substring(0, sepIndex).Trim(), pair.Substring(sepIndex + 1).Trim());
#endif
++braceDepth;
}
else
else if (c == ')' || c == ']' || c == '}')
{
am.Add(pair.Trim(), pair.Trim());
--braceDepth;
}
if (braceDepth == 0 && c == '#')
{
string rawPair = tags.Substring(pairStart, i - pairStart);
pairStart = i + 1;
AddAttr(am, rawPair);
}
}
if (braceDepth != 0)
{
throw new Exception($"非法tags:{tags}");
}
if (pairStart < tags.Length)
{
AddAttr(am, tags.Substring(pairStart));
}
return am;
}
public static int IndexOfElementTypeSep(string s)
public static int IndexOfBaseTypeEnd(string s)
{
int braceDepth = 0;
int firstSharpIndex = -1;// '#'
for (int i = 0; i < s.Length; i++)
{
var c = s[i];
@ -53,6 +85,48 @@ namespace Luban.Job.Common.Utils
{
--braceDepth;
}
if (c == '#' && firstSharpIndex == -1)
{
firstSharpIndex = i;
}
if (braceDepth == 0 && (c == ',' || c == ';'))
{
var strContainBaseType = firstSharpIndex > 0 ? s.Substring(0, firstSharpIndex) : s.Substring(0, i);
strContainBaseType = strContainBaseType.Replace("(", "").Replace(")", "").Replace("[", "").Replace("]", "");
if (strContainBaseType == "array" || strContainBaseType == "list" || strContainBaseType == "set" || strContainBaseType == "map")
{
return i;
}
else
{
return -1;
}
}
}
return -1;
}
public static int IndexOfElementTypeSep(string s)
{
int braceDepth = 0;
int firstSharpIndex = -1;// '#'
for (int i = 0; i < s.Length; i++)
{
var c = s[i];
if (c == '(' || c == '[' || c == '{')
{
++braceDepth;
}
else if (c == ')' || c == ')' || c == '}')
{
--braceDepth;
}
if (c == '#' && firstSharpIndex == -1)
{
firstSharpIndex = i;
}
if (braceDepth == 0 && (c == ',' || c == ';'))
{
@ -95,12 +169,12 @@ namespace Luban.Job.Common.Utils
{
++braceDepth;
}
else if (c == ')' || c == ')' || c == '}')
else if (c == ')' || c == ']' || c == '}')
{
--braceDepth;
}
if (braceDepth == 0 && (c == '#' || c == '&' || c == '|'))
if (braceDepth == 0 && (c == '#'))
{
return (s.Substring(0, i), ParseAttrs(s.Substring(i + 1)));
}