1609 lines
35 KiB
C#
1609 lines
35 KiB
C#
using MsgPack;
|
|
using System.IO;
|
|
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using CodeStage.AntiCheat.ObscuredTypes;
|
|
|
|
namespace metagen {
|
|
|
|
//NOTE: don't change existing values
|
|
public enum MetaIoError
|
|
{
|
|
NONE = 0,
|
|
NO_SPACE_LEFT_IN_ARRAY = 1,
|
|
HAS_LEFT_SPACE = 2,
|
|
ARRAY_STACK_IS_EMPTY = 3,
|
|
FAIL_READ = 4,
|
|
TYPE_DONT_MATCH = 5,
|
|
DATA_MISSING = 7,
|
|
GENERIC = 10,
|
|
}
|
|
|
|
public class MetaException : Exception
|
|
{
|
|
public MetaIoError err;
|
|
|
|
public MetaException(MetaIoError err)
|
|
{
|
|
this.err = err;
|
|
}
|
|
}
|
|
|
|
[System.Flags]
|
|
public enum MetaSyncContextOpts
|
|
{
|
|
NONE = 0,
|
|
USE_MASK = 1
|
|
}
|
|
|
|
[System.Flags]
|
|
public enum MetaSyncFieldOpts
|
|
{
|
|
NONE = 0,
|
|
SKIP_NOT_IN_MASK = 1,
|
|
SKIP_OPTIONAL = 2
|
|
}
|
|
|
|
public struct MetaSyncContext
|
|
{
|
|
public bool is_read;
|
|
public IDataReader reader;
|
|
public IDataWriter writer;
|
|
public Func<uint, IMetaStruct> factory;
|
|
public MetaSyncContextOpts opts;
|
|
|
|
public bool CanReadField(MetaSyncFieldOpts opts)
|
|
{
|
|
return is_read && (opts & MetaSyncFieldOpts.SKIP_NOT_IN_MASK) != MetaSyncFieldOpts.SKIP_NOT_IN_MASK;
|
|
}
|
|
|
|
public bool CanWriteField(MetaSyncFieldOpts opts)
|
|
{
|
|
return !is_read && (opts & MetaSyncFieldOpts.SKIP_NOT_IN_MASK) != MetaSyncFieldOpts.SKIP_NOT_IN_MASK;
|
|
}
|
|
|
|
public bool IsMaskUsed()
|
|
{
|
|
return (opts & MetaSyncContextOpts.USE_MASK) > 0;
|
|
}
|
|
|
|
public static MetaSyncContext NewForRead(Func<uint, IMetaStruct> factory, IDataReader reader, MetaSyncContextOpts opts = 0)
|
|
{
|
|
var ctx = new MetaSyncContext() {
|
|
is_read = true,
|
|
reader = reader,
|
|
writer = null,
|
|
factory = factory,
|
|
opts = opts
|
|
};
|
|
return ctx;
|
|
}
|
|
|
|
public static MetaSyncContext NewForWrite(IDataWriter writer, MetaSyncContextOpts opts = 0)
|
|
{
|
|
var ctx = new MetaSyncContext() {
|
|
is_read = false,
|
|
reader = null,
|
|
writer = writer,
|
|
opts = opts
|
|
};
|
|
return ctx;
|
|
}
|
|
}
|
|
|
|
public interface IMetaStruct
|
|
{
|
|
uint CLASS_ID();
|
|
|
|
int getFieldsCount();
|
|
int getWritableFieldsCount();
|
|
|
|
void syncFields(MetaSyncContext ctx);
|
|
|
|
void reset();
|
|
}
|
|
|
|
public interface IMetaCloneable
|
|
{
|
|
void copy(IMetaStruct source);
|
|
IMetaStruct clone();
|
|
}
|
|
|
|
public abstract class BaseMetaStruct : IMetaStruct
|
|
{
|
|
public virtual uint CLASS_ID() { return 0; }
|
|
|
|
public virtual int getFieldsCount() { return 0; }
|
|
public virtual int getWritableFieldsCount() { return 0; }
|
|
|
|
public virtual void reset() {}
|
|
|
|
public virtual void syncFields(MetaSyncContext ctx) {}
|
|
}
|
|
|
|
public interface IRpcError
|
|
{
|
|
bool isOk();
|
|
}
|
|
|
|
public interface IRpc
|
|
{
|
|
int getCode();
|
|
IMetaStruct getRequest();
|
|
IMetaStruct getResponse();
|
|
IRpcError getError();
|
|
void setError(IRpcError err);
|
|
}
|
|
|
|
public interface IDataReader
|
|
{
|
|
MetaIoError ReadI8(ref sbyte v);
|
|
MetaIoError ReadU8(ref byte v);
|
|
MetaIoError ReadI16(ref short v);
|
|
MetaIoError ReadU16(ref ushort v);
|
|
MetaIoError ReadI32(ref int v);
|
|
MetaIoError ReadU32(ref uint v);
|
|
MetaIoError ReadU64(ref ulong v);
|
|
MetaIoError ReadI64(ref long v);
|
|
MetaIoError ReadFloat(ref float v);
|
|
MetaIoError ReadBool(ref bool v);
|
|
MetaIoError ReadDouble(ref double v);
|
|
MetaIoError ReadString(ref string v);
|
|
MetaIoError ReadRaw(ref byte[] v, ref int vlen);
|
|
MetaIoError ReadNil();
|
|
MetaIoError BeginContainer();
|
|
MetaIoError GetContainerSize(ref int v);
|
|
MetaIoError EndContainer();
|
|
}
|
|
|
|
public interface IDataWriter
|
|
{
|
|
MetaIoError WriteI8(sbyte v);
|
|
MetaIoError WriteU8(byte v);
|
|
MetaIoError WriteI16(short v);
|
|
MetaIoError WriteU16(ushort v);
|
|
MetaIoError WriteI32(int v);
|
|
MetaIoError WriteU32(uint v);
|
|
MetaIoError WriteI64(long v);
|
|
MetaIoError WriteU64(ulong v);
|
|
MetaIoError WriteFloat(float v);
|
|
MetaIoError WriteBool(bool v);
|
|
MetaIoError WriteDouble(double v);
|
|
MetaIoError WriteString(string v);
|
|
MetaIoError WriteRaw(byte[] v);
|
|
MetaIoError BeginContainer(int len);
|
|
MetaIoError EndContainer();
|
|
MetaIoError End();
|
|
MetaIoError WriteNil();
|
|
}
|
|
|
|
public static class Meta
|
|
{
|
|
public delegate void LogCb(string text);
|
|
public static LogCb LogError = DefaultLog;
|
|
public static LogCb LogWarn = DefaultLog;
|
|
public static LogCb LogDebug = DefaultLog;
|
|
|
|
public struct BitfieldsContext
|
|
{
|
|
long fields_mask;
|
|
int curr_field_idx;
|
|
|
|
MetaSyncContext ctx;
|
|
|
|
readonly bool use_mask;
|
|
|
|
public BitfieldsContext(MetaSyncContext ctx, long fields_mask)
|
|
{
|
|
this.ctx = ctx;
|
|
this.use_mask = ctx.IsMaskUsed();
|
|
this.fields_mask = fields_mask;
|
|
this.curr_field_idx = -1;
|
|
}
|
|
|
|
public void SyncMaskHeader()
|
|
{
|
|
if(!use_mask)
|
|
return;
|
|
|
|
if(ctx.is_read)
|
|
{
|
|
ensure(ctx.reader.ReadNil());
|
|
ensure(ctx.reader.ReadI64(ref fields_mask));
|
|
}
|
|
else
|
|
{
|
|
ensure(ctx.writer.WriteNil());
|
|
ensure(ctx.writer.WriteI64(fields_mask));
|
|
}
|
|
}
|
|
|
|
public MetaSyncFieldOpts GetCurrentOpts()
|
|
{
|
|
if(!use_mask || curr_field_idx < 0 || curr_field_idx > 63)
|
|
return 0;
|
|
|
|
long curr_field_ptr = 1L << curr_field_idx;
|
|
if((curr_field_ptr & fields_mask) == 0)
|
|
return MetaSyncFieldOpts.SKIP_NOT_IN_MASK;
|
|
|
|
return 0;
|
|
}
|
|
|
|
public MetaSyncFieldOpts GetNextOpts()
|
|
{
|
|
Advance();
|
|
return GetCurrentOpts();
|
|
}
|
|
|
|
public void Advance()
|
|
{
|
|
curr_field_idx++;
|
|
#if DEBUG
|
|
if(curr_field_idx > 64)
|
|
{
|
|
LogError("overflow in @bitfields struct. Does it have > 64 fields?");
|
|
throw new MetaException(MetaIoError.GENERIC);
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
public const int MASK_HEADER_FIELDS_COUNT = 2;
|
|
|
|
public static List<int> tmp_enums_list = new List<int>();
|
|
|
|
static void DefaultLog(string s)
|
|
{}
|
|
|
|
public delegate string L_TCb(string text);
|
|
public static L_TCb L_T;
|
|
|
|
public delegate string L_FromListCb(IList<string> list);
|
|
public static L_FromListCb L_FromList;
|
|
|
|
public delegate string L_PFromListCb(IList<string> list, double force_n = double.NaN);
|
|
public static L_PFromListCb L_Pluralize;
|
|
|
|
public delegate bool L_PListCheckCb(IList<string> list, string plural_mark);
|
|
public static L_PListCheckCb L_IsPlural;
|
|
|
|
public static void ensure(MetaIoError err)
|
|
{
|
|
if(err != 0)
|
|
throw new MetaException(err);
|
|
}
|
|
|
|
static bool canSkipOptionalRead(MetaIoError err, MetaSyncFieldOpts opts)
|
|
{
|
|
return err != 0 && (opts & MetaSyncFieldOpts.SKIP_OPTIONAL) == MetaSyncFieldOpts.SKIP_OPTIONAL;
|
|
}
|
|
|
|
static MetaIoError checkRead(MetaIoError err, MetaSyncFieldOpts opts)
|
|
{
|
|
if(canSkipOptionalRead(err, opts))
|
|
{
|
|
LogWarn("Skipping optional field");
|
|
return MetaIoError.NONE;
|
|
}
|
|
else
|
|
return err;
|
|
}
|
|
|
|
public static void Sync(MetaSyncContext ctx, ref byte[] v, MetaSyncFieldOpts opts = 0)
|
|
{
|
|
if(ctx.CanReadField(opts))
|
|
{
|
|
int len = 0;
|
|
ensure(checkRead(ctx.reader.ReadRaw(ref v, ref len), opts));
|
|
}
|
|
else if(ctx.CanWriteField(opts))
|
|
ensure(ctx.writer.WriteRaw(v));
|
|
}
|
|
|
|
public static void Sync(MetaSyncContext ctx, ref string v, MetaSyncFieldOpts opts = 0)
|
|
{
|
|
if(ctx.CanReadField(opts))
|
|
ensure(checkRead(ctx.reader.ReadString(ref v), opts));
|
|
else if(ctx.CanWriteField(opts))
|
|
ensure(ctx.writer.WriteString(v));
|
|
}
|
|
|
|
public static void Sync(MetaSyncContext ctx, ref ObscuredString v, MetaSyncFieldOpts opts = 0)
|
|
{
|
|
if(ctx.CanReadField(opts))
|
|
{
|
|
string tmp = string.Empty;
|
|
ensure(checkRead(ctx.reader.ReadString(ref tmp), opts));
|
|
v = tmp;
|
|
}
|
|
else if(ctx.CanWriteField(opts))
|
|
ensure(ctx.writer.WriteString(v));
|
|
}
|
|
|
|
public static void Sync(MetaSyncContext ctx, ref long v, MetaSyncFieldOpts opts = 0)
|
|
{
|
|
if(ctx.CanReadField(opts))
|
|
ensure(checkRead(ctx.reader.ReadI64(ref v), opts));
|
|
else if(ctx.CanWriteField(opts))
|
|
ensure(ctx.writer.WriteI64(v));
|
|
}
|
|
|
|
public static void Sync(MetaSyncContext ctx, ref ObscuredLong v, MetaSyncFieldOpts opts = 0)
|
|
{
|
|
if(ctx.CanReadField(opts))
|
|
{
|
|
long tmp = 0;
|
|
ensure(checkRead(ctx.reader.ReadI64(ref tmp), opts));
|
|
v = tmp;
|
|
}
|
|
else if(ctx.CanWriteField(opts))
|
|
ensure(ctx.writer.WriteI64(v));
|
|
}
|
|
|
|
public static void Sync(MetaSyncContext ctx, ref int v, MetaSyncFieldOpts opts = 0)
|
|
{
|
|
if(ctx.CanReadField(opts))
|
|
ensure(checkRead(ctx.reader.ReadI32(ref v), opts));
|
|
else if(ctx.CanWriteField(opts))
|
|
ensure(ctx.writer.WriteI32(v));
|
|
}
|
|
|
|
public static void Sync(MetaSyncContext ctx, ref ObscuredInt v, MetaSyncFieldOpts opts = 0)
|
|
{
|
|
if(ctx.CanReadField(opts))
|
|
{
|
|
int tmp = 0;
|
|
ensure(checkRead(ctx.reader.ReadI32(ref tmp), opts));
|
|
v = tmp;
|
|
}
|
|
else if(ctx.CanWriteField(opts))
|
|
ensure(ctx.writer.WriteI32(v));
|
|
}
|
|
|
|
public static void Sync(MetaSyncContext ctx, ref short v, MetaSyncFieldOpts opts = 0)
|
|
{
|
|
if(ctx.CanReadField(opts))
|
|
ensure(checkRead(ctx.reader.ReadI16(ref v), opts));
|
|
else if(ctx.CanWriteField(opts))
|
|
ensure(ctx.writer.WriteI16(v));
|
|
}
|
|
|
|
public static void Sync(MetaSyncContext ctx, ref ObscuredShort v, MetaSyncFieldOpts opts = 0)
|
|
{
|
|
if(ctx.CanReadField(opts))
|
|
{
|
|
short tmp = 0;
|
|
ensure(checkRead(ctx.reader.ReadI16(ref tmp), opts));
|
|
v = tmp;
|
|
}
|
|
else if(ctx.CanWriteField(opts))
|
|
ensure(ctx.writer.WriteI16(v));
|
|
}
|
|
|
|
public static void Sync(MetaSyncContext ctx, ref sbyte v, MetaSyncFieldOpts opts = 0)
|
|
{
|
|
if(ctx.CanReadField(opts))
|
|
ensure(checkRead(ctx.reader.ReadI8(ref v), opts));
|
|
else if(ctx.CanWriteField(opts))
|
|
ensure(ctx.writer.WriteI8(v));
|
|
}
|
|
|
|
public static void Sync(MetaSyncContext ctx, ref ObscuredSByte v, MetaSyncFieldOpts opts = 0)
|
|
{
|
|
if(ctx.CanReadField(opts))
|
|
{
|
|
sbyte tmp = 0;
|
|
ensure(checkRead(ctx.reader.ReadI8(ref tmp), opts));
|
|
v = tmp;
|
|
}
|
|
else if(ctx.CanWriteField(opts))
|
|
ensure(ctx.writer.WriteI8(v));
|
|
}
|
|
|
|
public static void Sync(MetaSyncContext ctx, ref ulong v, MetaSyncFieldOpts opts = 0)
|
|
{
|
|
if(ctx.CanReadField(opts))
|
|
ensure(checkRead(ctx.reader.ReadU64(ref v), opts));
|
|
else if(ctx.CanWriteField(opts))
|
|
ensure(ctx.writer.WriteU64(v));
|
|
}
|
|
|
|
public static void Sync(MetaSyncContext ctx, ref ObscuredULong v, MetaSyncFieldOpts opts = 0)
|
|
{
|
|
if(ctx.CanReadField(opts))
|
|
{
|
|
ulong tmp = 0;
|
|
ensure(checkRead(ctx.reader.ReadU64(ref tmp), opts));
|
|
v = tmp;
|
|
}
|
|
else if(ctx.CanWriteField(opts))
|
|
ensure(ctx.writer.WriteU64(v));
|
|
}
|
|
|
|
public static void Sync(MetaSyncContext ctx, ref ushort v, MetaSyncFieldOpts opts = 0)
|
|
{
|
|
if(ctx.CanReadField(opts))
|
|
ensure(checkRead(ctx.reader.ReadU16(ref v), opts));
|
|
else if(ctx.CanWriteField(opts))
|
|
ensure(ctx.writer.WriteU16(v));
|
|
}
|
|
|
|
public static void Sync(MetaSyncContext ctx, ref ObscuredUShort v, MetaSyncFieldOpts opts = 0)
|
|
{
|
|
if(ctx.CanReadField(opts))
|
|
{
|
|
ushort tmp = 0;
|
|
ensure(checkRead(ctx.reader.ReadU16(ref tmp), opts));
|
|
v = tmp;
|
|
}
|
|
else if(ctx.CanWriteField(opts))
|
|
ensure(ctx.writer.WriteU16(v));
|
|
}
|
|
|
|
public static void Sync(MetaSyncContext ctx, ref uint v, MetaSyncFieldOpts opts = 0)
|
|
{
|
|
if(ctx.CanReadField(opts))
|
|
ensure(checkRead(ctx.reader.ReadU32(ref v), opts));
|
|
else if(ctx.CanWriteField(opts))
|
|
ensure(ctx.writer.WriteU32(v));
|
|
}
|
|
|
|
public static void Sync(MetaSyncContext ctx, ref ObscuredUInt v, MetaSyncFieldOpts opts = 0)
|
|
{
|
|
if(ctx.CanReadField(opts))
|
|
{
|
|
uint tmp = 0;
|
|
ensure(checkRead(ctx.reader.ReadU32(ref tmp), opts));
|
|
v = tmp;
|
|
}
|
|
else if(ctx.CanWriteField(opts))
|
|
ensure(ctx.writer.WriteU32(v));
|
|
}
|
|
|
|
public static void Sync(MetaSyncContext ctx, ref byte v, MetaSyncFieldOpts opts = 0)
|
|
{
|
|
if(ctx.CanReadField(opts))
|
|
ensure(checkRead(ctx.reader.ReadU8(ref v), opts));
|
|
else if(ctx.CanWriteField(opts))
|
|
ensure(ctx.writer.WriteU8(v));
|
|
}
|
|
|
|
public static void Sync(MetaSyncContext ctx, ref ObscuredByte v, MetaSyncFieldOpts opts = 0)
|
|
{
|
|
if(ctx.CanReadField(opts))
|
|
{
|
|
byte tmp = 0;
|
|
ensure(checkRead(ctx.reader.ReadU8(ref tmp), opts));
|
|
v = tmp;
|
|
}
|
|
else if(ctx.CanWriteField(opts))
|
|
ensure(ctx.writer.WriteU8(v));
|
|
}
|
|
|
|
public static void Sync(MetaSyncContext ctx, ref bool v, MetaSyncFieldOpts opts = 0)
|
|
{
|
|
if(ctx.CanReadField(opts))
|
|
ensure(checkRead(ctx.reader.ReadBool(ref v), opts));
|
|
else if(ctx.CanWriteField(opts))
|
|
ensure(ctx.writer.WriteBool(v));
|
|
}
|
|
|
|
public static void Sync(MetaSyncContext ctx, ref ObscuredBool v, MetaSyncFieldOpts opts = 0)
|
|
{
|
|
if(ctx.CanReadField(opts))
|
|
{
|
|
bool tmp = false;
|
|
ensure(checkRead(ctx.reader.ReadBool(ref tmp), opts));
|
|
v = tmp;
|
|
}
|
|
else if(ctx.CanWriteField(opts))
|
|
ensure(ctx.writer.WriteBool(v));
|
|
}
|
|
|
|
public static void Sync(MetaSyncContext ctx, ref float v, MetaSyncFieldOpts opts = 0)
|
|
{
|
|
if(ctx.CanReadField(opts))
|
|
ensure(checkRead(ctx.reader.ReadFloat(ref v), opts));
|
|
else if(ctx.CanWriteField(opts))
|
|
ensure(ctx.writer.WriteFloat(v));
|
|
}
|
|
|
|
public static void Sync(MetaSyncContext ctx, ref ObscuredFloat v, MetaSyncFieldOpts opts = 0)
|
|
{
|
|
if(ctx.CanReadField(opts))
|
|
{
|
|
float tmp = 0f;
|
|
ensure(checkRead(ctx.reader.ReadFloat(ref tmp), opts));
|
|
v = tmp;
|
|
}
|
|
else if(ctx.CanWriteField(opts))
|
|
ensure(ctx.writer.WriteFloat(v));
|
|
}
|
|
|
|
public static void Sync(MetaSyncContext ctx, ref double v, MetaSyncFieldOpts opts = 0)
|
|
{
|
|
if(ctx.CanReadField(opts))
|
|
ensure(checkRead(ctx.reader.ReadDouble(ref v), opts));
|
|
else if(ctx.CanWriteField(opts))
|
|
ensure(ctx.writer.WriteDouble(v));
|
|
}
|
|
|
|
public static void Sync(MetaSyncContext ctx, ref ObscuredDouble v, MetaSyncFieldOpts opts = 0)
|
|
{
|
|
if(ctx.CanReadField(opts))
|
|
{
|
|
double tmp = 0;
|
|
ensure(checkRead(ctx.reader.ReadDouble(ref tmp), opts));
|
|
v = tmp;
|
|
}
|
|
else if(ctx.CanWriteField(opts))
|
|
ensure(ctx.writer.WriteDouble(v));
|
|
}
|
|
|
|
static int SyncBeginListGetSize(MetaSyncContext ctx, IList v, MetaSyncFieldOpts opts)
|
|
{
|
|
if(ctx.CanReadField(opts))
|
|
{
|
|
var err = ctx.reader.BeginContainer();
|
|
if(canSkipOptionalRead(err, opts))
|
|
{
|
|
LogWarn("Skipping optional array field");
|
|
return -1;
|
|
}
|
|
ensure(err);
|
|
|
|
int size = 0;
|
|
ensure(ctx.reader.GetContainerSize(ref size));
|
|
|
|
return size;
|
|
}
|
|
else if(ctx.CanWriteField(opts))
|
|
{
|
|
int size = v == null ? 0 : v.Count;
|
|
ensure(ctx.writer.BeginContainer(size));
|
|
return size;
|
|
}
|
|
else
|
|
return -1;
|
|
}
|
|
|
|
static int SyncBeginList<T>(MetaSyncContext ctx, List<T> v, ref MetaSyncFieldOpts opts)
|
|
{
|
|
int size = SyncBeginListGetSize(ctx, v, opts);
|
|
if(size == -1)
|
|
return size;
|
|
|
|
if(ctx.is_read && v.Capacity < size)
|
|
v.Capacity = size;
|
|
|
|
//NOTE: unsetting opts for array items
|
|
opts &= ~MetaSyncFieldOpts.SKIP_OPTIONAL;
|
|
opts &= ~MetaSyncFieldOpts.SKIP_NOT_IN_MASK;
|
|
return size;
|
|
}
|
|
|
|
static void SyncEndList(MetaSyncContext ctx, IList v)
|
|
{
|
|
if(ctx.is_read)
|
|
ensure(ctx.reader.EndContainer());
|
|
else
|
|
ensure(ctx.writer.EndContainer());
|
|
}
|
|
|
|
public static void Sync(MetaSyncContext ctx, List<string> v, MetaSyncFieldOpts opts = 0)
|
|
{
|
|
int size = SyncBeginList(ctx, v, ref opts);
|
|
if(size == -1)
|
|
return;
|
|
for(int i = 0; i < size; ++i)
|
|
{
|
|
var tmp = ctx.is_read ? "" : v[i];
|
|
Sync(ctx, ref tmp, opts);
|
|
if(ctx.is_read)
|
|
v.Add(tmp);
|
|
}
|
|
SyncEndList(ctx, v);
|
|
}
|
|
|
|
public static void Sync(MetaSyncContext ctx, List<long> v, MetaSyncFieldOpts opts = 0)
|
|
{
|
|
int size = SyncBeginList(ctx, v, ref opts);
|
|
if(size == -1)
|
|
return;
|
|
for(int i = 0; i < size; ++i)
|
|
{
|
|
var tmp = ctx.is_read ? default(long) : v[i];
|
|
Sync(ctx, ref tmp, opts);
|
|
if(ctx.is_read)
|
|
v.Add(tmp);
|
|
}
|
|
SyncEndList(ctx, v);
|
|
}
|
|
|
|
public static void Sync(MetaSyncContext ctx, List<int> v, MetaSyncFieldOpts opts = 0)
|
|
{
|
|
int size = SyncBeginList(ctx, v, ref opts);
|
|
if(size == -1)
|
|
return;
|
|
for(int i = 0; i < size; ++i)
|
|
{
|
|
var tmp = ctx.is_read ? default(int) : v[i];
|
|
Sync(ctx, ref tmp, opts);
|
|
if(ctx.is_read)
|
|
v.Add(tmp);
|
|
}
|
|
SyncEndList(ctx, v);
|
|
}
|
|
|
|
public static void Sync(MetaSyncContext ctx, List<short> v, MetaSyncFieldOpts opts = 0)
|
|
{
|
|
int size = SyncBeginList(ctx, v, ref opts);
|
|
if(size == -1)
|
|
return;
|
|
for(int i = 0; i < size; ++i)
|
|
{
|
|
var tmp = ctx.is_read ? default(short) : v[i];
|
|
Sync(ctx, ref tmp, opts);
|
|
if(ctx.is_read)
|
|
v.Add(tmp);
|
|
}
|
|
SyncEndList(ctx, v);
|
|
}
|
|
|
|
public static void Sync(MetaSyncContext ctx, List<sbyte> v, MetaSyncFieldOpts opts = 0)
|
|
{
|
|
int size = SyncBeginList(ctx, v, ref opts);
|
|
if(size == -1)
|
|
return;
|
|
for(int i = 0; i < size; ++i)
|
|
{
|
|
var tmp = ctx.is_read ? default(sbyte) : v[i];
|
|
Sync(ctx, ref tmp, opts);
|
|
if(ctx.is_read)
|
|
v.Add(tmp);
|
|
}
|
|
SyncEndList(ctx, v);
|
|
}
|
|
|
|
public static void Sync(MetaSyncContext ctx, List<ulong> v, MetaSyncFieldOpts opts = 0)
|
|
{
|
|
int size = SyncBeginList(ctx, v, ref opts);
|
|
if(size == -1)
|
|
return;
|
|
for(int i = 0; i < size; ++i)
|
|
{
|
|
var tmp = ctx.is_read ? default(ulong) : v[i];
|
|
Sync(ctx, ref tmp, opts);
|
|
if(ctx.is_read)
|
|
v.Add(tmp);
|
|
}
|
|
SyncEndList(ctx, v);
|
|
}
|
|
|
|
public static void Sync(MetaSyncContext ctx, List<uint> v, MetaSyncFieldOpts opts = 0)
|
|
{
|
|
int size = SyncBeginList(ctx, v, ref opts);
|
|
if(size == -1)
|
|
return;
|
|
for(int i = 0; i < size; ++i)
|
|
{
|
|
var tmp = ctx.is_read ? default(uint) : v[i];
|
|
Sync(ctx, ref tmp, opts);
|
|
if(ctx.is_read)
|
|
v.Add(tmp);
|
|
}
|
|
SyncEndList(ctx, v);
|
|
}
|
|
|
|
public static void Sync(MetaSyncContext ctx, List<ushort> v, MetaSyncFieldOpts opts = 0)
|
|
{
|
|
int size = SyncBeginList(ctx, v, ref opts);
|
|
if(size == -1)
|
|
return;
|
|
for(int i = 0; i < size; ++i)
|
|
{
|
|
var tmp = ctx.is_read ? default(ushort) : v[i];
|
|
Sync(ctx, ref tmp, opts);
|
|
if(ctx.is_read)
|
|
v.Add(tmp);
|
|
}
|
|
SyncEndList(ctx, v);
|
|
}
|
|
|
|
public static void Sync(MetaSyncContext ctx, List<byte> v, MetaSyncFieldOpts opts = 0)
|
|
{
|
|
int size = SyncBeginList(ctx, v, ref opts);
|
|
if(size == -1)
|
|
return;
|
|
for(int i = 0; i < size; ++i)
|
|
{
|
|
var tmp = ctx.is_read ? default(byte) : v[i];
|
|
Sync(ctx, ref tmp, opts);
|
|
if(ctx.is_read)
|
|
v.Add(tmp);
|
|
}
|
|
SyncEndList(ctx, v);
|
|
}
|
|
|
|
public static void Sync(MetaSyncContext ctx, List<bool> v, MetaSyncFieldOpts opts = 0)
|
|
{
|
|
int size = SyncBeginList(ctx, v, ref opts);
|
|
if(size == -1)
|
|
return;
|
|
for(int i = 0; i < size; ++i)
|
|
{
|
|
var tmp = ctx.is_read ? default(bool) : v[i];
|
|
Sync(ctx, ref tmp, opts);
|
|
if(ctx.is_read)
|
|
v.Add(tmp);
|
|
}
|
|
SyncEndList(ctx, v);
|
|
}
|
|
|
|
public static void Sync(MetaSyncContext ctx, List<float> v, MetaSyncFieldOpts opts = 0)
|
|
{
|
|
int size = SyncBeginList(ctx, v, ref opts);
|
|
if(size == -1)
|
|
return;
|
|
for(int i = 0; i < size; ++i)
|
|
{
|
|
var tmp = ctx.is_read ? default(float) : v[i];
|
|
Sync(ctx, ref tmp, opts);
|
|
if(ctx.is_read)
|
|
v.Add(tmp);
|
|
}
|
|
SyncEndList(ctx, v);
|
|
}
|
|
|
|
public static void Sync(MetaSyncContext ctx, List<double> v, MetaSyncFieldOpts opts = 0)
|
|
{
|
|
int size = SyncBeginList(ctx, v, ref opts);
|
|
if(size == -1)
|
|
return;
|
|
for(int i = 0; i < size; ++i)
|
|
{
|
|
var tmp = ctx.is_read ? default(double) : v[i];
|
|
Sync(ctx, ref tmp, opts);
|
|
if(ctx.is_read)
|
|
v.Add(tmp);
|
|
}
|
|
SyncEndList(ctx, v);
|
|
}
|
|
|
|
public static void Sync<T>(MetaSyncContext ctx, List<T> v, MetaSyncFieldOpts opts = 0) where T : IMetaStruct, new()
|
|
{
|
|
int size = SyncBeginList(ctx, v, ref opts);
|
|
if(size == -1)
|
|
return;
|
|
|
|
if(ctx.is_read)
|
|
v.Clear();
|
|
|
|
for(int i = 0; i < size; ++i)
|
|
{
|
|
var tmp = ctx.is_read ? new T() : v[i];
|
|
Sync(ctx, ref tmp, opts);
|
|
if(ctx.is_read)
|
|
v.Add(tmp);
|
|
}
|
|
SyncEndList(ctx, v);
|
|
}
|
|
|
|
public static IMetaStruct SyncGeneric(MetaSyncContext ctx, IMetaStruct v, MetaSyncFieldOpts opts = 0)
|
|
{
|
|
if(ctx.CanReadField(opts))
|
|
{
|
|
ensure(ctx.reader.BeginContainer());
|
|
|
|
uint clid = 0;
|
|
ensure(ctx.reader.ReadU32(ref clid));
|
|
|
|
//NOTE: when reading we ignore the passed argument
|
|
v = ctx.factory(clid);
|
|
if(v == null)
|
|
{
|
|
LogError("Could not create struct: " + clid);
|
|
ensure(MetaIoError.TYPE_DONT_MATCH);
|
|
}
|
|
|
|
v.reset();
|
|
v.syncFields(ctx);
|
|
ensure(ctx.reader.EndContainer());
|
|
}
|
|
else if(ctx.CanWriteField(opts))
|
|
{
|
|
ensure(ctx.writer.BeginContainer(v.getFieldsCount() + 1));
|
|
ensure(ctx.writer.WriteU32(v.CLASS_ID()));
|
|
v.syncFields(ctx);
|
|
ensure(ctx.writer.EndContainer());
|
|
|
|
}
|
|
return v;
|
|
}
|
|
|
|
public static void SyncGeneric<T>(MetaSyncContext ctx, List<T> v, MetaSyncFieldOpts opts = 0) where T : IMetaStruct, new()
|
|
{
|
|
int size = SyncBeginList(ctx, v, ref opts);
|
|
if(size == -1)
|
|
return;
|
|
for(int i = 0; i < size; ++i)
|
|
{
|
|
var tmp = SyncGeneric(ctx, ctx.is_read ? default(T) : v[i]);
|
|
if(ctx.is_read)
|
|
v.Add((T)tmp);
|
|
}
|
|
SyncEndList(ctx, v);
|
|
}
|
|
|
|
public static void Sync<T>(MetaSyncContext ctx, ref T v, MetaSyncFieldOpts opts = 0) where T : IMetaStruct
|
|
{
|
|
if(ctx.CanReadField(opts))
|
|
{
|
|
var err = ctx.reader.BeginContainer();
|
|
if(canSkipOptionalRead(err, opts))
|
|
{
|
|
LogWarn("Skipping optional struct field");
|
|
return;
|
|
}
|
|
|
|
ensure(err);
|
|
v.reset();
|
|
v.syncFields(ctx);
|
|
ensure(ctx.reader.EndContainer());
|
|
}
|
|
else if(ctx.CanWriteField(opts))
|
|
{
|
|
int array_size = getWriteFieldsCount(ctx, v);
|
|
ensure(ctx.writer.BeginContainer(array_size));
|
|
v.syncFields(ctx);
|
|
ensure(ctx.writer.EndContainer());
|
|
}
|
|
}
|
|
|
|
public static MetaIoError SyncSafe<T>(MetaSyncContext ctx, ref T v, MetaSyncFieldOpts opts = 0) where T : IMetaStruct
|
|
{
|
|
try
|
|
{
|
|
Sync(ctx, ref v, opts);
|
|
}
|
|
catch(MetaException e)
|
|
{
|
|
LogError(e.Message + " " + e.StackTrace);
|
|
return e.err;
|
|
}
|
|
catch(Exception e)
|
|
{
|
|
LogError(e.Message + " " + e.StackTrace);
|
|
return MetaIoError.GENERIC;
|
|
}
|
|
return MetaIoError.NONE;
|
|
}
|
|
|
|
static int getWriteFieldsCount(MetaSyncContext ctx, IMetaStruct v)
|
|
{
|
|
if(ctx.IsMaskUsed())
|
|
return v.getWritableFieldsCount();
|
|
else
|
|
return v.getFieldsCount();
|
|
}
|
|
|
|
public static MetaSyncContext PrepareForClone<T>(ref T src) where T : IMetaStruct
|
|
{
|
|
var stream = new MemoryStream();
|
|
|
|
var ctx = new MetaSyncContext() {
|
|
is_read = false,
|
|
reader = new MsgPackDataReader(stream),
|
|
writer = new MsgPackDataWriter(stream),
|
|
opts = 0
|
|
};
|
|
|
|
Sync(ctx, ref src);
|
|
|
|
ctx.is_read = true;
|
|
stream.Position = 0;
|
|
|
|
return ctx;
|
|
}
|
|
|
|
//Shared mask utils below
|
|
|
|
public static int GetDirtyFieldsCount(long fields_mask, int fields_count)
|
|
{
|
|
int changed_fields = 0;
|
|
long ptr = 1L;
|
|
for(int i=0; i<fields_count; ++i, ptr = ptr << 1)
|
|
{
|
|
if((ptr & fields_mask) != 0)
|
|
changed_fields++;
|
|
}
|
|
return changed_fields;
|
|
}
|
|
|
|
public static void SetFieldDirty(ref long fields_mask, int field_index)
|
|
{
|
|
long diff = 1L << field_index;
|
|
fields_mask |= diff;
|
|
}
|
|
|
|
public static bool IsFieldDirty(long fields_mask, int field_index)
|
|
{
|
|
return (fields_mask & 1L << field_index) != 0;
|
|
}
|
|
|
|
public static void ClearList<T>(ref List<T> v)
|
|
{
|
|
if(v == null)
|
|
v = new List<T>();
|
|
v.Clear();
|
|
}
|
|
|
|
public static string I18NPick(string raw_val, List<string> list_val, string plural_marker, double pluralize_for_n)
|
|
{
|
|
if(raw_val.Length != 0)
|
|
return Meta.L_T(raw_val);
|
|
|
|
if(Meta.L_IsPlural(list_val, plural_marker))
|
|
return Meta.L_Pluralize(list_val, pluralize_for_n);
|
|
|
|
return Meta.L_FromList(list_val);
|
|
}
|
|
|
|
public static void Reset<T>(ref T v) where T : IMetaStruct, new()
|
|
{
|
|
if(v == null)
|
|
v = new T();
|
|
v.reset();
|
|
}
|
|
}
|
|
|
|
public class MsgPackDataWriter : IDataWriter
|
|
{
|
|
Stream stream;
|
|
MsgPackWriter io;
|
|
Stack<int> space = new Stack<int>();
|
|
|
|
public MsgPackDataWriter(Stream _stream)
|
|
{
|
|
reset(_stream);
|
|
}
|
|
|
|
public void reset(Stream _stream)
|
|
{
|
|
stream = _stream;
|
|
io = new MsgPackWriter(stream);
|
|
space.Clear();
|
|
space.Push(1);
|
|
}
|
|
|
|
MetaIoError decSpace()
|
|
{
|
|
if(space.Count == 0)
|
|
return MetaIoError.NO_SPACE_LEFT_IN_ARRAY;
|
|
|
|
int left = space.Pop();
|
|
left--;
|
|
if(left < 0)
|
|
return MetaIoError.NO_SPACE_LEFT_IN_ARRAY;
|
|
|
|
space.Push(left);
|
|
return 0;
|
|
}
|
|
|
|
public MetaIoError BeginContainer(int size)
|
|
{
|
|
MetaIoError err = decSpace();
|
|
if(err != 0)
|
|
return err;
|
|
|
|
space.Push(size);
|
|
io.WriteArrayHeader(size);
|
|
return 0;
|
|
}
|
|
|
|
public MetaIoError EndContainer()
|
|
{
|
|
if(space.Count <= 1)
|
|
return MetaIoError.ARRAY_STACK_IS_EMPTY;
|
|
|
|
int left = space.Pop();
|
|
if(left != 0)
|
|
return MetaIoError.HAS_LEFT_SPACE;
|
|
|
|
return 0;
|
|
}
|
|
|
|
public MetaIoError End()
|
|
{
|
|
if(space.Count != 1)
|
|
return MetaIoError.ARRAY_STACK_IS_EMPTY;
|
|
|
|
return 0;
|
|
}
|
|
|
|
public MetaIoError WriteI8(sbyte v)
|
|
{
|
|
io.Write(v);
|
|
return decSpace();
|
|
}
|
|
|
|
public MetaIoError WriteU8(byte v)
|
|
{
|
|
io.Write(v);
|
|
return decSpace();
|
|
}
|
|
|
|
public MetaIoError WriteI16(short v)
|
|
{
|
|
io.Write(v);
|
|
return decSpace();
|
|
}
|
|
|
|
public MetaIoError WriteU16(ushort v)
|
|
{
|
|
io.Write(v);
|
|
return decSpace();
|
|
}
|
|
|
|
public MetaIoError WriteI32(int v)
|
|
{
|
|
io.Write(v);
|
|
return decSpace();
|
|
}
|
|
|
|
public MetaIoError WriteU32(uint v)
|
|
{
|
|
io.Write(v);
|
|
return decSpace();
|
|
}
|
|
|
|
public MetaIoError WriteU64(ulong v)
|
|
{
|
|
io.Write(v);
|
|
return decSpace();
|
|
}
|
|
|
|
public MetaIoError WriteI64(long v)
|
|
{
|
|
io.Write(v);
|
|
return decSpace();
|
|
}
|
|
|
|
public MetaIoError WriteBool(bool v)
|
|
{
|
|
io.Write(v);
|
|
return decSpace();
|
|
}
|
|
|
|
public MetaIoError WriteFloat(float v)
|
|
{
|
|
io.Write(v);
|
|
return decSpace();
|
|
}
|
|
|
|
public MetaIoError WriteDouble(double v)
|
|
{
|
|
io.Write(v);
|
|
return decSpace();
|
|
}
|
|
|
|
public MetaIoError WriteString(string v)
|
|
{
|
|
if(v == null)
|
|
io.Write("");
|
|
else
|
|
io.Write(v);
|
|
|
|
return decSpace();
|
|
}
|
|
|
|
public MetaIoError WriteNil()
|
|
{
|
|
io.WriteNil();
|
|
|
|
return decSpace();
|
|
}
|
|
|
|
public MetaIoError WriteRaw(byte[] v)
|
|
{
|
|
io.Write(v);
|
|
|
|
return decSpace();
|
|
}
|
|
}
|
|
|
|
public class MsgPackDataReader : IDataReader
|
|
{
|
|
Stream stream;
|
|
MsgPackReader io;
|
|
|
|
public struct ContainerPosition
|
|
{
|
|
public int max;
|
|
public int curr;
|
|
|
|
public ContainerPosition(int length)
|
|
{
|
|
curr = 0;
|
|
max = length - 1;
|
|
}
|
|
}
|
|
|
|
Stack<ContainerPosition> stack = new Stack<ContainerPosition>();
|
|
|
|
public MsgPackDataReader(Stream _stream)
|
|
{
|
|
reset(_stream);
|
|
}
|
|
|
|
public void reset(Stream _stream)
|
|
{
|
|
stream = _stream;
|
|
stack.Clear();
|
|
io = new MsgPackReader(stream);
|
|
}
|
|
|
|
public void setPos(long pos)
|
|
{
|
|
stream.Position = pos;
|
|
stack.Clear();
|
|
}
|
|
|
|
int nextInt(ref MetaIoError err)
|
|
{
|
|
if(!ContainerPositionValid())
|
|
{
|
|
err = MetaIoError.DATA_MISSING;
|
|
return 0;
|
|
}
|
|
|
|
if(!io.Read())
|
|
{
|
|
err = MetaIoError.FAIL_READ;
|
|
return 0;
|
|
}
|
|
|
|
ContainerPositionMoveNext();
|
|
|
|
if(io.IsSigned())
|
|
return io.ValueSigned;
|
|
else if(io.IsUnsigned())
|
|
return (int)io.ValueUnsigned;
|
|
else
|
|
{
|
|
Meta.LogWarn("Got type: " + io.Type);
|
|
err = MetaIoError.TYPE_DONT_MATCH;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
uint nextUint(ref MetaIoError err)
|
|
{
|
|
if(!ContainerPositionValid())
|
|
{
|
|
err = MetaIoError.DATA_MISSING;
|
|
return 0;
|
|
}
|
|
|
|
if(!io.Read())
|
|
{
|
|
err = MetaIoError.FAIL_READ;
|
|
return 0;
|
|
}
|
|
|
|
ContainerPositionMoveNext();
|
|
|
|
if(io.IsUnsigned())
|
|
return io.ValueUnsigned;
|
|
else if(io.IsSigned())
|
|
return (uint)io.ValueSigned;
|
|
else
|
|
{
|
|
Meta.LogWarn("Got type: " + io.Type);
|
|
err = MetaIoError.TYPE_DONT_MATCH;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
bool nextBool(ref MetaIoError err)
|
|
{
|
|
if(!ContainerPositionValid())
|
|
{
|
|
err = MetaIoError.DATA_MISSING;
|
|
return false;
|
|
}
|
|
|
|
if(!io.Read())
|
|
{
|
|
err = MetaIoError.FAIL_READ;
|
|
return false;
|
|
}
|
|
|
|
ContainerPositionMoveNext();
|
|
|
|
if(io.IsBoolean())
|
|
return (bool)io.ValueBoolean;
|
|
else if(io.IsUnsigned())
|
|
return io.ValueUnsigned != 0;
|
|
else if(io.IsSigned())
|
|
return (uint)io.ValueSigned != 0;
|
|
else
|
|
{
|
|
Meta.LogWarn("Got type: " + io.Type);
|
|
err = MetaIoError.TYPE_DONT_MATCH;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
ulong nextUint64(ref MetaIoError err)
|
|
{
|
|
if(!ContainerPositionValid())
|
|
{
|
|
err = MetaIoError.DATA_MISSING;
|
|
return 0;
|
|
}
|
|
|
|
if(!io.Read())
|
|
{
|
|
err = MetaIoError.FAIL_READ;
|
|
return 0;
|
|
}
|
|
|
|
ContainerPositionMoveNext();
|
|
|
|
if(io.IsUnsigned())
|
|
return io.ValueUnsigned;
|
|
else if(io.IsSigned())
|
|
return (ulong)io.ValueSigned;
|
|
else if(io.IsUnsigned64())
|
|
return io.ValueUnsigned64;
|
|
else if(io.IsSigned64())
|
|
return (ulong)io.ValueSigned64;
|
|
else
|
|
{
|
|
Meta.LogWarn("Got type: " + io.Type);
|
|
err = MetaIoError.TYPE_DONT_MATCH;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
long nextInt64(ref MetaIoError err)
|
|
{
|
|
if(!ContainerPositionValid())
|
|
{
|
|
err = MetaIoError.DATA_MISSING;
|
|
return 0;
|
|
}
|
|
|
|
if(!io.Read())
|
|
{
|
|
err = MetaIoError.FAIL_READ;
|
|
return 0;
|
|
}
|
|
|
|
ContainerPositionMoveNext();
|
|
|
|
if(io.IsUnsigned())
|
|
return (long)io.ValueUnsigned;
|
|
else if(io.IsSigned())
|
|
return io.ValueSigned;
|
|
else if(io.IsUnsigned64())
|
|
return (long)io.ValueUnsigned64;
|
|
else if(io.IsSigned64())
|
|
return io.ValueSigned64;
|
|
else
|
|
{
|
|
Meta.LogWarn("Got type: " + io.Type);
|
|
err = MetaIoError.TYPE_DONT_MATCH;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
public MetaIoError ReadI8(ref sbyte v)
|
|
{
|
|
MetaIoError err = 0;
|
|
v = (sbyte) nextInt(ref err);
|
|
return err;
|
|
}
|
|
|
|
public MetaIoError ReadI16(ref short v)
|
|
{
|
|
MetaIoError err = 0;
|
|
v = (short) nextInt(ref err);
|
|
return err;
|
|
}
|
|
|
|
public MetaIoError ReadI32(ref int v)
|
|
{
|
|
MetaIoError err = 0;
|
|
v = nextInt(ref err);
|
|
return err;
|
|
}
|
|
|
|
public MetaIoError ReadU8(ref byte v)
|
|
{
|
|
MetaIoError err = 0;
|
|
v = (byte) nextUint(ref err);
|
|
return err;
|
|
}
|
|
|
|
public MetaIoError ReadU16(ref ushort v)
|
|
{
|
|
MetaIoError err = 0;
|
|
v = (ushort) nextUint(ref err);
|
|
return err;
|
|
}
|
|
|
|
public MetaIoError ReadU32(ref uint v)
|
|
{
|
|
MetaIoError err = 0;
|
|
v = nextUint(ref err);
|
|
return err;
|
|
}
|
|
|
|
public MetaIoError ReadU64(ref ulong v)
|
|
{
|
|
MetaIoError err = 0;
|
|
v = nextUint64(ref err);
|
|
return err;
|
|
}
|
|
|
|
public MetaIoError ReadI64(ref long v)
|
|
{
|
|
MetaIoError err = 0;
|
|
v = nextInt64(ref err);
|
|
return err;
|
|
}
|
|
|
|
public MetaIoError ReadBool(ref bool v)
|
|
{
|
|
MetaIoError err = 0;
|
|
v = nextBool(ref err);
|
|
return err;
|
|
}
|
|
|
|
public MetaIoError ReadFloat(ref float v)
|
|
{
|
|
if(!ContainerPositionValid())
|
|
return MetaIoError.DATA_MISSING;
|
|
|
|
if(!io.Read())
|
|
{
|
|
return MetaIoError.FAIL_READ;
|
|
}
|
|
|
|
if(io.IsUnsigned())
|
|
{
|
|
v = io.ValueUnsigned;
|
|
}
|
|
else if(io.IsSigned())
|
|
{
|
|
v = io.ValueSigned;
|
|
}
|
|
else
|
|
{
|
|
switch(io.Type)
|
|
{
|
|
case TypePrefixes.Float:
|
|
v = io.ValueFloat;
|
|
break;
|
|
case TypePrefixes.Double:
|
|
var tmp = io.ValueDouble;
|
|
//TODO:
|
|
//if(tmp > float.MaxValue || tmp < float.MinValue)
|
|
//{
|
|
// Meta.LogWarn("Double -> Float bad conversion: " + tmp);
|
|
// return MetaIoError.TYPE_DONT_MATCH;
|
|
//}
|
|
v = (float) tmp;
|
|
break;
|
|
default:
|
|
Meta.LogWarn("Got type: " + io.Type);
|
|
return MetaIoError.TYPE_DONT_MATCH;
|
|
}
|
|
}
|
|
ContainerPositionMoveNext();
|
|
return 0;
|
|
}
|
|
|
|
public MetaIoError ReadDouble(ref double v)
|
|
{
|
|
if(!ContainerPositionValid())
|
|
return MetaIoError.DATA_MISSING;
|
|
|
|
if(!io.Read())
|
|
{
|
|
return MetaIoError.FAIL_READ;
|
|
}
|
|
|
|
if(io.IsUnsigned())
|
|
{
|
|
v = io.ValueUnsigned;
|
|
}
|
|
else if(io.IsSigned())
|
|
{
|
|
v = io.ValueSigned;
|
|
}
|
|
else
|
|
{
|
|
switch(io.Type)
|
|
{
|
|
case TypePrefixes.Float:
|
|
v = (double) io.ValueFloat;
|
|
break;
|
|
case TypePrefixes.Double:
|
|
v = io.ValueDouble;
|
|
break;
|
|
case TypePrefixes.UInt64:
|
|
v = (double) io.ValueUnsigned64;
|
|
break;
|
|
case TypePrefixes.Int64:
|
|
v = (double) io.ValueSigned64;
|
|
break;
|
|
default:
|
|
Meta.LogWarn("Got type: " + io.Type);
|
|
return MetaIoError.TYPE_DONT_MATCH;
|
|
}
|
|
}
|
|
ContainerPositionMoveNext();
|
|
return 0;
|
|
}
|
|
|
|
public MetaIoError ReadRaw(ref byte[] v, ref int vlen)
|
|
{
|
|
if(!ContainerPositionValid())
|
|
return MetaIoError.DATA_MISSING;
|
|
|
|
if(!io.Read())
|
|
return MetaIoError.FAIL_READ;
|
|
|
|
if(!io.IsRaw())
|
|
{
|
|
Meta.LogWarn("Got type: " + io.Type);
|
|
return MetaIoError.TYPE_DONT_MATCH;
|
|
}
|
|
|
|
vlen = (int)io.Length;
|
|
if(v == null)
|
|
v = new byte[vlen];
|
|
else if(v.Length < vlen)
|
|
Array.Resize(ref v, vlen);
|
|
io.ReadValueRaw(v, 0, vlen);
|
|
ContainerPositionMoveNext();
|
|
return 0;
|
|
}
|
|
|
|
public MetaIoError ReadNil()
|
|
{
|
|
if(!ContainerPositionValid())
|
|
return MetaIoError.DATA_MISSING;
|
|
|
|
if(!io.Read())
|
|
return MetaIoError.FAIL_READ;
|
|
|
|
if(io.Type != TypePrefixes.Nil)
|
|
{
|
|
Meta.LogWarn("Got type: " + io.Type);
|
|
return MetaIoError.TYPE_DONT_MATCH;
|
|
}
|
|
|
|
ContainerPositionMoveNext();
|
|
return 0;
|
|
}
|
|
|
|
public MetaIoError ReadString(ref string v)
|
|
{
|
|
if(!ContainerPositionValid())
|
|
return MetaIoError.DATA_MISSING;
|
|
|
|
if(!io.Read())
|
|
return MetaIoError.FAIL_READ;
|
|
|
|
if(!io.IsRaw())
|
|
{
|
|
Meta.LogWarn("Got type: " + io.Type);
|
|
return MetaIoError.TYPE_DONT_MATCH;
|
|
}
|
|
|
|
//TODO: use shared buffer for strings loading
|
|
byte[] strval = new byte[io.Length];
|
|
io.ReadValueRaw(strval, 0, strval.Length);
|
|
v = System.Text.Encoding.UTF8.GetString(strval);
|
|
ContainerPositionMoveNext();
|
|
return 0;
|
|
}
|
|
|
|
public MetaIoError BeginContainer()
|
|
{
|
|
if(!ContainerPositionValid())
|
|
return MetaIoError.DATA_MISSING;
|
|
|
|
if(!io.Read())
|
|
return MetaIoError.FAIL_READ;
|
|
|
|
if(!io.IsArray())
|
|
{
|
|
Meta.LogWarn("Got type: " + io.Type);
|
|
return MetaIoError.TYPE_DONT_MATCH;
|
|
}
|
|
|
|
ContainerPosition ap = new ContainerPosition((int)io.Length);
|
|
stack.Push(ap);
|
|
return 0;
|
|
}
|
|
|
|
public MetaIoError GetContainerSize(ref int v)
|
|
{
|
|
if(!io.IsArray())
|
|
{
|
|
Meta.LogWarn("Got type: " + io.Type);
|
|
return MetaIoError.TYPE_DONT_MATCH;
|
|
}
|
|
|
|
v = (int) io.Length;
|
|
return 0;
|
|
}
|
|
|
|
void SkipField()
|
|
{
|
|
if(!io.Read())
|
|
return;
|
|
|
|
if(!io.IsArray() && !io.IsMap())
|
|
{
|
|
//NOTE: if value is a raw string we need to read all of its data
|
|
if(io.IsRaw())
|
|
io.ReadRawString();
|
|
return;
|
|
}
|
|
|
|
uint array_len = io.Length;
|
|
for(uint i=0; i<array_len; ++i)
|
|
SkipField();
|
|
}
|
|
|
|
void SkipTrailingFields()
|
|
{
|
|
while(ContainerEntriesLeft() > -1)
|
|
{
|
|
SkipField();
|
|
ContainerPositionMoveNext();
|
|
}
|
|
}
|
|
|
|
public MetaIoError EndContainer()
|
|
{
|
|
SkipTrailingFields();
|
|
stack.Pop();
|
|
ContainerPositionMoveNext();
|
|
return 0;
|
|
}
|
|
|
|
int ContainerEntriesLeft()
|
|
{
|
|
if(stack.Count == 0)
|
|
return 0;
|
|
ContainerPosition ap = stack.Peek();
|
|
return ap.max - ap.curr;
|
|
}
|
|
|
|
bool ContainerPositionValid()
|
|
{
|
|
return ContainerEntriesLeft() >= 0;
|
|
}
|
|
|
|
void ContainerPositionMoveNext()
|
|
{
|
|
if(stack.Count > 0)
|
|
{
|
|
ContainerPosition ap = stack.Pop();
|
|
ap.curr++;
|
|
stack.Push(ap);
|
|
}
|
|
}
|
|
}
|
|
|
|
} //namespace metagen
|