本文整理汇总了C#中ProtoBuf.ProtoReader.ReadFieldHeader方法的典型用法代码示例。如果您正苦于以下问题:C# ProtoReader.ReadFieldHeader方法的具体用法?C# ProtoReader.ReadFieldHeader怎么用?C# ProtoReader.ReadFieldHeader使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类ProtoBuf.ProtoReader
的用法示例。
在下文中一共展示了ProtoReader.ReadFieldHeader方法的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C#代码示例。
示例1: TestRandomDataWithReader
public void TestRandomDataWithReader()
{
var input = File.ReadAllBytes("protobuf-net.dll");
var stream = new MemoryStream(input);
stream.Seek(0, SeekOrigin.Begin);
Assert.Greater(3, 0); // I always double-check the param order
Assert.Greater(stream.Length, 0);
using (var reader = new ProtoReader(stream, null, null))
{
while (reader.ReadFieldHeader() > 0)
{
reader.SkipField();
}
}
}
示例2: ReadDecimal
public static decimal ReadDecimal(ProtoReader reader)
{
ulong num = 0uL;
uint num2 = 0u;
uint num3 = 0u;
SubItemToken token = ProtoReader.StartSubItem(reader);
int num4;
while ((num4 = reader.ReadFieldHeader()) > 0)
{
switch (num4)
{
case 1:
num = reader.ReadUInt64();
break;
case 2:
num2 = reader.ReadUInt32();
break;
case 3:
num3 = reader.ReadUInt32();
break;
default:
reader.SkipField();
break;
}
}
ProtoReader.EndSubItem(token, reader);
if (num == 0uL && num2 == 0u)
{
return 0m;
}
int lo = (int)(num & 0xFFFFFFFFL);
int mid = (int)(num >> 32 & 0xFFFFFFFFL);
int hi = (int)num2;
bool isNegative = (num3 & 1u) == 1u;
byte scale = (byte)((num3 & 510u) >> 1);
return new decimal(lo, mid, hi, isNegative, scale);
}
示例3: ReadNetObject
/// <summary>
/// Reads an *implementation specific* bundled .NET object, including (as options) type-metadata, identity/re-use, etc.
/// </summary>
public static object ReadNetObject(object value, ProtoReader source, int key, Type type, NetObjectOptions options)
{
SubItemToken token = ProtoReader.StartSubItem(source);
int fieldNumber;
int newObjectKey = -1, newTypeKey = -1, tmp;
while ((fieldNumber = source.ReadFieldHeader()) > 0)
{
switch (fieldNumber)
{
case FieldExistingObjectKey:
tmp = source.ReadInt32();
value = source.NetCache.GetKeyedObject(tmp);
break;
case FieldNewObjectKey:
newObjectKey = source.ReadInt32();
break;
case FieldExistingTypeKey:
tmp = source.ReadInt32();
type = (Type)source.NetCache.GetKeyedObject(tmp);
key = source.GetTypeKey(ref type);
break;
case FieldNewTypeKey:
newTypeKey = source.ReadInt32();
break;
case FieldTypeName:
type = source.DeserializeType(source.ReadString());
key = source.GetTypeKey(ref type);
break;
case FieldObject:
bool isString = type == typeof(string);
bool lateSet = value == null && isString;
if (value == null && !lateSet)
{
value = ((options & NetObjectOptions.UseConstructor) == 0) ? BclHelpers.GetUninitializedObject(type) : Activator.CreateInstance(type);
}
if (newObjectKey >= 0 && !lateSet)
{
source.NetCache.SetKeyedObject(newObjectKey, value);
if (newTypeKey >= 0) source.NetCache.SetKeyedObject(newTypeKey, type);
}
object oldValue = value;
if (isString)
{
value = source.ReadString();
}
else
{
value = ProtoReader.ReadTypedObject(oldValue, key, source, type);
}
if (newObjectKey >= 0 && lateSet)
{
source.NetCache.SetKeyedObject(newObjectKey, value);
if (newTypeKey >= 0) source.NetCache.SetKeyedObject(newTypeKey, type);
}
if (!lateSet && !ReferenceEquals(oldValue, value))
{
throw new ProtoException("A reference-tracked object changed reference during deserialization");
}
break;
default:
source.SkipField();
break;
}
}
ProtoReader.EndSubItem(token, source);
return value;
}
示例4: ReadGuid
public static Guid ReadGuid(ProtoReader source)
{
ulong num = 0uL;
ulong num2 = 0uL;
SubItemToken token = ProtoReader.StartSubItem(source);
int num3;
while ((num3 = source.ReadFieldHeader()) > 0)
{
int num4 = num3;
if (num4 != 1)
{
if (num4 != 2)
{
source.SkipField();
}
else
{
num2 = source.ReadUInt64();
}
}
else
{
num = source.ReadUInt64();
}
}
ProtoReader.EndSubItem(token, source);
if (num == 0uL && num2 == 0uL)
{
return Guid.Empty;
}
uint num5 = (uint)(num >> 32);
uint a = (uint)num;
uint num6 = (uint)(num2 >> 32);
uint num7 = (uint)num2;
return new Guid((int)a, (short)num5, (short)(num5 >> 16), (byte)num7, (byte)(num7 >> 8), (byte)(num7 >> 16), (byte)(num7 >> 24), (byte)num6, (byte)(num6 >> 8), (byte)(num6 >> 16), (byte)(num6 >> 24));
}
示例5: ReadGuid
/// <summary>
/// Parses a Guid from a protobuf stream
/// </summary>
public static Guid ReadGuid(ProtoReader source)
{
ulong low = 0, high = 0;
int fieldNumber;
SubItemToken token = ProtoReader.StartSubItem(source);
while ((fieldNumber = source.ReadFieldHeader()) > 0)
{
switch (fieldNumber)
{
case FieldGuidLow: low = source.ReadUInt64(); break;
case FieldGuidHigh: high = source.ReadUInt64(); break;
default: source.SkipField(); break;
}
}
ProtoReader.EndSubItem(token, source);
if(low == 0 && high == 0) return Guid.Empty;
uint a = (uint)(low >> 32), b = (uint)low, c = (uint)(high >> 32), d= (uint)high;
return new Guid((int)b, (short)a, (short)(a >> 16),
(byte)d, (byte)(d >> 8), (byte)(d >> 16), (byte)(d >> 24),
(byte)c, (byte)(c >> 8), (byte)(c >> 16), (byte)(c >> 24));
}
示例6: ReadProtobuf
public static Dictionary<int, List<object>> ReadProtobuf(Stream stream)
{
// try reading it as a protobuf
using (var reader = new ProtoReader(stream, null, null))
{
var fields = new Dictionary<int, List<object>>();
while (true)
{
int field = reader.ReadFieldHeader();
if (field == 0)
break;
object fieldValue = null;
switch (reader.WireType)
{
case WireType.Variant:
case WireType.Fixed32:
case WireType.Fixed64:
case WireType.SignedVariant:
{
try
{
fieldValue = reader.ReadInt64();
}
catch (Exception)
{
fieldValue = "Unable to read Variant (debugme)";
}
break;
}
case WireType.String:
{
try
{
fieldValue = reader.ReadString();
}
catch (Exception)
{
fieldValue = "Unable to read String (debugme)";
}
break;
}
default:
{
fieldValue = string.Format("{0} is not implemented", reader.WireType);
break;
}
}
if (!fields.ContainsKey(field))
{
fields[field] = new List<object>();
}
fields[field].Add(fieldValue);
}
if (fields.Count > 0)
return fields;
}
return null;
}
示例7: BuildBody
object BuildBody( uint realEMsg, Stream str )
{
EMsg eMsg = MsgUtil.GetMsg( realEMsg );
if ( eMsg == EMsg.ClientLogonGameServer )
eMsg = EMsg.ClientLogon; // temp hack for now
else if( eMsg == EMsg.ClientGamesPlayedWithDataBlob)
eMsg = EMsg.ClientGamesPlayed;
var protomsgType = typeof(CMClient).Assembly.GetTypes().ToList().Find(type =>
{
if (type.GetInterfaces().ToList().Find(inter => inter == typeof(IExtensible)) == null)
return false;
if (type.Name.EndsWith(eMsg.ToString()))
return true;
return false;
});
if (protomsgType != null)
{
return RuntimeTypeModel.Default.Deserialize(str, null, protomsgType);
}
// lets first find the type by checking all EMsgs we have
var msgType = typeof( CMClient ).Assembly.GetTypes().ToList().Find( type =>
{
if ( type.GetInterfaces().ToList().Find( inter => inter == typeof( ISteamSerializableMessage ) ) == null )
return false;
var gcMsg = Activator.CreateInstance( type ) as ISteamSerializableMessage;
return gcMsg.GetEMsg() == eMsg;
} );
string eMsgName = eMsg.ToString();
eMsgName = eMsgName.Replace( "Econ", "" ).Replace( "AM", "" );
// check name
if ( msgType == null )
msgType = GetSteamKitType( string.Format( "SteamKit2.Msg{0}", eMsgName ) );
if ( msgType != null )
{
var body = Activator.CreateInstance( msgType ) as ISteamSerializableMessage;
body.Deserialize( str );
return body;
}
msgType = GetSteamKitType( string.Format( "SteamKit2.CMsg{0}", eMsgName ) );
if ( msgType != null )
{
return Deserialize( msgType, str );
}
if ( eMsg == EMsg.ClientToGC || eMsg == EMsg.ClientFromGC )
{
return Serializer.Deserialize<CMsgGCClient>( str );
}
// try reading it as a protobuf
using (ProtoReader reader = new ProtoReader(str, null, null))
{
var fields = new Dictionary<int, List<object>>();
while(true)
{
int field = reader.ReadFieldHeader();
if(field == 0)
break;
object fieldValue = null;
switch (reader.WireType)
{
case WireType.Variant:
case WireType.Fixed32:
case WireType.Fixed64:
case WireType.SignedVariant:
{
try
{
fieldValue = reader.ReadInt64();
}
catch (Exception)
{
fieldValue = "Unable to read Variant (debugme)";
}
break;
}
case WireType.String:
{
try
{
//.........这里部分代码省略.........
示例8: ReadTimeSpanTicks
private static long ReadTimeSpanTicks(ProtoReader source) {
switch (source.WireType)
{
case WireType.String:
case WireType.StartGroup:
SubItemToken token = ProtoReader.StartSubItem(source);
int fieldNumber;
TimeSpanScale scale = TimeSpanScale.Days;
long value = 0;
while ((fieldNumber = source.ReadFieldHeader()) > 0)
{
switch (fieldNumber)
{
case FieldTimeSpanScale:
scale = (TimeSpanScale)source.ReadInt32();
break;
case FieldTimeSpanValue:
source.Assert(WireType.SignedVariant);
value = source.ReadInt64();
break;
default:
source.SkipField();
break;
}
}
ProtoReader.EndSubItem(token, source);
switch (scale)
{
case TimeSpanScale.Days:
return value * TimeSpan.TicksPerDay;
case TimeSpanScale.Hours:
return value * TimeSpan.TicksPerHour;
case TimeSpanScale.Minutes:
return value * TimeSpan.TicksPerMinute;
case TimeSpanScale.Seconds:
return value * TimeSpan.TicksPerSecond;
case TimeSpanScale.Milliseconds:
return value * TimeSpan.TicksPerMillisecond;
case TimeSpanScale.Ticks:
return value;
case TimeSpanScale.MinMax:
switch (value)
{
case 1: return long.MaxValue;
case -1: return long.MinValue;
default: throw new ProtoException("Unknown min/max value: " + value.ToString());
}
default:
throw new ProtoException("Unknown timescale: " + scale.ToString());
}
case WireType.Fixed64:
return source.ReadInt64();
default:
throw new ProtoException("Unexpected wire-type: " + source.WireType.ToString());
}
}
示例9: Read
/// <summary>
/// The read.
/// </summary>
/// <param name="compiledAsset">
/// The compiled asset.
/// </param>
/// <param name="protoReader">
/// The proto reader.
/// </param>
/// <returns>
/// The <see cref="CompiledAsset"/>.
/// </returns>
private static CompiledAsset Read(CompiledAsset compiledAsset, ProtoReader protoReader)
{
int num;
while ((num = protoReader.ReadFieldHeader()) > 0)
{
if (num != 1)
{
if (num != 3)
{
if (compiledAsset == null)
{
var expr_8A = new CompiledAsset();
ProtoReader.NoteObject(expr_8A, protoReader);
compiledAsset = expr_8A;
}
protoReader.SkipField();
}
else
{
if (compiledAsset == null)
{
var expr_4C = new CompiledAsset();
ProtoReader.NoteObject(expr_4C, protoReader);
compiledAsset = expr_4C;
}
PlatformData arg_63_0 = compiledAsset.PlatformData;
SubItemToken token = ProtoReader.StartSubItem(protoReader);
PlatformData arg_6F_0 = Read(arg_63_0, protoReader);
ProtoReader.EndSubItem(token, protoReader);
PlatformData platformData = arg_6F_0;
if (platformData != null)
{
compiledAsset.PlatformData = platformData;
}
}
}
else
{
if (compiledAsset == null)
{
var expr_19 = new CompiledAsset();
ProtoReader.NoteObject(expr_19, protoReader);
compiledAsset = expr_19;
}
string text = protoReader.ReadString();
if (text != null)
{
compiledAsset.Loader = text;
}
}
}
if (compiledAsset == null)
{
var expr_B2 = new CompiledAsset();
ProtoReader.NoteObject(expr_B2, protoReader);
compiledAsset = expr_B2;
}
return compiledAsset;
}
示例10: Read
private static Product Read(Product product1, ProtoReader reader1)
{
int num;
while ((num = reader1.ReadFieldHeader()) > 0)
{
switch (num)
{
case 1:
if (product1 == null)
{
product1 = new Product();
}
product1.ProductID = reader1.ReadInt32();
continue;
case 2:
if (product1 == null)
{
product1 = new Product();
}
product1.ProductName = reader1.ReadString();
continue;
case 3:
if (product1 == null)
{
product1 = new Product();
}
product1.SupplierID = new int?(reader1.ReadInt32());
continue;
}
}
return product1;
}
示例11: Read
/// <summary>
/// The read.
/// </summary>
/// <param name="mxPayload">
/// The mx payload.
/// </param>
/// <param name="protoReader">
/// The proto reader.
/// </param>
/// <returns>
/// The <see cref="MxPayload"/>.
/// </returns>
private static MxPayload Read(MxPayload mxPayload, ProtoReader protoReader)
{
int num;
while ((num = protoReader.ReadFieldHeader()) > 0)
{
if (num != 1)
{
if (mxPayload == null)
{
var expr_49 = new MxPayload();
ProtoReader.NoteObject(expr_49, protoReader);
mxPayload = expr_49;
}
protoReader.SkipField();
}
else
{
if (mxPayload == null)
{
var expr_19 = new MxPayload();
ProtoReader.NoteObject(expr_19, protoReader);
mxPayload = expr_19;
}
byte[] array = ProtoReader.AppendBytes(mxPayload.Data, protoReader);
if (array != null)
{
mxPayload.Data = array;
}
}
}
if (mxPayload == null)
{
var expr_71 = new MxPayload();
ProtoReader.NoteObject(expr_71, protoReader);
mxPayload = expr_71;
}
return mxPayload;
}
示例12: BuildBody
//.........这里部分代码省略.........
.Replace("GC", string.Empty)
.Replace("k_", string.Empty)
.Replace("ESOMsg", string.Empty)
.TrimStart('_')
.Replace("EMsg", string.Empty);
if ( typeMsgName == "Create" || typeMsgName == "Destroy" || typeMsgName == "Update" )
typeMsgName = "SingleObject";
else if ( typeMsgName == "Multiple" )
typeMsgName = "MultipleObjects";
var possibleTypes = from type in typeof( CMClient ).Assembly.GetTypes()
from typePrefix in gcMsgPossibleTypePrefixes
where type.GetInterfaces().Contains( typeof ( IExtensible ) )
where type.FullName.StartsWith( typePrefix ) && type.FullName.EndsWith( typeMsgName )
select type;
foreach ( var type in possibleTypes )
{
var streamPos = str.Position;
try
{
return Deserialize( type, str );
}
catch ( Exception )
{
str.Position = streamPos;
}
}
if (!MsgUtil.IsProtoBuf(realEMsg))
return null;
// try reading it as a protobuf
using (ProtoReader reader = new ProtoReader(str, null, null))
{
var fields = new Dictionary<int, List<object>>();
while(true)
{
int field = reader.ReadFieldHeader();
if(field == 0)
break;
object fieldValue = null;
switch (reader.WireType)
{
case WireType.Variant:
case WireType.Fixed32:
case WireType.Fixed64:
case WireType.SignedVariant:
{
try
{
fieldValue = reader.ReadInt64();
}
catch (Exception)
{
fieldValue = "Unable to read Variant (debugme)";
}
break;
}
case WireType.String:
{
try
{
fieldValue = reader.ReadString();
}
catch (Exception)
{
fieldValue = "Unable to read String (debugme)";
}
break;
}
default:
{
fieldValue = string.Format( "{0} is not implemented", reader.WireType );
break;
}
}
if ( !fields.ContainsKey( field ) )
{
fields[ field ] = new List<object>();
}
fields[ field ].Add( fieldValue );
}
if (fields.Count > 0)
return fields;
}
return null;
}
示例13: ReadSInstance
void ReadSInstance(ProtoReader reader, SInstance sInstance, CLS_Environment environment)
{
List<CLS_Content.Value> values;
List<string> keywords;
GetSortMembers(sInstance, out values, out keywords);
int fieldNumber = 0;
while ((fieldNumber = reader.ReadFieldHeader()) > 0)
{
Type memberT = values[fieldNumber - 1].type;
CLS_Content.Value memberV = values[fieldNumber - 1];
string sClassName = keywords[fieldNumber - 1];
if (memberT == null)
{
memberT = typeof(SInstance);
sClassName = ((SType)memberV.type).Name;
}
Type itemType = GetItemType(memberT);
if (itemType != null)
{
sClassName = sInstance.type.members[sClassName].type.keyword;
// 数组判断
if (memberT.IsArray)
{
string itemClass = sClassName.Substring(0, sClassName.Length - 2); // 从 xxx[] 中提取xxx
BasicList list = new BasicList();
do
{
list.Add(ReadField(reader, itemType, itemClass, environment));
} while (reader.TryReadFieldHeader(fieldNumber));
Array result = Array.CreateInstance(itemType, list.Count);
list.CopyTo(result, 0);
memberV.value = result;
}
// 列表判断
else
{
string itemClass = sClassName.Substring(5, sClassName.Length - 6); // 从 List<xxx> 中提取xxx
ICLS_Type iType = environment.GetTypeByKeywordQuiet(sClassName);
CLS_Content content = CLS_Content.NewContent(environment);
memberV.value = iType.function.New(content, m_emptyParams).value;
CLS_Content.PoolContent(content);
IList list = (IList)memberV.value;
do
{
list.Add(ReadField(reader, itemType, itemClass, environment));
} while (reader.TryReadFieldHeader(fieldNumber));
}
}
else
{
memberV.value = ReadField(reader, memberT, sClassName, environment);
}
}
}
示例14: ReadNetObject
/// <summary>
/// Reads an *implementation specific* bundled .NET object, including (as options) type-metadata, identity/re-use, etc.
/// </summary>
public static object ReadNetObject(object value, ProtoReader source, int key, Type type, NetObjectOptions options)
{
SubItemToken token = ProtoReader.StartSubItem(source);
int fieldNumber;
int newObjectKey = -1, newTypeKey = -1, tmp;
while ((fieldNumber = source.ReadFieldHeader()) > 0)
{
switch (fieldNumber)
{
case FieldExistingObjectKey:
tmp = source.ReadInt32();
value = source.NetCache.GetKeyedObject(tmp);
break;
case FieldNewObjectKey:
newObjectKey = source.ReadInt32();
break;
case FieldExistingTypeKey:
tmp = source.ReadInt32();
type = (Type)source.NetCache.GetKeyedObject(tmp);
key = source.GetTypeKey(ref type);
break;
case FieldNewTypeKey:
newTypeKey = source.ReadInt32();
break;
case FieldTypeName:
string typeName = source.ReadString();
type = source.DeserializeType(typeName);
if(type == null)
{
throw new ProtoException("Unable to resolve type: " + typeName + " (you can use the TypeModel.DynamicTypeFormatting event to provide a custom mapping)");
}
key = source.GetTypeKey(ref type);
if(key < 0) throw new InvalidOperationException("Dynamic type is not a contract-type: " + type.Name);
break;
case FieldObject:
bool isString = type == typeof(string);
bool lateSet = value == null && isString;
if (value == null && !lateSet)
{
try
{
value = ((options & NetObjectOptions.UseConstructor) == 0)
? BclHelpers.GetUninitializedObject(type)
: (type.IsArray || type.IsInterface ? null : Activator.CreateInstance(type, true));
} catch (Exception ex)
{
throw new ProtoException("Unable to create type " + (type == null ? "<null>" : type.FullName) + ": " + ex.Message, ex);
}
}
if (newObjectKey >= 0 && !lateSet)
{
source.NetCache.SetKeyedObject(newObjectKey, value);
if (newTypeKey >= 0) source.NetCache.SetKeyedObject(newTypeKey, type);
}
object oldValue = value;
if (isString)
{
value = source.ReadString();
}
else
{
value = ProtoReader.ReadTypedObject(oldValue, key, source, type);
}
if (newObjectKey >= 0 && lateSet)
{
source.NetCache.SetKeyedObject(newObjectKey, value);
if (newTypeKey >= 0) source.NetCache.SetKeyedObject(newTypeKey, type);
}
if (newObjectKey >= 0 && !lateSet && !ReferenceEquals(oldValue, value) && type.FullName.StartsWith("System.Collections.Generic.Dictionary`2"))
{
throw new ProtoException("A reference-tracked object changed reference during deserialization");
}
if (newObjectKey < 0 && newTypeKey >= 0)
{ // have a new type, but not a new object
source.NetCache.SetKeyedObject(newTypeKey, type);
}
break;
default:
source.SkipField();
break;
}
}
if(newObjectKey >= 0 && (options & NetObjectOptions.AsReference) == 0)
{
throw new ProtoException("Object key in input stream, but reference-tracking was not expected");
}
ProtoReader.EndSubItem(token, source);
return value;
}
示例15: ReadNetObject
public static object ReadNetObject(object value, ProtoReader source, int key, Type type, BclHelpers.NetObjectOptions options)
{
SubItemToken token = ProtoReader.StartSubItem(source);
int num = -1;
int num2 = -1;
int num3;
while ((num3 = source.ReadFieldHeader()) > 0)
{
switch (num3)
{
case 1:
{
int key2 = source.ReadInt32();
value = source.NetCache.GetKeyedObject(key2);
continue;
}
case 2:
num = source.ReadInt32();
continue;
case 3:
{
int key2 = source.ReadInt32();
type = (Type)source.NetCache.GetKeyedObject(key2);
key = source.GetTypeKey(ref type);
continue;
}
case 4:
num2 = source.ReadInt32();
continue;
case 8:
{
string text = source.ReadString();
type = source.DeserializeType(text);
if (type == null)
{
throw new ProtoException("Unable to resolve type: " + text + " (you can use the TypeModel.DynamicTypeFormatting event to provide a custom mapping)");
}
if (type == typeof(string))
{
key = -1;
}
else
{
key = source.GetTypeKey(ref type);
if (key < 0)
{
throw new InvalidOperationException("Dynamic type is not a contract-type: " + type.Name);
}
}
continue;
}
case 10:
{
bool flag = type == typeof(string);
bool flag2 = value == null;
bool flag3 = flag2 && (flag || (byte)(options & BclHelpers.NetObjectOptions.LateSet) != 0);
if (num >= 0 && !flag3)
{
if (value == null)
{
source.TrapNextObject(num);
}
else
{
source.NetCache.SetKeyedObject(num, value);
}
if (num2 >= 0)
{
source.NetCache.SetKeyedObject(num2, type);
}
}
object obj = value;
if (flag)
{
value = source.ReadString();
}
else
{
value = ProtoReader.ReadTypedObject(obj, key, source, type);
}
if (num >= 0)
{
if (flag2 && !flag3)
{
obj = source.NetCache.GetKeyedObject(num);
}
if (flag3)
{
source.NetCache.SetKeyedObject(num, value);
if (num2 >= 0)
{
source.NetCache.SetKeyedObject(num2, type);
}
}
}
if (num >= 0 && !flag3 && !object.ReferenceEquals(obj, value))
{
throw new ProtoException("A reference-tracked object changed reference during deserialization");
}
if (num < 0 && num2 >= 0)
//.........这里部分代码省略.........